PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.9.1
Secure Custom Fields v6.9.1
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / assets / build / js / acf-input.js
secure-custom-fields / assets / build / js Last commit date
commands 1 week ago pro 1 week ago acf-escaped-html-notice.asset.php 1 year ago acf-escaped-html-notice.js 1 year ago acf-escaped-html-notice.js.map 1 year ago acf-escaped-html-notice.min.asset.php 7 months ago acf-escaped-html-notice.min.js 7 months ago acf-field-group.asset.php 3 months ago acf-field-group.js 3 months ago acf-field-group.js.map 3 months ago acf-field-group.min.asset.php 3 months ago acf-field-group.min.js 3 months ago acf-input.asset.php 1 week ago acf-input.js 1 week ago acf-input.js.map 1 week ago acf-input.min.asset.php 1 week ago acf-input.min.js 1 week ago acf-internal-post-type.asset.php 7 months ago acf-internal-post-type.js 7 months ago acf-internal-post-type.js.map 7 months ago acf-internal-post-type.min.asset.php 7 months ago acf-internal-post-type.min.js 7 months ago acf.asset.php 7 months ago acf.js 7 months ago acf.js.map 7 months ago acf.min.asset.php 7 months ago acf.min.js 7 months ago index.php 1 year ago scf-bindings.asset.php 1 week ago scf-bindings.js 1 week ago scf-bindings.js.map 1 week ago scf-bindings.min.asset.php 1 week ago scf-bindings.min.js 1 week ago
acf-input.js
12194 lines
1 /******/ (() => { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ "./assets/src/js/_acf-compatibility.js":
5 /*!*********************************************!*\
6 !*** ./assets/src/js/_acf-compatibility.js ***!
7 \*********************************************/
8 /***/ (() => {
9
10 (function ($, undefined) {
11 /**
12 * acf.newCompatibility
13 *
14 * Inserts a new __proto__ object compatibility layer
15 *
16 * @date 15/2/18
17 * @since ACF 5.6.9
18 *
19 * @param object instance The object to modify.
20 * @param object compatibilty Optional. The compatibility layer.
21 * @return object compatibilty
22 */
23
24 acf.newCompatibility = function (instance, compatibilty) {
25 // defaults
26 compatibilty = compatibilty || {};
27
28 // inherit __proto_-
29 compatibilty.__proto__ = instance.__proto__;
30
31 // inject
32 instance.__proto__ = compatibilty;
33
34 // reference
35 instance.compatibility = compatibilty;
36
37 // return
38 return compatibilty;
39 };
40
41 /**
42 * acf.getCompatibility
43 *
44 * Returns the compatibility layer for a given instance
45 *
46 * @date 13/3/18
47 * @since ACF 5.6.9
48 *
49 * @param object instance The object to look in.
50 * @return object|null compatibility The compatibility object or null on failure.
51 */
52
53 acf.getCompatibility = function (instance) {
54 return instance.compatibility || null;
55 };
56
57 /**
58 * acf (compatibility)
59 *
60 * Compatibility layer for the acf object
61 *
62 * @date 15/2/18
63 * @since ACF 5.6.9
64 *
65 * @param void
66 * @return void
67 */
68
69 var _acf = acf.newCompatibility(acf, {
70 // storage
71 l10n: {},
72 o: {},
73 fields: {},
74 // changed function names
75 update: acf.set,
76 add_action: acf.addAction,
77 remove_action: acf.removeAction,
78 do_action: acf.doAction,
79 add_filter: acf.addFilter,
80 remove_filter: acf.removeFilter,
81 apply_filters: acf.applyFilters,
82 parse_args: acf.parseArgs,
83 disable_el: acf.disable,
84 disable_form: acf.disable,
85 enable_el: acf.enable,
86 enable_form: acf.enable,
87 update_user_setting: acf.updateUserSetting,
88 prepare_for_ajax: acf.prepareForAjax,
89 is_ajax_success: acf.isAjaxSuccess,
90 remove_el: acf.remove,
91 remove_tr: acf.remove,
92 str_replace: acf.strReplace,
93 render_select: acf.renderSelect,
94 get_uniqid: acf.uniqid,
95 serialize_form: acf.serialize,
96 esc_html: acf.strEscape,
97 str_sanitize: acf.strSanitize
98 });
99 _acf._e = function (k1, k2) {
100 // defaults
101 k1 = k1 || '';
102 k2 = k2 || '';
103
104 // compatibility
105 var compatKey = k2 ? k1 + '.' + k2 : k1;
106 var compats = {
107 'image.select': 'Select Image',
108 'image.edit': 'Edit Image',
109 'image.update': 'Update Image'
110 };
111 if (compats[compatKey]) {
112 return acf.__(compats[compatKey]);
113 }
114
115 // try k1
116 var string = this.l10n[k1] || '';
117
118 // try k2
119 if (k2) {
120 string = string[k2] || '';
121 }
122
123 // return
124 return string;
125 };
126 _acf.get_selector = function (s) {
127 // vars
128 var selector = '.acf-field';
129
130 // bail early if no search
131 if (!s) {
132 return selector;
133 }
134
135 // compatibility with object
136 if ($.isPlainObject(s)) {
137 if ($.isEmptyObject(s)) {
138 return selector;
139 } else {
140 for (var k in s) {
141 s = s[k];
142 break;
143 }
144 }
145 }
146
147 // append
148 selector += '-' + s;
149
150 // replace underscores (split/join replaces all and is faster than regex!)
151 selector = acf.strReplace('_', '-', selector);
152
153 // remove potential double up
154 selector = acf.strReplace('field-field-', 'field-', selector);
155
156 // return
157 return selector;
158 };
159 _acf.get_fields = function (s, $el, all) {
160 // args
161 var args = {
162 is: s || '',
163 parent: $el || false,
164 suppressFilters: all || false
165 };
166
167 // change 'field_123' to '.acf-field-123'
168 if (args.is) {
169 args.is = this.get_selector(args.is);
170 }
171
172 // return
173 return acf.findFields(args);
174 };
175 _acf.get_field = function (s, $el) {
176 // get fields
177 var $fields = this.get_fields.apply(this, arguments);
178
179 // return
180 if ($fields.length) {
181 return $fields.first();
182 } else {
183 return false;
184 }
185 };
186 _acf.get_closest_field = function ($el, s) {
187 return $el.closest(this.get_selector(s));
188 };
189 _acf.get_field_wrap = function ($el) {
190 return $el.closest(this.get_selector());
191 };
192 _acf.get_field_key = function ($field) {
193 return $field.data('key');
194 };
195 _acf.get_field_type = function ($field) {
196 return $field.data('type');
197 };
198 _acf.get_data = function ($el, defaults) {
199 return acf.parseArgs($el.data(), defaults);
200 };
201 _acf.maybe_get = function (obj, key, value) {
202 // default
203 if (value === undefined) {
204 value = null;
205 }
206
207 // get keys
208 keys = String(key).split('.');
209
210 // acf.isget
211 for (var i = 0; i < keys.length; i++) {
212 if (!obj.hasOwnProperty(keys[i])) {
213 return value;
214 }
215 obj = obj[keys[i]];
216 }
217 return obj;
218 };
219
220 /**
221 * hooks
222 *
223 * Modify add_action and add_filter functions to add compatibility with changed $field parameter
224 * Using the acf.add_action() or acf.add_filter() functions will interpret new field parameters as jQuery $field
225 *
226 * @date 12/5/18
227 * @since ACF 5.6.9
228 *
229 * @param void
230 * @return void
231 */
232
233 var compatibleArgument = function (arg) {
234 return arg instanceof acf.Field ? arg.$el : arg;
235 };
236 var compatibleArguments = function (args) {
237 return acf.arrayArgs(args).map(compatibleArgument);
238 };
239 var compatibleCallback = function (origCallback) {
240 return function () {
241 // convert to compatible arguments
242 if (arguments.length) {
243 var args = compatibleArguments(arguments);
244
245 // add default argument for 'ready', 'append' and 'load' events
246 } else {
247 var args = [$(document)];
248 }
249
250 // return
251 return origCallback.apply(this, args);
252 };
253 };
254 _acf.add_action = function (action, callback, priority, context) {
255 // handle multiple actions
256 var actions = action.split(' ');
257 var length = actions.length;
258 if (length > 1) {
259 for (var i = 0; i < length; i++) {
260 action = actions[i];
261 _acf.add_action.apply(this, arguments);
262 }
263 return this;
264 }
265
266 // single
267 var callback = compatibleCallback(callback);
268 return acf.addAction.apply(this, arguments);
269 };
270 _acf.add_filter = function (action, callback, priority, context) {
271 var callback = compatibleCallback(callback);
272 return acf.addFilter.apply(this, arguments);
273 };
274
275 /*
276 * acf.model
277 *
278 * This model acts as a scaffold for action.event driven modules
279 *
280 * @type object
281 * @date 8/09/2014
282 * @since ACF 5.0.0
283 *
284 * @param (object)
285 * @return (object)
286 */
287
288 _acf.model = {
289 actions: {},
290 filters: {},
291 events: {},
292 extend: function (args) {
293 // extend
294 var model = $.extend({}, this, args);
295
296 // setup actions
297 $.each(model.actions, function (name, callback) {
298 model._add_action(name, callback);
299 });
300
301 // setup filters
302 $.each(model.filters, function (name, callback) {
303 model._add_filter(name, callback);
304 });
305
306 // setup events
307 $.each(model.events, function (name, callback) {
308 model._add_event(name, callback);
309 });
310
311 // return
312 return model;
313 },
314 _add_action: function (name, callback) {
315 // split
316 var model = this,
317 data = name.split(' ');
318
319 // add missing priority
320 var name = data[0] || '',
321 priority = data[1] || 10;
322
323 // add action
324 acf.add_action(name, model[callback], priority, model);
325 },
326 _add_filter: function (name, callback) {
327 // split
328 var model = this,
329 data = name.split(' ');
330
331 // add missing priority
332 var name = data[0] || '',
333 priority = data[1] || 10;
334
335 // add action
336 acf.add_filter(name, model[callback], priority, model);
337 },
338 _add_event: function (name, callback) {
339 // vars
340 var model = this,
341 i = name.indexOf(' '),
342 event = i > 0 ? name.substr(0, i) : name,
343 selector = i > 0 ? name.substr(i + 1) : '';
344
345 // event
346 var fn = function (e) {
347 // append $el to event object
348 e.$el = $(this);
349
350 // append $field to event object (used in field group)
351 if (acf.field_group) {
352 e.$field = e.$el.closest('.acf-field-object');
353 }
354
355 // event
356 if (typeof model.event === 'function') {
357 e = model.event(e);
358 }
359
360 // callback
361 model[callback].apply(model, arguments);
362 };
363
364 // add event
365 if (selector) {
366 $(document).on(event, selector, fn);
367 } else {
368 $(document).on(event, fn);
369 }
370 },
371 get: function (name, value) {
372 // defaults
373 value = value || null;
374
375 // get
376 if (typeof this[name] !== 'undefined') {
377 value = this[name];
378 }
379
380 // return
381 return value;
382 },
383 set: function (name, value) {
384 // set
385 this[name] = value;
386
387 // function for 3rd party
388 if (typeof this['_set_' + name] === 'function') {
389 this['_set_' + name].apply(this);
390 }
391
392 // return for chaining
393 return this;
394 }
395 };
396
397 /*
398 * field
399 *
400 * This model sets up many of the field's interactions
401 *
402 * @type function
403 * @date 21/02/2014
404 * @since ACF 3.5.1
405 *
406 * @param n/a
407 * @return n/a
408 */
409
410 _acf.field = acf.model.extend({
411 type: '',
412 o: {},
413 $field: null,
414 _add_action: function (name, callback) {
415 // vars
416 var model = this;
417
418 // update name
419 name = name + '_field/type=' + model.type;
420
421 // add action
422 acf.add_action(name, function ($field) {
423 // focus
424 model.set('$field', $field);
425
426 // callback
427 model[callback].apply(model, arguments);
428 });
429 },
430 _add_filter: function (name, callback) {
431 // vars
432 var model = this;
433
434 // update name
435 name = name + '_field/type=' + model.type;
436
437 // add action
438 acf.add_filter(name, function ($field) {
439 // focus
440 model.set('$field', $field);
441
442 // callback
443 model[callback].apply(model, arguments);
444 });
445 },
446 _add_event: function (name, callback) {
447 // vars
448 var model = this,
449 event = name.substr(0, name.indexOf(' ')),
450 selector = name.substr(name.indexOf(' ') + 1),
451 context = acf.get_selector(model.type);
452
453 // add event
454 $(document).on(event, context + ' ' + selector, function (e) {
455 // vars
456 var $el = $(this);
457 var $field = acf.get_closest_field($el, model.type);
458
459 // bail early if no field
460 if (!$field.length) return;
461
462 // focus
463 if (!$field.is(model.$field)) {
464 model.set('$field', $field);
465 }
466
467 // append to event
468 e.$el = $el;
469 e.$field = $field;
470
471 // callback
472 model[callback].apply(model, [e]);
473 });
474 },
475 _set_$field: function () {
476 // callback
477 if (typeof this.focus === 'function') {
478 this.focus();
479 }
480 },
481 // depreciated
482 doFocus: function ($field) {
483 return this.set('$field', $field);
484 }
485 });
486
487 /**
488 * validation
489 *
490 * description
491 *
492 * @date 15/2/18
493 * @since ACF 5.6.9
494 *
495 * @param type $var Description. Default.
496 * @return type Description.
497 */
498
499 var _validation = acf.newCompatibility(acf.validation, {
500 remove_error: function ($field) {
501 acf.getField($field).removeError();
502 },
503 add_warning: function ($field, message) {
504 acf.getField($field).showNotice({
505 text: message,
506 type: 'warning',
507 timeout: 1000
508 });
509 },
510 fetch: acf.validateForm,
511 enableSubmit: acf.enableSubmit,
512 disableSubmit: acf.disableSubmit,
513 showSpinner: acf.showSpinner,
514 hideSpinner: acf.hideSpinner,
515 unlockForm: acf.unlockForm,
516 lockForm: acf.lockForm
517 });
518
519 /**
520 * tooltip
521 *
522 * description
523 *
524 * @date 15/2/18
525 * @since ACF 5.6.9
526 *
527 * @param type $var Description. Default.
528 * @return type Description.
529 */
530
531 _acf.tooltip = {
532 tooltip: function (text, $el) {
533 var tooltip = acf.newTooltip({
534 text: text,
535 target: $el
536 });
537
538 // return
539 return tooltip.$el;
540 },
541 temp: function (text, $el) {
542 var tooltip = acf.newTooltip({
543 text: text,
544 target: $el,
545 timeout: 250
546 });
547 },
548 confirm: function ($el, callback, text, button_y, button_n) {
549 var tooltip = acf.newTooltip({
550 confirm: true,
551 text: text,
552 target: $el,
553 confirm: function () {
554 callback(true);
555 },
556 cancel: function () {
557 callback(false);
558 }
559 });
560 },
561 confirm_remove: function ($el, callback) {
562 var tooltip = acf.newTooltip({
563 confirmRemove: true,
564 target: $el,
565 confirm: function () {
566 callback(true);
567 },
568 cancel: function () {
569 callback(false);
570 }
571 });
572 }
573 };
574
575 /**
576 * tooltip
577 *
578 * description
579 *
580 * @date 15/2/18
581 * @since ACF 5.6.9
582 *
583 * @param type $var Description. Default.
584 * @return type Description.
585 */
586
587 _acf.media = new acf.Model({
588 activeFrame: false,
589 actions: {
590 new_media_popup: 'onNewMediaPopup'
591 },
592 frame: function () {
593 return this.activeFrame;
594 },
595 onNewMediaPopup: function (popup) {
596 this.activeFrame = popup.frame;
597 },
598 popup: function (props) {
599 // update props
600 if (props.mime_types) {
601 props.allowedTypes = props.mime_types;
602 }
603 if (props.id) {
604 props.attachment = props.id;
605 }
606
607 // new
608 var popup = acf.newMediaPopup(props);
609
610 // append
611 /*
612 if( props.selected ) {
613 popup.selected = props.selected;
614 }
615 */
616
617 // return
618 return popup.frame;
619 }
620 });
621
622 /**
623 * Select2
624 *
625 * description
626 *
627 * @date 11/6/18
628 * @since ACF 5.6.9
629 *
630 * @param type $var Description. Default.
631 * @return type Description.
632 */
633
634 _acf.select2 = {
635 init: function ($select, args, $field) {
636 // compatible args
637 if (args.allow_null) {
638 args.allowNull = args.allow_null;
639 }
640 if (args.ajax_action) {
641 args.ajaxAction = args.ajax_action;
642 }
643 if ($field) {
644 args.field = acf.getField($field);
645 }
646
647 // return
648 return acf.newSelect2($select, args);
649 },
650 destroy: function ($select) {
651 return acf.getInstance($select).destroy();
652 }
653 };
654
655 /**
656 * postbox
657 *
658 * description
659 *
660 * @date 11/6/18
661 * @since ACF 5.6.9
662 *
663 * @param type $var Description. Default.
664 * @return type Description.
665 */
666
667 _acf.postbox = {
668 render: function (args) {
669 // compatible args
670 if (args.edit_url) {
671 args.editLink = args.edit_url;
672 }
673 if (args.edit_title) {
674 args.editTitle = args.edit_title;
675 }
676
677 // return
678 return acf.newPostbox(args);
679 }
680 };
681
682 /**
683 * acf.screen
684 *
685 * description
686 *
687 * @date 11/6/18
688 * @since ACF 5.6.9
689 *
690 * @param type $var Description. Default.
691 * @return type Description.
692 */
693
694 acf.newCompatibility(acf.screen, {
695 update: function () {
696 return this.set.apply(this, arguments);
697 },
698 fetch: acf.screen.check
699 });
700 _acf.ajax = acf.screen;
701 })(jQuery);
702
703 /***/ }),
704
705 /***/ "./assets/src/js/_acf-condition-types.js":
706 /*!***********************************************!*\
707 !*** ./assets/src/js/_acf-condition-types.js ***!
708 \***********************************************/
709 /***/ (() => {
710
711 (function ($, undefined) {
712 const __ = acf.__;
713 const parseString = function (val) {
714 return val ? '' + val : '';
715 };
716 const isEqualTo = function (v1, v2) {
717 return parseString(v1).toLowerCase() === parseString(v2).toLowerCase();
718 };
719
720 /**
721 * Checks if rule and selection are equal numbers.
722 *
723 * @param {string} v1 - The rule value to expect.
724 * @param {number|string|Array} v2 - The selected value to compare.
725 * @returns {boolean} Returns true if the values are equal numbers, otherwise returns false.
726 */
727 const isEqualToNumber = function (v1, v2) {
728 if (v2 instanceof Array) {
729 return v2.length === 1 && isEqualToNumber(v1, v2[0]);
730 }
731 return parseFloat(v1) === parseFloat(v2);
732 };
733 const isGreaterThan = function (v1, v2) {
734 return parseFloat(v1) > parseFloat(v2);
735 };
736 const isLessThan = function (v1, v2) {
737 return parseFloat(v1) < parseFloat(v2);
738 };
739 const inArray = function (v1, array) {
740 // cast all values as string
741 array = array.map(function (v2) {
742 return parseString(v2);
743 });
744 return array.indexOf(v1) > -1;
745 };
746 const containsString = function (haystack, needle) {
747 return parseString(haystack).indexOf(parseString(needle)) > -1;
748 };
749 const matchesPattern = function (v1, pattern) {
750 const regexp = new RegExp(parseString(pattern), 'gi');
751 return parseString(v1).match(regexp);
752 };
753 const conditionalSelect2 = function (field, type) {
754 const $select = $('<select></select>');
755 let queryAction = `acf/fields/${type}/query`;
756 if (type === 'user') {
757 queryAction = 'acf/ajax/query_users';
758 }
759 const ajaxData = {
760 action: queryAction,
761 field_key: field.data.key,
762 s: '',
763 type: field.data.key
764 };
765 const typeAttr = acf.escAttr(type);
766 const template = function (selection) {
767 return `<span class="acf-${typeAttr}-select-name acf-conditional-select-name">` + acf.strEscape(selection.text) + '</span>';
768 };
769 const resultsTemplate = function (results) {
770 let classes = results.text.startsWith('- ') ? `acf-${typeAttr}-select-name acf-${typeAttr}-select-sub-item` : `acf-${typeAttr}-select-name`;
771 return '<span class="' + classes + '">' + acf.strEscape(results.text) + '</span>' + `<span class="acf-${typeAttr}-select-id acf-conditional-select-id">` + (results.id ? results.id : '') + '</span>';
772 };
773 const select2Props = {
774 field: false,
775 ajax: true,
776 ajaxAction: queryAction,
777 ajaxData: function (data) {
778 ajaxData.paged = data.paged;
779 ajaxData.s = data.s;
780 ajaxData.conditional_logic = true;
781 ajaxData.include = $.isNumeric(data.s) ? Number(data.s) : '';
782 return acf.prepareForAjax(ajaxData);
783 },
784 escapeMarkup: function (markup) {
785 return acf.escHtml(markup);
786 },
787 templateSelection: template,
788 templateResult: resultsTemplate
789 };
790 $select.data('acfSelect2Props', select2Props);
791 return $select;
792 };
793 /**
794 * Adds condition for Page Link having Page Link equal to.
795 *
796 * @since ACF 6.3
797 */
798 const HasPageLink = acf.Condition.extend({
799 type: 'hasPageLink',
800 operator: '==',
801 label: __('Page is equal to'),
802 fieldTypes: ['page_link'],
803 match: function (rule, field) {
804 return isEqualTo(rule.value, field.val());
805 },
806 choices: function (fieldObject) {
807 return conditionalSelect2(fieldObject, 'page_link');
808 }
809 });
810 acf.registerConditionType(HasPageLink);
811
812 /**
813 * Adds condition for Page Link not equal to.
814 *
815 * @since ACF 6.3
816 */
817 const HasPageLinkNotEqual = acf.Condition.extend({
818 type: 'hasPageLinkNotEqual',
819 operator: '!==',
820 label: __('Page is not equal to'),
821 fieldTypes: ['page_link'],
822 match: function (rule, field) {
823 return !isEqualTo(rule.value, field.val());
824 },
825 choices: function (fieldObject) {
826 return conditionalSelect2(fieldObject, 'page_link');
827 }
828 });
829 acf.registerConditionType(HasPageLinkNotEqual);
830
831 /**
832 * Adds condition for Page Link containing a specific Page Link.
833 *
834 * @since ACF 6.3
835 */
836 const containsPageLink = acf.Condition.extend({
837 type: 'containsPageLink',
838 operator: '==contains',
839 label: __('Pages contain'),
840 fieldTypes: ['page_link'],
841 match: function (rule, field) {
842 const val = field.val();
843 const ruleVal = rule.value;
844 let match = false;
845 if (val instanceof Array) {
846 match = val.includes(ruleVal);
847 } else {
848 match = val === ruleVal;
849 }
850 return match;
851 },
852 choices: function (fieldObject) {
853 return conditionalSelect2(fieldObject, 'page_link');
854 }
855 });
856 acf.registerConditionType(containsPageLink);
857
858 /**
859 * Adds condition for Page Link not containing a specific Page Link.
860 *
861 * @since ACF 6.3
862 */
863 const containsNotPageLink = acf.Condition.extend({
864 type: 'containsNotPageLink',
865 operator: '!=contains',
866 label: __('Pages do not contain'),
867 fieldTypes: ['page_link'],
868 match: function (rule, field) {
869 const val = field.val();
870 const ruleVal = rule.value;
871 let match = true;
872 if (val instanceof Array) {
873 match = !val.includes(ruleVal);
874 } else {
875 match = val !== ruleVal;
876 }
877 return match;
878 },
879 choices: function (fieldObject) {
880 return conditionalSelect2(fieldObject, 'page_link');
881 }
882 });
883 acf.registerConditionType(containsNotPageLink);
884
885 /**
886 * Adds condition for when any page link is selected.
887 *
888 * @since ACF 6.3
889 */
890 const HasAnyPageLink = acf.Condition.extend({
891 type: 'hasAnyPageLink',
892 operator: '!=empty',
893 label: __('Has any page selected'),
894 fieldTypes: ['page_link'],
895 match: function (rule, field) {
896 let val = field.val();
897 if (val instanceof Array) {
898 val = val.length;
899 }
900 return !!val;
901 },
902 choices: function () {
903 return '<input type="text" disabled />';
904 }
905 });
906 acf.registerConditionType(HasAnyPageLink);
907
908 /**
909 * Adds condition for when no page link is selected.
910 *
911 * @since ACF 6.3
912 */
913 const HasNoPageLink = acf.Condition.extend({
914 type: 'hasNoPageLink',
915 operator: '==empty',
916 label: __('Has no page selected'),
917 fieldTypes: ['page_link'],
918 match: function (rule, field) {
919 let val = field.val();
920 if (val instanceof Array) {
921 val = val.length;
922 }
923 return !val;
924 },
925 choices: function () {
926 return '<input type="text" disabled />';
927 }
928 });
929 acf.registerConditionType(HasNoPageLink);
930
931 /**
932 * Adds condition for user field having user equal to.
933 *
934 * @since ACF 6.3
935 */
936 const HasUser = acf.Condition.extend({
937 type: 'hasUser',
938 operator: '==',
939 label: __('User is equal to'),
940 fieldTypes: ['user'],
941 match: function (rule, field) {
942 return isEqualToNumber(rule.value, field.val());
943 },
944 choices: function (fieldObject) {
945 return conditionalSelect2(fieldObject, 'user');
946 }
947 });
948 acf.registerConditionType(HasUser);
949
950 /**
951 * Adds condition for user field having user not equal to.
952 *
953 * @since ACF 6.3
954 */
955 const HasUserNotEqual = acf.Condition.extend({
956 type: 'hasUserNotEqual',
957 operator: '!==',
958 label: __('User is not equal to'),
959 fieldTypes: ['user'],
960 match: function (rule, field) {
961 return !isEqualToNumber(rule.value, field.val());
962 },
963 choices: function (fieldObject) {
964 return conditionalSelect2(fieldObject, 'user');
965 }
966 });
967 acf.registerConditionType(HasUserNotEqual);
968
969 /**
970 * Adds condition for user field containing a specific user.
971 *
972 * @since ACF 6.3
973 */
974 const containsUser = acf.Condition.extend({
975 type: 'containsUser',
976 operator: '==contains',
977 label: __('Users contain'),
978 fieldTypes: ['user'],
979 match: function (rule, field) {
980 const val = field.val();
981 const ruleVal = rule.value;
982 let match = false;
983 if (val instanceof Array) {
984 match = val.includes(ruleVal);
985 } else {
986 match = val === ruleVal;
987 }
988 return match;
989 },
990 choices: function (fieldObject) {
991 return conditionalSelect2(fieldObject, 'user');
992 }
993 });
994 acf.registerConditionType(containsUser);
995
996 /**
997 * Adds condition for user field not containing a specific user.
998 *
999 * @since ACF 6.3
1000 */
1001 const containsNotUser = acf.Condition.extend({
1002 type: 'containsNotUser',
1003 operator: '!=contains',
1004 label: __('Users do not contain'),
1005 fieldTypes: ['user'],
1006 match: function (rule, field) {
1007 const val = field.val();
1008 const ruleVal = rule.value;
1009 let match = true;
1010 if (val instanceof Array) {
1011 match = !val.includes(ruleVal);
1012 } else {
1013 match = !val === ruleVal;
1014 }
1015 },
1016 choices: function (fieldObject) {
1017 return conditionalSelect2(fieldObject, 'user');
1018 }
1019 });
1020 acf.registerConditionType(containsNotUser);
1021
1022 /**
1023 * Adds condition for when any user is selected.
1024 *
1025 * @since ACF 6.3
1026 */
1027 const HasAnyUser = acf.Condition.extend({
1028 type: 'hasAnyUser',
1029 operator: '!=empty',
1030 label: __('Has any user selected'),
1031 fieldTypes: ['user'],
1032 match: function (rule, field) {
1033 let val = field.val();
1034 if (val instanceof Array) {
1035 val = val.length;
1036 }
1037 return !!val;
1038 },
1039 choices: function () {
1040 return '<input type="text" disabled />';
1041 }
1042 });
1043 acf.registerConditionType(HasAnyUser);
1044
1045 /**
1046 * Adds condition for when no user is selected.
1047 *
1048 * @since ACF 6.3
1049 */
1050 const HasNoUser = acf.Condition.extend({
1051 type: 'hasNoUser',
1052 operator: '==empty',
1053 label: __('Has no user selected'),
1054 fieldTypes: ['user'],
1055 match: function (rule, field) {
1056 let val = field.val();
1057 if (val instanceof Array) {
1058 val = val.length;
1059 }
1060 return !val;
1061 },
1062 choices: function () {
1063 return '<input type="text" disabled />';
1064 }
1065 });
1066 acf.registerConditionType(HasNoUser);
1067
1068 /**
1069 * Adds condition for Relationship having Relationship equal to.
1070 *
1071 * @since ACF 6.3
1072 */
1073 const HasRelationship = acf.Condition.extend({
1074 type: 'hasRelationship',
1075 operator: '==',
1076 label: __('Relationship is equal to'),
1077 fieldTypes: ['relationship'],
1078 match: function (rule, field) {
1079 return isEqualToNumber(rule.value, field.val());
1080 },
1081 choices: function (fieldObject) {
1082 return conditionalSelect2(fieldObject, 'relationship');
1083 }
1084 });
1085 acf.registerConditionType(HasRelationship);
1086
1087 /**
1088 * Adds condition for selection having Relationship not equal to.
1089 *
1090 * @since ACF 6.3
1091 */
1092 const HasRelationshipNotEqual = acf.Condition.extend({
1093 type: 'hasRelationshipNotEqual',
1094 operator: '!==',
1095 label: __('Relationship is not equal to'),
1096 fieldTypes: ['relationship'],
1097 match: function (rule, field) {
1098 return !isEqualToNumber(rule.value, field.val());
1099 },
1100 choices: function (fieldObject) {
1101 return conditionalSelect2(fieldObject, 'relationship');
1102 }
1103 });
1104 acf.registerConditionType(HasRelationshipNotEqual);
1105
1106 /**
1107 * Adds condition for Relationship containing a specific Relationship.
1108 *
1109 * @since ACF 6.3
1110 */
1111 const containsRelationship = acf.Condition.extend({
1112 type: 'containsRelationship',
1113 operator: '==contains',
1114 label: __('Relationships contain'),
1115 fieldTypes: ['relationship'],
1116 match: function (rule, field) {
1117 const val = field.val();
1118 // Relationships are stored as strings, use float to compare to field's rule value.
1119 const ruleVal = parseInt(rule.value);
1120 let match = false;
1121 if (val instanceof Array) {
1122 match = val.includes(ruleVal);
1123 }
1124 return match;
1125 },
1126 choices: function (fieldObject) {
1127 return conditionalSelect2(fieldObject, 'relationship');
1128 }
1129 });
1130 acf.registerConditionType(containsRelationship);
1131
1132 /**
1133 * Adds condition for Relationship not containing a specific Relationship.
1134 *
1135 * @since ACF 6.3
1136 */
1137 const containsNotRelationship = acf.Condition.extend({
1138 type: 'containsNotRelationship',
1139 operator: '!=contains',
1140 label: __('Relationships do not contain'),
1141 fieldTypes: ['relationship'],
1142 match: function (rule, field) {
1143 const val = field.val();
1144 // Relationships are stored as strings, use float to compare to field's rule value.
1145 const ruleVal = parseInt(rule.value);
1146 let match = true;
1147 if (val instanceof Array) {
1148 match = !val.includes(ruleVal);
1149 }
1150 return match;
1151 },
1152 choices: function (fieldObject) {
1153 return conditionalSelect2(fieldObject, 'relationship');
1154 }
1155 });
1156 acf.registerConditionType(containsNotRelationship);
1157
1158 /**
1159 * Adds condition for when any relation is selected.
1160 *
1161 * @since ACF 6.3
1162 */
1163 const HasAnyRelation = acf.Condition.extend({
1164 type: 'hasAnyRelation',
1165 operator: '!=empty',
1166 label: __('Has any relationship selected'),
1167 fieldTypes: ['relationship'],
1168 match: function (rule, field) {
1169 let val = field.val();
1170 if (val instanceof Array) {
1171 val = val.length;
1172 }
1173 return !!val;
1174 },
1175 choices: function () {
1176 return '<input type="text" disabled />';
1177 }
1178 });
1179 acf.registerConditionType(HasAnyRelation);
1180
1181 /**
1182 * Adds condition for when no relation is selected.
1183 *
1184 * @since ACF 6.3
1185 */
1186 const HasNoRelation = acf.Condition.extend({
1187 type: 'hasNoRelation',
1188 operator: '==empty',
1189 label: __('Has no relationship selected'),
1190 fieldTypes: ['relationship'],
1191 match: function (rule, field) {
1192 let val = field.val();
1193 if (val instanceof Array) {
1194 val = val.length;
1195 }
1196 return !val;
1197 },
1198 choices: function () {
1199 return '<input type="text" disabled />';
1200 }
1201 });
1202 acf.registerConditionType(HasNoRelation);
1203
1204 /**
1205 * Adds condition for having post equal to.
1206 *
1207 * @since ACF 6.3
1208 */
1209 const HasPostObject = acf.Condition.extend({
1210 type: 'hasPostObject',
1211 operator: '==',
1212 label: __('Post is equal to'),
1213 fieldTypes: ['post_object'],
1214 match: function (rule, field) {
1215 return isEqualToNumber(rule.value, field.val());
1216 },
1217 choices: function (fieldObject) {
1218 return conditionalSelect2(fieldObject, 'post_object');
1219 }
1220 });
1221 acf.registerConditionType(HasPostObject);
1222
1223 /**
1224 * Adds condition for selection having post not equal to.
1225 *
1226 * @since ACF 6.3
1227 */
1228 const HasPostObjectNotEqual = acf.Condition.extend({
1229 type: 'hasPostObjectNotEqual',
1230 operator: '!==',
1231 label: __('Post is not equal to'),
1232 fieldTypes: ['post_object'],
1233 match: function (rule, field) {
1234 return !isEqualToNumber(rule.value, field.val());
1235 },
1236 choices: function (fieldObject) {
1237 return conditionalSelect2(fieldObject, 'post_object');
1238 }
1239 });
1240 acf.registerConditionType(HasPostObjectNotEqual);
1241
1242 /**
1243 * Adds condition for Relationship containing a specific Relationship.
1244 *
1245 * @since ACF 6.3
1246 */
1247 const containsPostObject = acf.Condition.extend({
1248 type: 'containsPostObject',
1249 operator: '==contains',
1250 label: __('Posts contain'),
1251 fieldTypes: ['post_object'],
1252 match: function (rule, field) {
1253 const val = field.val();
1254 const ruleVal = rule.value;
1255 let match = false;
1256 if (val instanceof Array) {
1257 match = val.includes(ruleVal);
1258 } else {
1259 match = val === ruleVal;
1260 }
1261 return match;
1262 },
1263 choices: function (fieldObject) {
1264 return conditionalSelect2(fieldObject, 'post_object');
1265 }
1266 });
1267 acf.registerConditionType(containsPostObject);
1268
1269 /**
1270 * Adds condition for Relationship not containing a specific Relationship.
1271 *
1272 * @since ACF 6.3
1273 */
1274 const containsNotPostObject = acf.Condition.extend({
1275 type: 'containsNotPostObject',
1276 operator: '!=contains',
1277 label: __('Posts do not contain'),
1278 fieldTypes: ['post_object'],
1279 match: function (rule, field) {
1280 const val = field.val();
1281 const ruleVal = rule.value;
1282 let match = true;
1283 if (val instanceof Array) {
1284 match = !val.includes(ruleVal);
1285 } else {
1286 match = val !== ruleVal;
1287 }
1288 return match;
1289 },
1290 choices: function (fieldObject) {
1291 return conditionalSelect2(fieldObject, 'post_object');
1292 }
1293 });
1294 acf.registerConditionType(containsNotPostObject);
1295
1296 /**
1297 * Adds condition for when any post is selected.
1298 *
1299 * @since ACF 6.3
1300 */
1301 const HasAnyPostObject = acf.Condition.extend({
1302 type: 'hasAnyPostObject',
1303 operator: '!=empty',
1304 label: __('Has any post selected'),
1305 fieldTypes: ['post_object'],
1306 match: function (rule, field) {
1307 let val = field.val();
1308 if (val instanceof Array) {
1309 val = val.length;
1310 }
1311 return !!val;
1312 },
1313 choices: function () {
1314 return '<input type="text" disabled />';
1315 }
1316 });
1317 acf.registerConditionType(HasAnyPostObject);
1318
1319 /**
1320 * Adds condition for when no post is selected.
1321 *
1322 * @since ACF 6.3
1323 */
1324 const HasNoPostObject = acf.Condition.extend({
1325 type: 'hasNoPostObject',
1326 operator: '==empty',
1327 label: __('Has no post selected'),
1328 fieldTypes: ['post_object'],
1329 match: function (rule, field) {
1330 let val = field.val();
1331 if (val instanceof Array) {
1332 val = val.length;
1333 }
1334 return !val;
1335 },
1336 choices: function () {
1337 return '<input type="text" disabled />';
1338 }
1339 });
1340 acf.registerConditionType(HasNoPostObject);
1341
1342 /**
1343 * Adds condition for taxonomy having term equal to.
1344 *
1345 * @since ACF 6.3
1346 */
1347 const HasTerm = acf.Condition.extend({
1348 type: 'hasTerm',
1349 operator: '==',
1350 label: __('Term is equal to'),
1351 fieldTypes: ['taxonomy'],
1352 match: function (rule, field) {
1353 return isEqualToNumber(rule.value, field.val());
1354 },
1355 choices: function (fieldObject) {
1356 return conditionalSelect2(fieldObject, 'taxonomy');
1357 }
1358 });
1359 acf.registerConditionType(HasTerm);
1360
1361 /**
1362 * Adds condition for taxonomy having term not equal to.
1363 *
1364 * @since ACF 6.3
1365 */
1366 const hasTermNotEqual = acf.Condition.extend({
1367 type: 'hasTermNotEqual',
1368 operator: '!==',
1369 label: __('Term is not equal to'),
1370 fieldTypes: ['taxonomy'],
1371 match: function (rule, field) {
1372 return !isEqualToNumber(rule.value, field.val());
1373 },
1374 choices: function (fieldObject) {
1375 return conditionalSelect2(fieldObject, 'taxonomy');
1376 }
1377 });
1378 acf.registerConditionType(hasTermNotEqual);
1379
1380 /**
1381 * Adds condition for taxonomy containing a specific term.
1382 *
1383 * @since ACF 6.3
1384 */
1385 const containsTerm = acf.Condition.extend({
1386 type: 'containsTerm',
1387 operator: '==contains',
1388 label: __('Terms contain'),
1389 fieldTypes: ['taxonomy'],
1390 match: function (rule, field) {
1391 const val = field.val();
1392 const ruleVal = rule.value;
1393 let match = false;
1394 if (val instanceof Array) {
1395 match = val.includes(ruleVal);
1396 }
1397 return match;
1398 },
1399 choices: function (fieldObject) {
1400 return conditionalSelect2(fieldObject, 'taxonomy');
1401 }
1402 });
1403 acf.registerConditionType(containsTerm);
1404
1405 /**
1406 * Adds condition for taxonomy not containing a specific term.
1407 *
1408 * @since ACF 6.3
1409 */
1410 const containsNotTerm = acf.Condition.extend({
1411 type: 'containsNotTerm',
1412 operator: '!=contains',
1413 label: __('Terms do not contain'),
1414 fieldTypes: ['taxonomy'],
1415 match: function (rule, field) {
1416 const val = field.val();
1417 const ruleVal = rule.value;
1418 let match = true;
1419 if (val instanceof Array) {
1420 match = !val.includes(ruleVal);
1421 }
1422 return match;
1423 },
1424 choices: function (fieldObject) {
1425 return conditionalSelect2(fieldObject, 'taxonomy');
1426 }
1427 });
1428 acf.registerConditionType(containsNotTerm);
1429
1430 /**
1431 * Adds condition for when any term is selected.
1432 *
1433 * @since ACF 6.3
1434 */
1435 const HasAnyTerm = acf.Condition.extend({
1436 type: 'hasAnyTerm',
1437 operator: '!=empty',
1438 label: __('Has any term selected'),
1439 fieldTypes: ['taxonomy'],
1440 match: function (rule, field) {
1441 let val = field.val();
1442 if (val instanceof Array) {
1443 val = val.length;
1444 }
1445 return !!val;
1446 },
1447 choices: function () {
1448 return '<input type="text" disabled />';
1449 }
1450 });
1451 acf.registerConditionType(HasAnyTerm);
1452
1453 /**
1454 * Adds condition for when no term is selected.
1455 *
1456 * @since ACF 6.3
1457 */
1458 const HasNoTerm = acf.Condition.extend({
1459 type: 'hasNoTerm',
1460 operator: '==empty',
1461 label: __('Has no term selected'),
1462 fieldTypes: ['taxonomy'],
1463 match: function (rule, field) {
1464 let val = field.val();
1465 if (val instanceof Array) {
1466 val = val.length;
1467 }
1468 return !val;
1469 },
1470 choices: function () {
1471 return '<input type="text" disabled />';
1472 }
1473 });
1474 acf.registerConditionType(HasNoTerm);
1475
1476 /**
1477 * hasValue
1478 *
1479 * @date 1/2/18
1480 * @since ACF 5.6.5
1481 *
1482 * @param void
1483 * @return void
1484 */
1485 const HasValue = acf.Condition.extend({
1486 type: 'hasValue',
1487 operator: '!=empty',
1488 label: __('Has any value'),
1489 fieldTypes: ['text', 'textarea', 'number', 'range', 'email', 'url', 'password', 'image', 'file', 'wysiwyg', 'oembed', 'select', 'checkbox', 'radio', 'button_group', 'link', 'google_map', 'date_picker', 'date_time_picker', 'time_picker', 'color_picker', 'icon_picker'],
1490 match: function (rule, field) {
1491 let val = field.val();
1492 if (val instanceof Array) {
1493 val = val.length;
1494 }
1495 return val ? true : false;
1496 },
1497 choices: function (fieldObject) {
1498 return '<input type="text" disabled />';
1499 }
1500 });
1501 acf.registerConditionType(HasValue);
1502
1503 /**
1504 * hasValue
1505 *
1506 * @date 1/2/18
1507 * @since ACF 5.6.5
1508 *
1509 * @param void
1510 * @return void
1511 */
1512 const HasNoValue = HasValue.extend({
1513 type: 'hasNoValue',
1514 operator: '==empty',
1515 label: __('Has no value'),
1516 match: function (rule, field) {
1517 return !HasValue.prototype.match.apply(this, arguments);
1518 }
1519 });
1520 acf.registerConditionType(HasNoValue);
1521
1522 /**
1523 * EqualTo
1524 *
1525 * @date 1/2/18
1526 * @since ACF 5.6.5
1527 *
1528 * @param void
1529 * @return void
1530 */
1531 const EqualTo = acf.Condition.extend({
1532 type: 'equalTo',
1533 operator: '==',
1534 label: __('Value is equal to'),
1535 fieldTypes: ['text', 'textarea', 'number', 'range', 'email', 'url', 'password'],
1536 match: function (rule, field) {
1537 if (acf.isNumeric(rule.value)) {
1538 return isEqualToNumber(rule.value, field.val());
1539 } else {
1540 return isEqualTo(rule.value, field.val());
1541 }
1542 },
1543 choices: function (fieldObject) {
1544 return '<input type="text" />';
1545 }
1546 });
1547 acf.registerConditionType(EqualTo);
1548
1549 /**
1550 * NotEqualTo
1551 *
1552 * @date 1/2/18
1553 * @since ACF 5.6.5
1554 *
1555 * @param void
1556 * @return void
1557 */
1558 const NotEqualTo = EqualTo.extend({
1559 type: 'notEqualTo',
1560 operator: '!=',
1561 label: __('Value is not equal to'),
1562 match: function (rule, field) {
1563 return !EqualTo.prototype.match.apply(this, arguments);
1564 }
1565 });
1566 acf.registerConditionType(NotEqualTo);
1567
1568 /**
1569 * PatternMatch
1570 *
1571 * @date 1/2/18
1572 * @since ACF 5.6.5
1573 *
1574 * @param void
1575 * @return void
1576 */
1577 const PatternMatch = acf.Condition.extend({
1578 type: 'patternMatch',
1579 operator: '==pattern',
1580 label: __('Value matches pattern'),
1581 fieldTypes: ['text', 'textarea', 'email', 'url', 'password', 'wysiwyg'],
1582 match: function (rule, field) {
1583 return matchesPattern(field.val(), rule.value);
1584 },
1585 choices: function (fieldObject) {
1586 return '<input type="text" placeholder="[a-z0-9]" />';
1587 }
1588 });
1589 acf.registerConditionType(PatternMatch);
1590
1591 /**
1592 * Contains
1593 *
1594 * @date 1/2/18
1595 * @since ACF 5.6.5
1596 *
1597 * @param void
1598 * @return void
1599 */
1600 const Contains = acf.Condition.extend({
1601 type: 'contains',
1602 operator: '==contains',
1603 label: __('Value contains'),
1604 fieldTypes: ['text', 'textarea', 'number', 'email', 'url', 'password', 'wysiwyg', 'oembed', 'select'],
1605 match: function (rule, field) {
1606 return containsString(field.val(), rule.value);
1607 },
1608 choices: function (fieldObject) {
1609 return '<input type="text" />';
1610 }
1611 });
1612 acf.registerConditionType(Contains);
1613
1614 /**
1615 * TrueFalseEqualTo
1616 *
1617 * @date 1/2/18
1618 * @since ACF 5.6.5
1619 *
1620 * @param void
1621 * @return void
1622 */
1623 const TrueFalseEqualTo = EqualTo.extend({
1624 type: 'trueFalseEqualTo',
1625 choiceType: 'select',
1626 fieldTypes: ['true_false'],
1627 choices: function (field) {
1628 return [{
1629 id: 1,
1630 text: __('Checked')
1631 }];
1632 }
1633 });
1634 acf.registerConditionType(TrueFalseEqualTo);
1635
1636 /**
1637 * TrueFalseNotEqualTo
1638 *
1639 * @date 1/2/18
1640 * @since ACF 5.6.5
1641 *
1642 * @param void
1643 * @return void
1644 */
1645 const TrueFalseNotEqualTo = NotEqualTo.extend({
1646 type: 'trueFalseNotEqualTo',
1647 choiceType: 'select',
1648 fieldTypes: ['true_false'],
1649 choices: function (field) {
1650 return [{
1651 id: 1,
1652 text: __('Checked')
1653 }];
1654 }
1655 });
1656 acf.registerConditionType(TrueFalseNotEqualTo);
1657
1658 /**
1659 * SelectEqualTo
1660 *
1661 * @date 1/2/18
1662 * @since ACF 5.6.5
1663 *
1664 * @param void
1665 * @return void
1666 */
1667 const SelectEqualTo = acf.Condition.extend({
1668 type: 'selectEqualTo',
1669 operator: '==',
1670 label: __('Value is equal to'),
1671 fieldTypes: ['select', 'checkbox', 'radio', 'button_group'],
1672 match: function (rule, field) {
1673 const val = field.val();
1674 if (val instanceof Array) {
1675 return inArray(rule.value, val);
1676 } else {
1677 return isEqualTo(rule.value, val);
1678 }
1679 },
1680 choices: function (fieldObject) {
1681 // vars
1682 const choices = [];
1683 const lines = fieldObject.$setting('choices textarea').val().split('\n');
1684
1685 // allow null
1686 if (fieldObject.$input('allow_null').prop('checked')) {
1687 choices.push({
1688 id: '',
1689 text: __('Null')
1690 });
1691 }
1692
1693 // loop
1694 lines.map(function (line) {
1695 // split
1696 line = line.split(':');
1697
1698 // default label to value
1699 line[1] = line[1] || line[0];
1700
1701 // append
1702 choices.push({
1703 id: line[0].trim(),
1704 text: line[1].trim()
1705 });
1706 });
1707
1708 // return
1709 return choices;
1710 }
1711 });
1712 acf.registerConditionType(SelectEqualTo);
1713
1714 /**
1715 * SelectNotEqualTo
1716 *
1717 * @date 1/2/18
1718 * @since ACF 5.6.5
1719 *
1720 * @param void
1721 * @return void
1722 */
1723 const SelectNotEqualTo = SelectEqualTo.extend({
1724 type: 'selectNotEqualTo',
1725 operator: '!=',
1726 label: __('Value is not equal to'),
1727 match: function (rule, field) {
1728 return !SelectEqualTo.prototype.match.apply(this, arguments);
1729 }
1730 });
1731 acf.registerConditionType(SelectNotEqualTo);
1732
1733 /**
1734 * GreaterThan
1735 *
1736 * @date 1/2/18
1737 * @since ACF 5.6.5
1738 *
1739 * @param void
1740 * @return void
1741 */
1742 const GreaterThan = acf.Condition.extend({
1743 type: 'greaterThan',
1744 operator: '>',
1745 label: __('Value is greater than'),
1746 fieldTypes: ['number', 'range'],
1747 match: function (rule, field) {
1748 let val = field.val();
1749 if (val instanceof Array) {
1750 val = val.length;
1751 }
1752 return isGreaterThan(val, rule.value);
1753 },
1754 choices: function (fieldObject) {
1755 return '<input type="number" />';
1756 }
1757 });
1758 acf.registerConditionType(GreaterThan);
1759
1760 /**
1761 * LessThan
1762 *
1763 * @date 1/2/18
1764 * @since ACF 5.6.5
1765 *
1766 * @param void
1767 * @return void
1768 */
1769 const LessThan = GreaterThan.extend({
1770 type: 'lessThan',
1771 operator: '<',
1772 label: __('Value is less than'),
1773 match: function (rule, field) {
1774 let val = field.val();
1775 if (val instanceof Array) {
1776 val = val.length;
1777 }
1778 if (val === undefined || val === null || val === false) {
1779 return true;
1780 }
1781 return isLessThan(val, rule.value);
1782 },
1783 choices: function (fieldObject) {
1784 return '<input type="number" />';
1785 }
1786 });
1787 acf.registerConditionType(LessThan);
1788
1789 /**
1790 * SelectedGreaterThan
1791 *
1792 * @date 1/2/18
1793 * @since ACF 5.6.5
1794 *
1795 * @param void
1796 * @return void
1797 */
1798 const SelectionGreaterThan = GreaterThan.extend({
1799 type: 'selectionGreaterThan',
1800 label: __('Selection is greater than'),
1801 fieldTypes: ['checkbox', 'select', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user']
1802 });
1803 acf.registerConditionType(SelectionGreaterThan);
1804
1805 /**
1806 * SelectionLessThan
1807 *
1808 * @date 1/2/18
1809 * @since ACF 5.6.5
1810 *
1811 * @param void
1812 * @return void
1813 */
1814 const SelectionLessThan = LessThan.extend({
1815 type: 'selectionLessThan',
1816 label: __('Selection is less than'),
1817 fieldTypes: ['checkbox', 'select', 'post_object', 'page_link', 'relationship', 'taxonomy', 'user']
1818 });
1819 acf.registerConditionType(SelectionLessThan);
1820 })(jQuery);
1821
1822 /***/ }),
1823
1824 /***/ "./assets/src/js/_acf-condition.js":
1825 /*!*****************************************!*\
1826 !*** ./assets/src/js/_acf-condition.js ***!
1827 \*****************************************/
1828 /***/ (() => {
1829
1830 (function ($, undefined) {
1831 // vars
1832 var storage = [];
1833
1834 /**
1835 * acf.Condition
1836 *
1837 * description
1838 *
1839 * @date 23/3/18
1840 * @since ACF 5.6.9
1841 *
1842 * @param type $var Description. Default.
1843 * @return type Description.
1844 */
1845
1846 acf.Condition = acf.Model.extend({
1847 type: '',
1848 // used for model name
1849 operator: '==',
1850 // rule operator
1851 label: '',
1852 // label shown when editing fields
1853 choiceType: 'input',
1854 // input, select
1855 fieldTypes: [],
1856 // auto connect this conditions with these field types
1857
1858 data: {
1859 conditions: false,
1860 // the parent instance
1861 field: false,
1862 // the field which we query against
1863 rule: {} // the rule [field, operator, value]
1864 },
1865 events: {
1866 change: 'change',
1867 keyup: 'change',
1868 enableField: 'change',
1869 disableField: 'change'
1870 },
1871 setup: function (props) {
1872 $.extend(this.data, props);
1873 },
1874 getEventTarget: function ($el, event) {
1875 return $el || this.get('field').$el;
1876 },
1877 change: function (e, $el) {
1878 this.get('conditions').change(e);
1879 },
1880 match: function (rule, field) {
1881 return false;
1882 },
1883 calculate: function () {
1884 return this.match(this.get('rule'), this.get('field'));
1885 },
1886 choices: function (field) {
1887 return '<input type="text" />';
1888 }
1889 });
1890
1891 /**
1892 * acf.newCondition
1893 *
1894 * description
1895 *
1896 * @date 1/2/18
1897 * @since ACF 5.6.5
1898 *
1899 * @param type $var Description. Default.
1900 * @return type Description.
1901 */
1902
1903 acf.newCondition = function (rule, conditions) {
1904 // currently setting up conditions for fieldX, this field is the 'target'
1905 var target = conditions.get('field');
1906
1907 // use the 'target' to find the 'trigger' field.
1908 // - this field is used to setup the conditional logic events
1909 var field = target.getField(rule.field);
1910
1911 // bail early if no target or no field (possible if field doesn't exist due to HTML error)
1912 if (!target || !field) {
1913 return false;
1914 }
1915
1916 // vars
1917 var args = {
1918 rule: rule,
1919 target: target,
1920 conditions: conditions,
1921 field: field
1922 };
1923
1924 // vars
1925 var fieldType = field.get('type');
1926 var operator = rule.operator;
1927
1928 // get available conditions
1929 var conditionTypes = acf.getConditionTypes({
1930 fieldType: fieldType,
1931 operator: operator
1932 });
1933
1934 // instantiate
1935 var model = conditionTypes[0] || acf.Condition;
1936
1937 // instantiate
1938 var condition = new model(args);
1939
1940 // return
1941 return condition;
1942 };
1943
1944 /**
1945 * mid
1946 *
1947 * Calculates the model ID for a field type
1948 *
1949 * @date 15/12/17
1950 * @since ACF 5.6.5
1951 *
1952 * @param string type
1953 * @return string
1954 */
1955
1956 var modelId = function (type) {
1957 return acf.strPascalCase(type || '') + 'Condition';
1958 };
1959
1960 /**
1961 * acf.registerConditionType
1962 *
1963 * description
1964 *
1965 * @date 1/2/18
1966 * @since ACF 5.6.5
1967 *
1968 * @param type $var Description. Default.
1969 * @return type Description.
1970 */
1971
1972 acf.registerConditionType = function (model) {
1973 // vars
1974 var proto = model.prototype;
1975 var type = proto.type;
1976 var mid = modelId(type);
1977
1978 // store model
1979 acf.models[mid] = model;
1980
1981 // store reference
1982 storage.push(type);
1983 };
1984
1985 /**
1986 * acf.getConditionType
1987 *
1988 * description
1989 *
1990 * @date 1/2/18
1991 * @since ACF 5.6.5
1992 *
1993 * @param type $var Description. Default.
1994 * @return type Description.
1995 */
1996
1997 acf.getConditionType = function (type) {
1998 var mid = modelId(type);
1999 return acf.models[mid] || false;
2000 };
2001
2002 /**
2003 * acf.registerConditionForFieldType
2004 *
2005 * description
2006 *
2007 * @date 1/2/18
2008 * @since ACF 5.6.5
2009 *
2010 * @param type $var Description. Default.
2011 * @return type Description.
2012 */
2013
2014 acf.registerConditionForFieldType = function (conditionType, fieldType) {
2015 // get model
2016 var model = acf.getConditionType(conditionType);
2017
2018 // append
2019 if (model) {
2020 model.prototype.fieldTypes.push(fieldType);
2021 }
2022 };
2023
2024 /**
2025 * acf.getConditionTypes
2026 *
2027 * description
2028 *
2029 * @date 1/2/18
2030 * @since ACF 5.6.5
2031 *
2032 * @param type $var Description. Default.
2033 * @return type Description.
2034 */
2035
2036 acf.getConditionTypes = function (args) {
2037 // defaults
2038 args = acf.parseArgs(args, {
2039 fieldType: '',
2040 operator: ''
2041 });
2042
2043 // clone available types
2044 var types = [];
2045
2046 // loop
2047 storage.map(function (type) {
2048 // vars
2049 var model = acf.getConditionType(type);
2050 var ProtoFieldTypes = model.prototype.fieldTypes;
2051 var ProtoOperator = model.prototype.operator;
2052
2053 // check fieldType
2054 if (args.fieldType && ProtoFieldTypes.indexOf(args.fieldType) === -1) {
2055 return;
2056 }
2057
2058 // check operator
2059 if (args.operator && ProtoOperator !== args.operator) {
2060 return;
2061 }
2062
2063 // append
2064 types.push(model);
2065 });
2066
2067 // return
2068 return types;
2069 };
2070 })(jQuery);
2071
2072 /***/ }),
2073
2074 /***/ "./assets/src/js/_acf-conditions.js":
2075 /*!******************************************!*\
2076 !*** ./assets/src/js/_acf-conditions.js ***!
2077 \******************************************/
2078 /***/ (() => {
2079
2080 (function ($, undefined) {
2081 // vars
2082 var CONTEXT = 'conditional_logic';
2083
2084 /**
2085 * conditionsManager
2086 *
2087 * description
2088 *
2089 * @date 1/2/18
2090 * @since ACF 5.6.5
2091 *
2092 * @param type $var Description. Default.
2093 * @return type Description.
2094 */
2095
2096 var conditionsManager = new acf.Model({
2097 id: 'conditionsManager',
2098 priority: 20,
2099 // run actions later
2100
2101 actions: {
2102 new_field: 'onNewField'
2103 },
2104 onNewField: function (field) {
2105 if (field.has('conditions')) {
2106 field.getConditions().render();
2107 }
2108 }
2109 });
2110
2111 /**
2112 * acf.Field.prototype.getField
2113 *
2114 * Finds a field that is related to another field
2115 *
2116 * @date 1/2/18
2117 * @since ACF 5.6.5
2118 *
2119 * @param type $var Description. Default.
2120 * @return type Description.
2121 */
2122
2123 var getSiblingField = function (field, key) {
2124 // find sibling (very fast)
2125 var fields = acf.getFields({
2126 key: key,
2127 sibling: field.$el,
2128 suppressFilters: true
2129 });
2130
2131 // find sibling-children (fast)
2132 // needed for group fields, accordions, etc
2133 if (!fields.length) {
2134 fields = acf.getFields({
2135 key: key,
2136 parent: field.$el.parent(),
2137 suppressFilters: true
2138 });
2139 }
2140
2141 // Check for fields on other settings tabs (probably less fast).
2142 if (!fields.length && $('.acf-field-settings').length) {
2143 fields = acf.getFields({
2144 key: key,
2145 parent: field.$el.parents('.acf-field-settings:first'),
2146 suppressFilters: true
2147 });
2148 }
2149 if (!fields.length && $('#acf-basic-settings').length) {
2150 fields = acf.getFields({
2151 key: key,
2152 parent: $('#acf-basic-settings'),
2153 suppressFilters: true
2154 });
2155 }
2156
2157 // return
2158 if (fields.length) {
2159 return fields[0];
2160 }
2161 return false;
2162 };
2163 acf.Field.prototype.getField = function (key) {
2164 // get sibling field
2165 var field = getSiblingField(this, key);
2166
2167 // return early
2168 if (field) {
2169 return field;
2170 }
2171
2172 // move up through each parent and try again
2173 var parents = this.parents();
2174 for (var i = 0; i < parents.length; i++) {
2175 // get sibling field
2176 field = getSiblingField(parents[i], key);
2177
2178 // return early
2179 if (field) {
2180 return field;
2181 }
2182 }
2183
2184 // return
2185 return false;
2186 };
2187
2188 /**
2189 * acf.Field.prototype.getConditions
2190 *
2191 * Returns the field's conditions instance
2192 *
2193 * @date 1/2/18
2194 * @since ACF 5.6.5
2195 *
2196 * @param type $var Description. Default.
2197 * @return type Description.
2198 */
2199
2200 acf.Field.prototype.getConditions = function () {
2201 // instantiate
2202 if (!this.conditions) {
2203 this.conditions = new Conditions(this);
2204 }
2205
2206 // return
2207 return this.conditions;
2208 };
2209
2210 /**
2211 * Conditions
2212 *
2213 * description
2214 *
2215 * @date 1/2/18
2216 * @since ACF 5.6.5
2217 *
2218 * @param type $var Description. Default.
2219 * @return type Description.
2220 */
2221 var timeout = false;
2222 var Conditions = acf.Model.extend({
2223 id: 'Conditions',
2224 data: {
2225 field: false,
2226 // The field with "data-conditions" (target).
2227 timeStamp: false,
2228 // Reference used during "change" event.
2229 groups: [] // The groups of condition instances.
2230 },
2231 setup: function (field) {
2232 // data
2233 this.data.field = field;
2234
2235 // vars
2236 var conditions = field.get('conditions');
2237
2238 // detect groups
2239 if (conditions instanceof Array) {
2240 // detect groups
2241 if (conditions[0] instanceof Array) {
2242 // loop
2243 conditions.map(function (rules, i) {
2244 this.addRules(rules, i);
2245 }, this);
2246
2247 // detect rules
2248 } else {
2249 this.addRules(conditions);
2250 }
2251
2252 // detect rule
2253 } else {
2254 this.addRule(conditions);
2255 }
2256 },
2257 change: function (e) {
2258 // this function may be triggered multiple times per event due to multiple condition classes
2259 // compare timestamp to allow only 1 trigger per event
2260 if (this.get('timeStamp') === e.timeStamp) {
2261 return false;
2262 } else {
2263 this.set('timeStamp', e.timeStamp, true);
2264 }
2265
2266 // render condition and store result
2267 var changed = this.render();
2268 },
2269 render: function () {
2270 return this.calculate() ? this.show() : this.hide();
2271 },
2272 show: function () {
2273 return this.get('field').showEnable(this.cid, CONTEXT);
2274 },
2275 hide: function () {
2276 return this.get('field').hideDisable(this.cid, CONTEXT);
2277 },
2278 calculate: function () {
2279 // vars
2280 var pass = false;
2281
2282 // loop
2283 this.getGroups().map(function (group) {
2284 // ignore this group if another group passed
2285 if (pass) return;
2286
2287 // find passed
2288 var passed = group.filter(function (condition) {
2289 return condition.calculate();
2290 });
2291
2292 // if all conditions passed, update the global var
2293 if (passed.length == group.length) {
2294 pass = true;
2295 }
2296 });
2297 return pass;
2298 },
2299 hasGroups: function () {
2300 return this.data.groups != null;
2301 },
2302 getGroups: function () {
2303 return this.data.groups;
2304 },
2305 addGroup: function () {
2306 var group = [];
2307 this.data.groups.push(group);
2308 return group;
2309 },
2310 hasGroup: function (i) {
2311 return this.data.groups[i] != null;
2312 },
2313 getGroup: function (i) {
2314 return this.data.groups[i];
2315 },
2316 removeGroup: function (i) {
2317 this.data.groups[i].delete;
2318 return this;
2319 },
2320 addRules: function (rules, group) {
2321 rules.map(function (rule) {
2322 this.addRule(rule, group);
2323 }, this);
2324 },
2325 addRule: function (rule, group) {
2326 // defaults
2327 group = group || 0;
2328
2329 // vars
2330 var groupArray;
2331
2332 // get group
2333 if (this.hasGroup(group)) {
2334 groupArray = this.getGroup(group);
2335 } else {
2336 groupArray = this.addGroup();
2337 }
2338
2339 // instantiate
2340 var condition = acf.newCondition(rule, this);
2341
2342 // bail early if condition failed (field did not exist)
2343 if (!condition) {
2344 return false;
2345 }
2346
2347 // add rule
2348 groupArray.push(condition);
2349 },
2350 hasRule: function () {},
2351 getRule: function (rule, group) {
2352 // defaults
2353 rule = rule || 0;
2354 group = group || 0;
2355 return this.data.groups[group][rule];
2356 },
2357 removeRule: function () {}
2358 });
2359 })(jQuery);
2360
2361 /***/ }),
2362
2363 /***/ "./assets/src/js/_acf-field-accordion.js":
2364 /*!***********************************************!*\
2365 !*** ./assets/src/js/_acf-field-accordion.js ***!
2366 \***********************************************/
2367 /***/ (() => {
2368
2369 (function ($, undefined) {
2370 var i = 0;
2371 var Field = acf.Field.extend({
2372 type: 'accordion',
2373 wait: '',
2374 $control: function () {
2375 return this.$('.acf-fields:first');
2376 },
2377 initialize: function () {
2378 // Bail early if this is a duplicate of an existing initialized accordion.
2379 if (this.$el.hasClass('acf-accordion')) {
2380 return;
2381 }
2382
2383 // bail early if is cell
2384 if (this.$el.is('td')) return;
2385
2386 // endpoint
2387 if (this.get('endpoint')) {
2388 return this.remove();
2389 }
2390
2391 // vars
2392 var $field = this.$el;
2393 var $label = this.$labelWrap();
2394 var $input = this.$inputWrap();
2395 var $wrap = this.$control();
2396 var $instructions = $input.children('.description');
2397
2398 // force description into label
2399 if ($instructions.length) {
2400 $label.append($instructions);
2401 }
2402
2403 // table
2404 if (this.$el.is('tr')) {
2405 // vars
2406 var $table = this.$el.closest('table');
2407 var $newLabel = $('<div class="acf-accordion-title"/>');
2408 var $newInput = $('<div class="acf-accordion-content"/>');
2409 var $newTable = $('<table class="' + $table.attr('class') + '"/>');
2410 var $newWrap = $('<tbody/>');
2411
2412 // dom
2413 $newLabel.append($label.html());
2414 $newTable.append($newWrap);
2415 $newInput.append($newTable);
2416 $input.append($newLabel);
2417 $input.append($newInput);
2418
2419 // modify
2420 $label.remove();
2421 $wrap.remove();
2422 $input.attr('colspan', 2);
2423
2424 // update vars
2425 $label = $newLabel;
2426 $input = $newInput;
2427 $wrap = $newWrap;
2428 }
2429
2430 // add classes
2431 $field.addClass('acf-accordion');
2432 $label.addClass('acf-accordion-title');
2433 $input.addClass('acf-accordion-content');
2434
2435 // index
2436 i++;
2437
2438 // multi-expand
2439 if (this.get('multi_expand')) {
2440 $field.attr('multi-expand', 1);
2441 }
2442
2443 // open
2444 var order = acf.getPreference('this.accordions') || [];
2445 if (order[i - 1] !== undefined) {
2446 this.set('open', order[i - 1]);
2447 }
2448 if (this.get('open')) {
2449 $field.addClass('-open');
2450 $input.css('display', 'block'); // needed for accordion to close smoothly
2451 }
2452
2453 // add icon
2454 $label.prepend(accordionManager.iconHtml({
2455 open: this.get('open')
2456 }));
2457 $label.attr({
2458 tabindex: 0,
2459 role: 'button',
2460 'aria-expanded': this.get('open') ? 'true' : 'false'
2461 });
2462 $input.attr({
2463 role: 'region'
2464 });
2465
2466 // classes
2467 // - remove 'inside' which is a #poststuff WP class
2468 var $parent = $field.parent();
2469 $wrap.addClass($parent.hasClass('-left') ? '-left' : '');
2470 $wrap.addClass($parent.hasClass('-clear') ? '-clear' : '');
2471
2472 // append
2473 $wrap.append($field.nextUntil('.acf-field-accordion', '.acf-field'));
2474
2475 // clean up
2476 $wrap.removeAttr('data-open data-multi_expand data-endpoint');
2477 }
2478 });
2479 acf.registerFieldType(Field);
2480
2481 /**
2482 * accordionManager
2483 *
2484 * Events manager for the acf accordion
2485 *
2486 * @date 14/2/18
2487 * @since ACF 5.6.9
2488 *
2489 * @param void
2490 * @return void
2491 */
2492
2493 var accordionManager = new acf.Model({
2494 actions: {
2495 unload: 'onUnload'
2496 },
2497 events: {
2498 'click .acf-accordion-title': 'onClick',
2499 'keydown .acf-accordion-title': 'onKeydown',
2500 'invalidField .acf-accordion': 'onInvalidField'
2501 },
2502 isOpen: function ($el) {
2503 return $el.hasClass('-open');
2504 },
2505 toggle: function ($el) {
2506 if (this.isOpen($el)) {
2507 this.close($el);
2508 } else {
2509 this.open($el);
2510 }
2511 },
2512 iconHtml: function (props) {
2513 // Use SVG inside Gutenberg editor.
2514 if (acf.isGutenberg()) {
2515 if (props.open) {
2516 return '<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="acf-accordion-icon components-panel__arrow" aria-hidden="true" focusable="false"><path d="M6.5 12.4L12 8l5.5 4.4-.9 1.2L12 10l-4.5 3.6-1-1.2z"></path></svg>';
2517 } else {
2518 return '<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class=" acf-accordion-icon components-panel__arrow" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>';
2519 }
2520 } else {
2521 if (props.open) {
2522 return '<i class="acf-accordion-icon dashicons dashicons-arrow-down"></i>';
2523 } else {
2524 return '<i class="acf-accordion-icon dashicons dashicons-arrow-right"></i>';
2525 }
2526 }
2527 },
2528 open: function ($el) {
2529 var duration = acf.isGutenberg() ? 0 : 300;
2530
2531 // open
2532 $el.find('.acf-accordion-content:first').slideDown(duration).css('display', 'block');
2533 $el.find('.acf-accordion-icon:first').replaceWith(this.iconHtml({
2534 open: true
2535 }));
2536 $el.addClass('-open');
2537 $el.find('.acf-accordion-title:first').attr('aria-expanded', 'true');
2538
2539 // action
2540 acf.doAction('show', $el);
2541
2542 // close siblings
2543 if (!$el.attr('multi-expand')) {
2544 $el.siblings('.acf-accordion.-open').each(function () {
2545 accordionManager.close($(this));
2546 });
2547 }
2548 },
2549 close: function ($el) {
2550 var duration = acf.isGutenberg() ? 0 : 300;
2551
2552 // close
2553 $el.find('.acf-accordion-content:first').slideUp(duration);
2554 $el.find('.acf-accordion-icon:first').replaceWith(this.iconHtml({
2555 open: false
2556 }));
2557 $el.removeClass('-open');
2558 $el.find('.acf-accordion-title:first').attr('aria-expanded', 'false');
2559
2560 // action
2561 acf.doAction('hide', $el);
2562 },
2563 onClick: function (e, $el) {
2564 // prevent Default
2565 e.preventDefault();
2566
2567 // open close
2568 this.toggle($el.parent());
2569 },
2570 onKeydown: function (e, $el) {
2571 // check for enter or space
2572 if (13 === e.which) {
2573 // prevent Default
2574 e.preventDefault();
2575 // open close
2576 this.toggle($el.parent());
2577 }
2578 },
2579 onInvalidField: function (e, $el) {
2580 // bail early if already focused
2581 if (this.busy) {
2582 return;
2583 }
2584
2585 // disable functionality for 1sec (allow next validation to work)
2586 this.busy = true;
2587 this.setTimeout(function () {
2588 this.busy = false;
2589 }, 1000);
2590
2591 // open accordion
2592 this.open($el);
2593 },
2594 onUnload: function (e) {
2595 // vars
2596 var order = [];
2597
2598 // loop
2599 $('.acf-accordion').each(function () {
2600 var open = $(this).hasClass('-open') ? 1 : 0;
2601 order.push(open);
2602 });
2603
2604 // set
2605 if (order.length) {
2606 acf.setPreference('this.accordions', order);
2607 }
2608 }
2609 });
2610 })(jQuery);
2611
2612 /***/ }),
2613
2614 /***/ "./assets/src/js/_acf-field-button-group.js":
2615 /*!**************************************************!*\
2616 !*** ./assets/src/js/_acf-field-button-group.js ***!
2617 \**************************************************/
2618 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2619
2620 "use strict";
2621 __webpack_require__.r(__webpack_exports__);
2622
2623 (function ($, undefined) {
2624 const Field = acf.Field.extend({
2625 type: 'button_group',
2626 events: {
2627 'click input[type="radio"]': 'onClick',
2628 'keydown label': 'onKeyDown'
2629 },
2630 $control: function () {
2631 return this.$('.acf-button-group');
2632 },
2633 $input: function () {
2634 return this.$('input:checked');
2635 },
2636 initialize: function () {
2637 this.updateButtonStates();
2638 },
2639 setValue: function (val) {
2640 this.$('input[value="' + val + '"]').prop('checked', true).trigger('change');
2641 this.updateButtonStates();
2642 },
2643 updateButtonStates: function () {
2644 const labels = this.$control().find('label');
2645 const input = this.$input();
2646 labels.removeClass('selected').attr('aria-checked', 'false').attr('tabindex', '-1');
2647 if (input.length) {
2648 // If there's a checked input, mark its parent label as selected
2649 input.parent('label').addClass('selected').attr('aria-checked', 'true').attr('tabindex', '0');
2650 } else {
2651 labels.first().attr('tabindex', '0');
2652 }
2653 },
2654 onClick: function (e, $el) {
2655 this.selectButton($el.parent('label'));
2656 },
2657 onKeyDown: function (event, label) {
2658 const key = event.which;
2659
2660 // Space or Enter: select the button
2661 if (key === 13 || key === 32) {
2662 event.preventDefault();
2663 this.selectButton(label);
2664 return;
2665 }
2666
2667 // Arrow keys: move focus between buttons
2668 if (key === 37 || key === 39 || key === 38 || key === 40) {
2669 event.preventDefault();
2670 const labels = this.$control().find('label');
2671 const currentIndex = labels.index(label);
2672 let nextIndex;
2673
2674 // Left/Up arrow: move to previous, wrap to last if at start
2675 if (key === 37 || key === 38) {
2676 nextIndex = currentIndex > 0 ? currentIndex - 1 : labels.length - 1;
2677 }
2678 // Right/Down arrow: move to next, wrap to first if at end
2679 else {
2680 nextIndex = currentIndex < labels.length - 1 ? currentIndex + 1 : 0;
2681 }
2682 const nextLabel = labels.eq(nextIndex);
2683 labels.attr('tabindex', '-1');
2684 nextLabel.attr('tabindex', '0').trigger('focus');
2685 }
2686 },
2687 selectButton: function (element) {
2688 const inputRadio = element.find('input[type="radio"]');
2689 const isSelected = element.hasClass('selected');
2690 inputRadio.prop('checked', true).trigger('change');
2691 if (this.get('allow_null') && isSelected) {
2692 inputRadio.prop('checked', false).trigger('change');
2693 }
2694 this.updateButtonStates();
2695 }
2696 });
2697 acf.registerFieldType(Field);
2698 })(jQuery);
2699
2700 /***/ }),
2701
2702 /***/ "./assets/src/js/_acf-field-checkbox.js":
2703 /*!**********************************************!*\
2704 !*** ./assets/src/js/_acf-field-checkbox.js ***!
2705 \**********************************************/
2706 /***/ (() => {
2707
2708 (function ($, undefined) {
2709 var Field = acf.Field.extend({
2710 type: 'checkbox',
2711 events: {
2712 'change input': 'onChange',
2713 'click .acf-add-checkbox': 'onClickAdd',
2714 'click .acf-checkbox-toggle': 'onClickToggle',
2715 'click .acf-checkbox-custom': 'onClickCustom',
2716 'keydown input[type="checkbox"]': 'onKeyDownInput'
2717 },
2718 $control: function () {
2719 return this.$('.acf-checkbox-list');
2720 },
2721 $toggle: function () {
2722 return this.$('.acf-checkbox-toggle');
2723 },
2724 $input: function () {
2725 return this.$('input[type="hidden"]');
2726 },
2727 $inputs: function () {
2728 return this.$('input[type="checkbox"]').not('.acf-checkbox-toggle');
2729 },
2730 setValue: function (val) {
2731 if (!Array.isArray(val)) {
2732 val = val ? [val] : [];
2733 }
2734 this.$inputs().each(function () {
2735 const $input = $(this);
2736 const checked = val.includes($input.val());
2737 $input.prop('checked', checked);
2738 if (checked) {
2739 $input.parent('label').addClass('selected');
2740 } else {
2741 $input.parent('label').removeClass('selected');
2742 }
2743 });
2744 const $toggle = this.$toggle();
2745 if ($toggle.length) {
2746 const checked = this.$inputs().not(':checked').length === 0;
2747 $toggle.prop('checked', checked);
2748 }
2749 },
2750 getValue: function () {
2751 var val = [];
2752 this.$(':checked').each(function () {
2753 val.push($(this).val());
2754 });
2755 return val.length ? val : false;
2756 },
2757 onChange: function (e, $el) {
2758 // Vars.
2759 var checked = $el.prop('checked');
2760 var $label = $el.parent('label');
2761 var $toggle = this.$toggle();
2762
2763 // Add or remove "selected" class.
2764 if (checked) {
2765 $label.addClass('selected');
2766 } else {
2767 $label.removeClass('selected');
2768 }
2769
2770 // Update toggle state if all inputs are checked.
2771 if ($toggle.length) {
2772 var $inputs = this.$inputs();
2773
2774 // all checked
2775 if ($inputs.not(':checked').length == 0) {
2776 $toggle.prop('checked', true);
2777 } else {
2778 $toggle.prop('checked', false);
2779 }
2780 }
2781 },
2782 onClickAdd: function (e, $el) {
2783 var html = '<li><input class="acf-checkbox-custom" type="checkbox" checked="checked" /><input type="text" name="' + this.getInputName() + '[]" /></li>';
2784 $el.parent('li').before(html);
2785 $el.parent('li').parent().find('input[type="text"]').last().trigger('focus');
2786 },
2787 onClickToggle: function (e, $el) {
2788 var $inputs = this.$inputs();
2789 var checked = $el.prop('checked');
2790 $inputs.prop('checked', checked).trigger('change');
2791 },
2792 onClickCustom: function (e, $el) {
2793 var checked = $el.prop('checked');
2794 var $text = $el.next('input[type="text"]');
2795
2796 // checked
2797 if (checked) {
2798 $text.prop('disabled', false);
2799
2800 // not checked
2801 } else {
2802 $text.prop('disabled', true);
2803
2804 // remove
2805 if ($text.val() == '') {
2806 $el.parent('li').remove();
2807 }
2808 }
2809 },
2810 onKeyDownInput: function (e, $el) {
2811 // Check if Enter key (keyCode 13) was pressed
2812 if (e.which === 13) {
2813 // Prevent default form submission
2814 e.preventDefault();
2815
2816 // Toggle the checkbox state and trigger change event
2817 $el.prop('checked', !$el.prop('checked')).trigger('change');
2818
2819 // If this is the "Select All" toggle checkbox, run the toggle logic
2820 if ($el.is('.acf-checkbox-toggle')) {
2821 this.onClickToggle(e, $el);
2822 }
2823 }
2824 }
2825 });
2826 acf.registerFieldType(Field);
2827 })(jQuery);
2828
2829 /***/ }),
2830
2831 /***/ "./assets/src/js/_acf-field-color-picker.js":
2832 /*!**************************************************!*\
2833 !*** ./assets/src/js/_acf-field-color-picker.js ***!
2834 \**************************************************/
2835 /***/ (() => {
2836
2837 (function ($, undefined) {
2838 var Field = acf.Field.extend({
2839 type: 'color_picker',
2840 wait: 'load',
2841 events: {
2842 duplicateField: 'onDuplicate'
2843 },
2844 $control: function () {
2845 return this.$('.acf-color-picker');
2846 },
2847 $input: function () {
2848 return this.$('input[type="hidden"]');
2849 },
2850 $inputText: function () {
2851 return this.$('input[type="text"]');
2852 },
2853 setValue: function (val) {
2854 // update input (with change)
2855 acf.val(this.$input(), val);
2856
2857 // update iris
2858 this.$inputText().iris('color', val);
2859 },
2860 initialize: function () {
2861 // vars
2862 var $input = this.$input();
2863 var $inputText = this.$inputText();
2864
2865 // event
2866 var onChange = function (e) {
2867 // timeout is required to ensure the $input val is correct
2868 setTimeout(function () {
2869 acf.val($input, $inputText.val());
2870 }, 1);
2871 };
2872
2873 // args
2874 var args = {
2875 defaultColor: false,
2876 palettes: true,
2877 hide: true,
2878 change: onChange,
2879 clear: onChange
2880 };
2881 if ('custom' === $inputText.data('acf-palette-type')) {
2882 const paletteColor = $inputText.data('acf-palette-colors').match(/#(?:[0-9a-fA-F]{3}){1,2}|rgba?\([\s*(\d|.)+\s*,]+\)/g);
2883 if (paletteColor) {
2884 let trimmed = paletteColor.map(color => color.trim());
2885 args.palettes = trimmed;
2886 }
2887 }
2888
2889 // filter
2890 var args = acf.applyFilters('color_picker_args', args, this);
2891 if (Array.isArray(args.palettes) && args.palettes.length > 10) {
2892 // Add class for large custom palette styling
2893 this.$control().addClass('acf-color-picker-large-custom-palette');
2894 }
2895 // initialize
2896 $inputText.wpColorPicker(args);
2897 },
2898 onDuplicate: function (e, $el, $duplicate) {
2899 // The wpColorPicker library does not provide a destroy method.
2900 // Manually reset DOM by replacing elements back to their original state.
2901 $colorPicker = $duplicate.find('.wp-picker-container');
2902 $inputText = $duplicate.find('input[type="text"]');
2903 $colorPicker.replaceWith($inputText);
2904 }
2905 });
2906 acf.registerFieldType(Field);
2907 })(jQuery);
2908
2909 /***/ }),
2910
2911 /***/ "./assets/src/js/_acf-field-date-picker.js":
2912 /*!*************************************************!*\
2913 !*** ./assets/src/js/_acf-field-date-picker.js ***!
2914 \*************************************************/
2915 /***/ (() => {
2916
2917 (function ($, undefined) {
2918 var Field = acf.Field.extend({
2919 type: 'date_picker',
2920 events: {
2921 'blur input[type="text"]': 'onBlur',
2922 duplicateField: 'onDuplicate'
2923 },
2924 $control: function () {
2925 return this.$('.acf-date-picker');
2926 },
2927 $input: function () {
2928 return this.$('input[type="hidden"]');
2929 },
2930 $inputText: function () {
2931 return this.$('input[type="text"]');
2932 },
2933 initialize: function () {
2934 // save_format: compatibility with ACF < 5.0.0
2935 if (this.has('save_format')) {
2936 return this.initializeCompatibility();
2937 }
2938
2939 // vars
2940 var $input = this.$input();
2941 var $inputText = this.$inputText();
2942
2943 // args
2944 var args = {
2945 dateFormat: this.get('date_format'),
2946 altField: $input,
2947 altFormat: 'yymmdd',
2948 changeYear: true,
2949 yearRange: '-100:+100',
2950 changeMonth: true,
2951 showButtonPanel: true,
2952 firstDay: this.get('first_day')
2953 };
2954
2955 // filter
2956 args = acf.applyFilters('date_picker_args', args, this);
2957
2958 // add date picker
2959 acf.newDatePicker($inputText, args);
2960
2961 // Check if default to today is enabled and field is empty
2962 if ($inputText.data('default-to-today') === 1 && !$input.val()) {
2963 // Get current date
2964 const currentDate = new Date();
2965
2966 // Format display date
2967 const displayDate = $.datepicker.formatDate(args.dateFormat, currentDate);
2968
2969 // Set the display input value (what user sees)
2970 $inputText.val(`${displayDate}`);
2971
2972 // Format hidden field date (for database storage)
2973 const hiddenDate = $.datepicker.formatDate('yymmdd', currentDate);
2974
2975 // Set the hidden input value (what gets saved)
2976 $input.val(`${hiddenDate}`);
2977 }
2978 acf.doAction('date_picker_init', $inputText, args, this);
2979 },
2980 initializeCompatibility: function () {
2981 // vars
2982 var $input = this.$input();
2983 var $inputText = this.$inputText();
2984
2985 // get and set value from alt field
2986 $inputText.val($input.val());
2987
2988 // args
2989 var args = {
2990 dateFormat: this.get('date_format'),
2991 altField: $input,
2992 altFormat: this.get('save_format'),
2993 changeYear: true,
2994 yearRange: '-100:+100',
2995 changeMonth: true,
2996 showButtonPanel: true,
2997 firstDay: this.get('first_day')
2998 };
2999
3000 // filter for 3rd party customization
3001 args = acf.applyFilters('date_picker_args', args, this);
3002
3003 // backup
3004 var dateFormat = args.dateFormat;
3005
3006 // change args.dateFormat
3007 args.dateFormat = this.get('save_format');
3008
3009 // add date picker
3010 acf.newDatePicker($inputText, args);
3011
3012 // now change the format back to how it should be.
3013 $inputText.datepicker('option', 'dateFormat', dateFormat);
3014
3015 // action for 3rd party customization
3016 acf.doAction('date_picker_init', $inputText, args, this);
3017 },
3018 setValue: function (val) {
3019 acf.val(this.$input(), val);
3020 const $inputText = this.$inputText();
3021 if (val && $inputText.length) {
3022 try {
3023 const date = $.datepicker.parseDate('yymmdd', val);
3024 const dateFormat = this.get('date_format') || $inputText.datepicker('option', 'dateFormat');
3025 $inputText.val($.datepicker.formatDate(dateFormat, date));
3026 } catch (e) {
3027 $inputText.val(val);
3028 }
3029 } else {
3030 $inputText.val('');
3031 }
3032 },
3033 onBlur: function () {
3034 if (!this.$inputText().val()) {
3035 acf.val(this.$input(), '');
3036 }
3037 },
3038 onDuplicate: function (e, $el, $duplicate) {
3039 $duplicate.find('input[type="text"]').removeClass('hasDatepicker').removeAttr('id');
3040 }
3041 });
3042 acf.registerFieldType(Field);
3043
3044 // manager
3045 var datePickerManager = new acf.Model({
3046 priority: 5,
3047 wait: 'ready',
3048 initialize: function () {
3049 // vars
3050 var locale = acf.get('locale');
3051 var rtl = acf.get('rtl');
3052 var l10n = acf.get('datePickerL10n');
3053
3054 // bail early if no l10n
3055 if (!l10n) {
3056 return false;
3057 }
3058
3059 // bail early if no datepicker library
3060 if (typeof $.datepicker === 'undefined') {
3061 return false;
3062 }
3063
3064 // rtl
3065 l10n.isRTL = rtl;
3066
3067 // append
3068 $.datepicker.regional[locale] = l10n;
3069 $.datepicker.setDefaults(l10n);
3070 }
3071 });
3072
3073 // add
3074 acf.newDatePicker = function ($input, args) {
3075 // bail early if no datepicker library
3076 if (typeof $.datepicker === 'undefined') {
3077 return false;
3078 }
3079
3080 // defaults
3081 args = args || {};
3082
3083 // initialize
3084 $input.datepicker(args);
3085
3086 // wrap the datepicker (only if it hasn't already been wrapped)
3087 if ($('body > #ui-datepicker-div').exists()) {
3088 $('body > #ui-datepicker-div').wrap('<div class="acf-ui-datepicker" />');
3089 }
3090 };
3091 })(jQuery);
3092
3093 /***/ }),
3094
3095 /***/ "./assets/src/js/_acf-field-date-time-picker.js":
3096 /*!******************************************************!*\
3097 !*** ./assets/src/js/_acf-field-date-time-picker.js ***!
3098 \******************************************************/
3099 /***/ (() => {
3100
3101 (function ($, undefined) {
3102 var Field = acf.models.DatePickerField.extend({
3103 type: 'date_time_picker',
3104 $control: function () {
3105 return this.$('.acf-date-time-picker');
3106 },
3107 setValue: function (val) {
3108 acf.val(this.$input(), val);
3109 const $inputText = this.$inputText();
3110 if (val && $inputText.length) {
3111 try {
3112 const parts = val.split(' ');
3113 const dateValue = parts[0] || '';
3114 const timeValue = parts[1] || '';
3115 const date = $.datepicker.parseDate('yy-mm-dd', dateValue);
3116 const dateFormat = this.get('date_format') || $inputText.datetimepicker('option', 'dateFormat');
3117 const timeFormat = this.get('time_format') || $inputText.datetimepicker('option', 'timeFormat');
3118 const dateText = $.datepicker.formatDate(dateFormat, date);
3119 let timeText = timeValue;
3120 const matches = timeValue.match(/^(\d{2}):(\d{2}):(\d{2})$/);
3121 if (matches && $.datepicker.formatTime) {
3122 timeText = $.datepicker.formatTime(timeFormat, {
3123 hour: parseInt(matches[1], 10),
3124 minute: parseInt(matches[2], 10),
3125 second: parseInt(matches[3], 10)
3126 });
3127 }
3128 $inputText.val(dateText + ' ' + timeText);
3129 } catch (e) {
3130 $inputText.val(val);
3131 }
3132 } else {
3133 $inputText.val('');
3134 }
3135 },
3136 initialize: function () {
3137 // vars
3138 var $input = this.$input();
3139 var $inputText = this.$inputText();
3140
3141 // args
3142 var args = {
3143 dateFormat: this.get('date_format'),
3144 timeFormat: this.get('time_format'),
3145 altField: $input,
3146 altFieldTimeOnly: false,
3147 altFormat: 'yy-mm-dd',
3148 altTimeFormat: 'HH:mm:ss',
3149 changeYear: true,
3150 yearRange: '-100:+100',
3151 changeMonth: true,
3152 showButtonPanel: true,
3153 firstDay: this.get('first_day'),
3154 controlType: 'select',
3155 oneLine: true
3156 };
3157
3158 // filter
3159 args = acf.applyFilters('date_time_picker_args', args, this);
3160
3161 // add date time picker
3162 acf.newDateTimePicker($inputText, args);
3163
3164 // Check if default to today is enabled and field is empty
3165 if ($inputText.data('default-to-today') === 1 && !$input.val()) {
3166 // Get current date
3167 const currentDate = new Date();
3168
3169 // Format display date and time
3170 const displayDate = $.datepicker.formatDate(args.dateFormat, currentDate);
3171 const displayTime = $.datepicker.formatTime(args.timeFormat, {
3172 hour: currentDate.getHours(),
3173 minute: currentDate.getMinutes(),
3174 second: currentDate.getSeconds()
3175 });
3176
3177 // Set the display input value (what user sees)
3178 $inputText.val(`${displayDate} ${displayTime}`);
3179
3180 // Format hidden field date and time (for database storage)
3181 const hiddenDate = $.datepicker.formatDate('yy-mm-dd', currentDate);
3182 const hiddenTime = $.datepicker.formatTime('hh:mm:ss', {
3183 hour: currentDate.getHours(),
3184 minute: currentDate.getMinutes(),
3185 second: currentDate.getSeconds()
3186 });
3187
3188 // Set the hidden input value (what gets saved)
3189 $input.val(`${hiddenDate} ${hiddenTime}`);
3190 }
3191
3192 // action
3193 acf.doAction('date_time_picker_init', $inputText, args, this);
3194 }
3195 });
3196 acf.registerFieldType(Field);
3197
3198 // manager
3199 var dateTimePickerManager = new acf.Model({
3200 priority: 5,
3201 wait: 'ready',
3202 initialize: function () {
3203 // vars
3204 var locale = acf.get('locale');
3205 var rtl = acf.get('rtl');
3206 var l10n = acf.get('dateTimePickerL10n');
3207
3208 // bail early if no l10n
3209 if (!l10n) {
3210 return false;
3211 }
3212
3213 // bail early if no datepicker library
3214 if (typeof $.timepicker === 'undefined') {
3215 return false;
3216 }
3217
3218 // rtl
3219 l10n.isRTL = rtl;
3220
3221 // append
3222 $.timepicker.regional[locale] = l10n;
3223 $.timepicker.setDefaults(l10n);
3224 }
3225 });
3226
3227 // add
3228 acf.newDateTimePicker = function ($input, args) {
3229 // bail early if no datepicker library
3230 if (typeof $.timepicker === 'undefined') {
3231 return false;
3232 }
3233
3234 // defaults
3235 args = args || {};
3236
3237 // initialize
3238 $input.datetimepicker(args);
3239
3240 // wrap the datepicker (only if it hasn't already been wrapped)
3241 if ($('body > #ui-datepicker-div').exists()) {
3242 $('body > #ui-datepicker-div').wrap('<div class="acf-ui-datepicker" />');
3243 }
3244 };
3245 })(jQuery);
3246
3247 /***/ }),
3248
3249 /***/ "./assets/src/js/_acf-field-file.js":
3250 /*!******************************************!*\
3251 !*** ./assets/src/js/_acf-field-file.js ***!
3252 \******************************************/
3253 /***/ (() => {
3254
3255 (function ($, undefined) {
3256 const Field = acf.models.ImageField.extend({
3257 type: 'file',
3258 $control: function () {
3259 return this.$('.acf-file-uploader');
3260 },
3261 $input: function () {
3262 return this.$('input[type="hidden"]:first');
3263 },
3264 events: {
3265 'click a[data-name="add"]': 'onClickAdd',
3266 'click a[data-name="edit"]': 'onClickEdit',
3267 'click a[data-name="remove"]': 'onClickRemove',
3268 'change input[type="file"]': 'onChange',
3269 'keydown .file-wrap': 'onImageWrapKeydown'
3270 },
3271 validateAttachment: function (attachment) {
3272 // defaults
3273 attachment = attachment || {};
3274
3275 // WP attachment
3276 if (attachment.id !== undefined) {
3277 attachment = attachment.attributes;
3278 }
3279
3280 // args
3281 attachment = acf.parseArgs(attachment, {
3282 url: '',
3283 alt: '',
3284 title: '',
3285 filename: '',
3286 filesizeHumanReadable: '',
3287 icon: '/wp-includes/images/media/default.png'
3288 });
3289
3290 // return
3291 return attachment;
3292 },
3293 render: function (attachment) {
3294 // vars
3295 attachment = this.validateAttachment(attachment);
3296
3297 // update image
3298 this.$('img').attr({
3299 src: attachment.icon,
3300 alt: attachment.alt,
3301 title: attachment.title
3302 });
3303
3304 // update elements
3305 this.$('[data-name="title"]').text(attachment.title);
3306 this.$('[data-name="filename"]').text(attachment.filename).attr('href', attachment.url);
3307 this.$('[data-name="filesize"]').text(attachment.filesizeHumanReadable);
3308
3309 // vars
3310 const val = attachment.id || '';
3311
3312 // update val
3313 acf.val(this.$input(), val);
3314 if (val) {
3315 // update class
3316 this.$control().addClass('has-value');
3317 const fileWrap = this.$('.file-wrap');
3318 if (fileWrap.length) {
3319 fileWrap.trigger('focus');
3320 }
3321 } else {
3322 this.$control().removeClass('has-value');
3323 }
3324 },
3325 setValue: function (val) {
3326 val = val ? String(val) : '';
3327 if (acf.val(this.$input(), val, true) === false) {
3328 return;
3329 }
3330 if (val) {
3331 if (window.wp && wp.media && wp.media.attachment) {
3332 const attachment = wp.media.attachment(val);
3333 attachment.fetch().then($.proxy(function () {
3334 this.render(attachment);
3335 }, this));
3336 } else {
3337 this.$control().addClass('has-value');
3338 }
3339 } else {
3340 this.render(false);
3341 }
3342 },
3343 selectAttachment: function () {
3344 // vars
3345 const parent = this.parent();
3346 const multiple = parent && parent.get('type') === 'repeater';
3347
3348 // new frame
3349 const frame = acf.newMediaPopup({
3350 mode: 'select',
3351 title: acf.__('Select File'),
3352 field: this.get('key'),
3353 multiple: multiple,
3354 library: this.get('library'),
3355 allowedTypes: this.get('mime_types'),
3356 select: $.proxy(function (attachment, i) {
3357 if (i > 0) {
3358 this.append(attachment, parent);
3359 } else {
3360 this.render(attachment);
3361 }
3362 }, this)
3363 });
3364 },
3365 editAttachment: function (button) {
3366 // vars
3367 const val = this.val();
3368
3369 // bail early if no val
3370 if (!val) {
3371 return false;
3372 }
3373
3374 // popup
3375 var frame = acf.newMediaPopup({
3376 mode: 'edit',
3377 title: acf.__('Edit File'),
3378 button: acf.__('Update File'),
3379 attachment: val,
3380 field: this.get('key'),
3381 select: $.proxy(function (attachment) {
3382 this.render(attachment);
3383 }, this),
3384 close: $.proxy(function () {
3385 if ('edit-button' === button) {
3386 const edit = this.$el.find('a[data-name="edit"]');
3387 if (edit.length) {
3388 edit.trigger('focus');
3389 }
3390 } else {
3391 const imageWrap = this.$el.find('.image-wrap');
3392 if (imageWrap.length) {
3393 imageWrap.trigger('focus');
3394 }
3395 }
3396 }, this)
3397 });
3398 }
3399 });
3400 acf.registerFieldType(Field);
3401 })(jQuery);
3402
3403 /***/ }),
3404
3405 /***/ "./assets/src/js/_acf-field-google-map.js":
3406 /*!************************************************!*\
3407 !*** ./assets/src/js/_acf-field-google-map.js ***!
3408 \************************************************/
3409 /***/ (() => {
3410
3411 (function ($, undefined) {
3412 var Field = acf.Field.extend({
3413 type: 'google_map',
3414 map: false,
3415 wait: 'load',
3416 events: {
3417 'click button[data-name="clear"]': 'onClickClear',
3418 'click button[data-name="locate"]': 'onClickLocate',
3419 'click button[data-name="search"]': 'onClickSearch',
3420 'keydown .search': 'onKeydownSearch',
3421 'keyup .search': 'onKeyupSearch',
3422 'focus .search': 'onFocusSearch',
3423 'blur .search': 'onBlurSearch',
3424 showField: 'onShow'
3425 },
3426 $control: function () {
3427 return this.$('.acf-google-map');
3428 },
3429 $search: function () {
3430 return this.$('.search');
3431 },
3432 $canvas: function () {
3433 return this.$('.canvas');
3434 },
3435 setState: function (state) {
3436 // Remove previous state classes.
3437 this.$control().removeClass('-value -loading -searching');
3438
3439 // Determine auto state based of current value.
3440 if (state === 'default') {
3441 state = this.val() ? 'value' : '';
3442 }
3443
3444 // Update state class.
3445 if (state) {
3446 this.$control().addClass('-' + state);
3447 }
3448 },
3449 getValue: function () {
3450 var val = this.$input().val();
3451 if (val) {
3452 return JSON.parse(val);
3453 } else {
3454 return false;
3455 }
3456 },
3457 setValue: function (val, silent) {
3458 // Convert input value.
3459 var valAttr = '';
3460 if (val) {
3461 valAttr = JSON.stringify(val);
3462 }
3463
3464 // Update input (with change).
3465 acf.val(this.$input(), valAttr);
3466
3467 // Bail early if silent update.
3468 if (silent) {
3469 return;
3470 }
3471
3472 // Render.
3473 this.renderVal(val);
3474
3475 /**
3476 * Fires immediately after the value has changed.
3477 *
3478 * @date 12/02/2014
3479 * @since ACF 5.0.0
3480 *
3481 * @param object|string val The new value.
3482 * @param object map The Google Map instance.
3483 * @param object field The field instance.
3484 */
3485 acf.doAction('google_map_change', val, this.map, this);
3486 },
3487 renderVal: function (val) {
3488 // Value.
3489 if (val) {
3490 this.setState('value');
3491 this.$search().val(val.address);
3492 this.setPosition(val.lat, val.lng);
3493
3494 // No value.
3495 } else {
3496 this.setState('');
3497 this.$search().val('');
3498 this.map.marker.setVisible(false);
3499 }
3500 },
3501 newLatLng: function (lat, lng) {
3502 return new google.maps.LatLng(parseFloat(lat), parseFloat(lng));
3503 },
3504 setPosition: function (lat, lng) {
3505 // Update marker position.
3506 this.map.marker.setPosition({
3507 lat: parseFloat(lat),
3508 lng: parseFloat(lng)
3509 });
3510
3511 // Show marker.
3512 this.map.marker.setVisible(true);
3513
3514 // Center map.
3515 this.center();
3516 },
3517 center: function () {
3518 // Find marker position.
3519 var position = this.map.marker.getPosition();
3520 if (position) {
3521 var lat = position.lat();
3522 var lng = position.lng();
3523
3524 // Or find default settings.
3525 } else {
3526 var lat = this.get('lat');
3527 var lng = this.get('lng');
3528 }
3529
3530 // Center map.
3531 this.map.setCenter({
3532 lat: parseFloat(lat),
3533 lng: parseFloat(lng)
3534 });
3535 },
3536 initialize: function () {
3537 // Ensure Google API is loaded and then initialize map.
3538 withAPI(this.initializeMap.bind(this));
3539 },
3540 initializeMap: function () {
3541 // Get value ignoring conditional logic status.
3542 var val = this.getValue();
3543
3544 // Construct default args.
3545 var args = acf.parseArgs(val, {
3546 zoom: this.get('zoom'),
3547 lat: this.get('lat'),
3548 lng: this.get('lng')
3549 });
3550
3551 // Create Map.
3552 var mapArgs = {
3553 scrollwheel: false,
3554 zoom: parseInt(args.zoom),
3555 center: {
3556 lat: parseFloat(args.lat),
3557 lng: parseFloat(args.lng)
3558 },
3559 mapTypeId: google.maps.MapTypeId.ROADMAP,
3560 marker: {
3561 draggable: true,
3562 raiseOnDrag: true
3563 },
3564 autocomplete: {}
3565 };
3566 mapArgs = acf.applyFilters('google_map_args', mapArgs, this);
3567 var map = new google.maps.Map(this.$canvas()[0], mapArgs);
3568
3569 // Create Marker.
3570 var markerArgs = acf.parseArgs(mapArgs.marker, {
3571 draggable: true,
3572 raiseOnDrag: true,
3573 map: map
3574 });
3575 markerArgs = acf.applyFilters('google_map_marker_args', markerArgs, this);
3576 var marker = new google.maps.Marker(markerArgs);
3577
3578 // Maybe Create Autocomplete.
3579 var autocomplete = false;
3580 if (acf.isset(google, 'maps', 'places', 'Autocomplete')) {
3581 var autocompleteArgs = mapArgs.autocomplete || {};
3582 autocompleteArgs = acf.applyFilters('google_map_autocomplete_args', autocompleteArgs, this);
3583 autocomplete = new google.maps.places.Autocomplete(this.$search()[0], autocompleteArgs);
3584 autocomplete.bindTo('bounds', map);
3585 }
3586
3587 // Add map events.
3588 this.addMapEvents(this, map, marker, autocomplete);
3589
3590 // Append references.
3591 map.acf = this;
3592 map.marker = marker;
3593 map.autocomplete = autocomplete;
3594 this.map = map;
3595
3596 // Set position.
3597 if (val) {
3598 this.setPosition(val.lat, val.lng);
3599 }
3600
3601 /**
3602 * Fires immediately after the Google Map has been initialized.
3603 *
3604 * @date 12/02/2014
3605 * @since ACF 5.0.0
3606 *
3607 * @param object map The Google Map instance.
3608 * @param object marker The Google Map marker isntance.
3609 * @param object field The field instance.
3610 */
3611 acf.doAction('google_map_init', map, marker, this);
3612 },
3613 addMapEvents: function (field, map, marker, autocomplete) {
3614 // Click map.
3615 google.maps.event.addListener(map, 'click', function (e) {
3616 var lat = e.latLng.lat();
3617 var lng = e.latLng.lng();
3618 field.searchPosition(lat, lng);
3619 });
3620
3621 // Drag marker.
3622 google.maps.event.addListener(marker, 'dragend', function () {
3623 var lat = this.getPosition().lat();
3624 var lng = this.getPosition().lng();
3625 field.searchPosition(lat, lng);
3626 });
3627
3628 // Autocomplete search.
3629 if (autocomplete) {
3630 google.maps.event.addListener(autocomplete, 'place_changed', function () {
3631 var place = this.getPlace();
3632 field.searchPlace(place);
3633 });
3634 }
3635
3636 // Detect zoom change.
3637 google.maps.event.addListener(map, 'zoom_changed', function () {
3638 var val = field.val();
3639 if (val) {
3640 val.zoom = map.getZoom();
3641 field.setValue(val, true);
3642 }
3643 });
3644 },
3645 searchPosition: function (lat, lng) {
3646 //console.log('searchPosition', lat, lng );
3647
3648 // Start Loading.
3649 this.setState('loading');
3650
3651 // Query Geocoder.
3652 var latLng = {
3653 lat: lat,
3654 lng: lng
3655 };
3656 geocoder.geocode({
3657 location: latLng
3658 }, function (results, status) {
3659 //console.log('searchPosition', arguments );
3660
3661 // End Loading.
3662 this.setState('');
3663
3664 // Status failure.
3665 if (status !== 'OK') {
3666 this.showNotice({
3667 text: acf.__('Location not found: %s').replace('%s', status),
3668 type: 'warning'
3669 });
3670
3671 // Success.
3672 } else {
3673 var val = this.parseResult(results[0]);
3674
3675 // Override lat/lng to match user defined marker location.
3676 // Avoids issue where marker "snaps" to nearest result.
3677 val.lat = lat;
3678 val.lng = lng;
3679 this.val(val);
3680 }
3681 }.bind(this));
3682 },
3683 searchPlace: function (place) {
3684 //console.log('searchPlace', place );
3685
3686 // Bail early if no place.
3687 if (!place) {
3688 return;
3689 }
3690
3691 // Selecting from the autocomplete dropdown will return a rich PlaceResult object.
3692 // Be sure to over-write the "formatted_address" value with the one displayed to the user for best UX.
3693 if (place.geometry) {
3694 place.formatted_address = this.$search().val();
3695 var val = this.parseResult(place);
3696 this.val(val);
3697
3698 // Searching a custom address will return an empty PlaceResult object.
3699 } else if (place.name) {
3700 this.searchAddress(place.name);
3701 }
3702 },
3703 searchAddress: function (address) {
3704 //console.log('searchAddress', address );
3705
3706 // Bail early if no address.
3707 if (!address) {
3708 return;
3709 }
3710
3711 // Allow "lat,lng" search.
3712 var latLng = address.split(',');
3713 if (latLng.length == 2) {
3714 var lat = parseFloat(latLng[0]);
3715 var lng = parseFloat(latLng[1]);
3716 if (lat && lng) {
3717 return this.searchPosition(lat, lng);
3718 }
3719 }
3720
3721 // Start Loading.
3722 this.setState('loading');
3723
3724 // Query Geocoder.
3725 geocoder.geocode({
3726 address: address
3727 }, function (results, status) {
3728 //console.log('searchPosition', arguments );
3729
3730 // End Loading.
3731 this.setState('');
3732
3733 // Status failure.
3734 if (status !== 'OK') {
3735 this.showNotice({
3736 text: acf.__('Location not found: %s').replace('%s', status),
3737 type: 'warning'
3738 });
3739
3740 // Success.
3741 } else {
3742 var val = this.parseResult(results[0]);
3743
3744 // Override address data with parameter allowing custom address to be defined in search.
3745 val.address = address;
3746
3747 // Update value.
3748 this.val(val);
3749 }
3750 }.bind(this));
3751 },
3752 searchLocation: function () {
3753 //console.log('searchLocation' );
3754
3755 // Check HTML5 geolocation.
3756 if (!navigator.geolocation) {
3757 return alert(acf.__('Sorry, this browser does not support geolocation'));
3758 }
3759
3760 // Start Loading.
3761 this.setState('loading');
3762
3763 // Query Geolocation.
3764 navigator.geolocation.getCurrentPosition(
3765 // Success.
3766 function (results) {
3767 // End Loading.
3768 this.setState('');
3769
3770 // Search position.
3771 var lat = results.coords.latitude;
3772 var lng = results.coords.longitude;
3773 this.searchPosition(lat, lng);
3774 }.bind(this),
3775 // Failure.
3776 function (error) {
3777 this.setState('');
3778 }.bind(this));
3779 },
3780 /**
3781 * parseResult
3782 *
3783 * Returns location data for the given GeocoderResult object.
3784 *
3785 * @date 15/10/19
3786 * @since ACF 5.8.6
3787 *
3788 * @param object obj A GeocoderResult object.
3789 * @return object
3790 */
3791 parseResult: function (obj) {
3792 // Construct basic data.
3793 var result = {
3794 address: obj.formatted_address,
3795 lat: obj.geometry.location.lat(),
3796 lng: obj.geometry.location.lng()
3797 };
3798
3799 // Add zoom level.
3800 result.zoom = this.map.getZoom();
3801
3802 // Add place ID.
3803 if (obj.place_id) {
3804 result.place_id = obj.place_id;
3805 }
3806
3807 // Add place name.
3808 if (obj.name) {
3809 result.name = obj.name;
3810 }
3811
3812 // Create search map for address component data.
3813 var map = {
3814 street_number: ['street_number'],
3815 street_name: ['street_address', 'route'],
3816 city: ['locality', 'postal_town'],
3817 state: ['administrative_area_level_1', 'administrative_area_level_2', 'administrative_area_level_3', 'administrative_area_level_4', 'administrative_area_level_5'],
3818 post_code: ['postal_code'],
3819 country: ['country']
3820 };
3821
3822 // Loop over map.
3823 for (var k in map) {
3824 var keywords = map[k];
3825
3826 // Loop over address components.
3827 for (var i = 0; i < obj.address_components.length; i++) {
3828 var component = obj.address_components[i];
3829 var component_type = component.types[0];
3830
3831 // Look for matching component type.
3832 if (keywords.indexOf(component_type) !== -1) {
3833 // Append to result.
3834 result[k] = component.long_name;
3835
3836 // Append short version.
3837 if (component.long_name !== component.short_name) {
3838 result[k + '_short'] = component.short_name;
3839 }
3840 }
3841 }
3842 }
3843
3844 /**
3845 * Filters the parsed result.
3846 *
3847 * @date 18/10/19
3848 * @since ACF 5.8.6
3849 *
3850 * @param object result The parsed result value.
3851 * @param object obj The GeocoderResult object.
3852 */
3853 return acf.applyFilters('google_map_result', result, obj, this.map, this);
3854 },
3855 onClickClear: function () {
3856 this.val(false);
3857 },
3858 onClickLocate: function () {
3859 this.searchLocation();
3860 },
3861 onClickSearch: function () {
3862 this.searchAddress(this.$search().val());
3863 },
3864 onFocusSearch: function (event, searchInput) {
3865 const currentValue = this.val();
3866 const currentAddress = currentValue ? currentValue.address : '';
3867 if (searchInput.val() !== currentAddress) {
3868 this.setState('searching');
3869 }
3870 },
3871 onBlurSearch: function (e, $el) {
3872 // Get saved address value.
3873 var val = this.val();
3874 var address = val ? val.address : '';
3875
3876 // Remove 'is-searching' if value has not changed.
3877 if ($el.val() === address) {
3878 this.setState('default');
3879 }
3880 },
3881 onKeyupSearch: function (e, $el) {
3882 const val = this.val();
3883 const address = val ? val.address : '';
3884 if ($el.val()) {
3885 // If search input has value
3886 if ($el.val() !== address) {
3887 this.setState('searching');
3888 } else {
3889 this.setState('default');
3890 }
3891 } else {
3892 // If search input is empty
3893 this.val(false);
3894 this.setState('default');
3895 }
3896 },
3897 // Prevent form from submitting.
3898 onKeydownSearch: function (e, $el) {
3899 if (e.which == 13) {
3900 e.preventDefault();
3901 $el.blur();
3902 }
3903 },
3904 // Center map once made visible.
3905 onShow: function () {
3906 if (this.map) {
3907 this.setTimeout(this.center);
3908 }
3909 }
3910 });
3911 acf.registerFieldType(Field);
3912
3913 // Vars.
3914 var loading = false;
3915 var geocoder = false;
3916
3917 /**
3918 * withAPI
3919 *
3920 * Loads the Google Maps API library and triggers callback.
3921 *
3922 * @date 28/3/19
3923 * @since ACF 5.7.14
3924 *
3925 * @param function callback The callback to execute.
3926 * @return void
3927 */
3928
3929 function withAPI(callback) {
3930 // Check if geocoder exists.
3931 if (geocoder) {
3932 return callback();
3933 }
3934
3935 // Check if geocoder API exists.
3936 if (acf.isset(window, 'google', 'maps', 'Geocoder')) {
3937 geocoder = new google.maps.Geocoder();
3938 return callback();
3939 }
3940
3941 // Geocoder will need to be loaded. Hook callback to action.
3942 acf.addAction('google_map_api_loaded', callback);
3943
3944 // Bail early if already loading API.
3945 if (loading) {
3946 return;
3947 }
3948
3949 // load api
3950 var url = acf.get('google_map_api');
3951 if (url) {
3952 // Set loading status.
3953 loading = true;
3954
3955 // Load API
3956 $.ajax({
3957 url: url,
3958 dataType: 'script',
3959 cache: true,
3960 success: function () {
3961 geocoder = new google.maps.Geocoder();
3962 acf.doAction('google_map_api_loaded');
3963 }
3964 });
3965 }
3966 }
3967 })(jQuery);
3968
3969 /***/ }),
3970
3971 /***/ "./assets/src/js/_acf-field-icon-picker.js":
3972 /*!*************************************************!*\
3973 !*** ./assets/src/js/_acf-field-icon-picker.js ***!
3974 \*************************************************/
3975 /***/ (() => {
3976
3977 (function ($, undefined) {
3978 const Field = acf.Field.extend({
3979 type: 'icon_picker',
3980 wait: 'load',
3981 events: {
3982 showField: 'scrollToSelectedIcon',
3983 'input .acf-icon_url': 'onUrlChange',
3984 'click .acf-icon-picker-list-icon': 'onIconClick',
3985 'focus .acf-icon-picker-list-icon-radio': 'onIconRadioFocus',
3986 'blur .acf-icon-picker-list-icon-radio': 'onIconRadioBlur',
3987 'keydown .acf-icon-picker-list-icon-radio': 'onIconKeyDown',
3988 'input .acf-icon-list-search-input': 'onIconSearch',
3989 'keydown .acf-icon-list-search-input': 'onIconSearchKeyDown',
3990 'click .acf-icon-picker-media-library-button': 'onMediaLibraryButtonClick',
3991 'click .acf-icon-picker-media-library-preview': 'onMediaLibraryButtonClick'
3992 },
3993 $typeInput() {
3994 return this.$('input[type="hidden"][data-hidden-type="type"]:first');
3995 },
3996 $valueInput() {
3997 return this.$('input[type="hidden"][data-hidden-type="value"]:first');
3998 },
3999 $tabButton() {
4000 return this.$('.acf-tab-button');
4001 },
4002 $selectedIcon() {
4003 return this.$('.acf-icon-picker-list-icon.active');
4004 },
4005 $selectedRadio() {
4006 return this.$('.acf-icon-picker-list-icon.active input');
4007 },
4008 $iconsList() {
4009 return this.$('.acf-icon-list:visible');
4010 },
4011 $mediaLibraryButton() {
4012 return this.$('.acf-icon-picker-media-library-button');
4013 },
4014 $mediaLibraryPreviewImg() {
4015 return this.$('.acf-icon-picker-media-library-preview-img img');
4016 },
4017 getValue() {
4018 return {
4019 type: this.$typeInput().val(),
4020 value: this.$valueInput().val()
4021 };
4022 },
4023 setValue(val) {
4024 if (!val || typeof val !== 'object') {
4025 val = {
4026 type: '',
4027 value: ''
4028 };
4029 }
4030 const type = val.type || '';
4031 const value = val.value || '';
4032 this.updateTypeAndValue(type, value);
4033 if (type) {
4034 this.$tabButton().filter(`[data-unique-tab-key="${type}"]`).trigger('click');
4035 const $iconsList = this.$(`.acf-icon-list[data-parent-tab="${type}"]`);
4036 if ($iconsList.length) {
4037 $iconsList.find('.acf-icon-picker-list-icon.active').removeClass('active');
4038 $iconsList.find('input:checked').prop('checked', false);
4039 const $icon = $iconsList.find(`.acf-icon-picker-list-icon[data-icon="${value}"]`);
4040 if ($icon.length) {
4041 $icon.addClass('active');
4042 $icon.find('input').prop('checked', true);
4043 this.set('selectedIcon', value);
4044 }
4045 }
4046 }
4047 if (type === 'url') {
4048 this.$('.acf-icon_url').val(value);
4049 }
4050 if (type === 'media_library' && value && window.wp?.media?.attachment) {
4051 const attachment = wp.media.attachment(value);
4052 attachment.fetch().then(() => {
4053 const url = attachment.get('url');
4054 if (url) {
4055 this.set('mediaLibraryPreviewUrl', url);
4056 this.$mediaLibraryPreviewImg().attr('src', url);
4057 }
4058 });
4059 }
4060 },
4061 initialize() {
4062 // Set up actions hook callbacks.
4063 this.addActions();
4064
4065 // Initialize the state of the icon picker.
4066 let typeAndValue = {
4067 type: this.$typeInput().val(),
4068 value: this.$valueInput().val()
4069 };
4070
4071 // Store the type and value object.
4072 this.set('typeAndValue', typeAndValue);
4073 if (typeAndValue.type === 'media_library') {
4074 const previewUrl = this.$mediaLibraryPreviewImg().attr('src');
4075 if (previewUrl) {
4076 this.set('mediaLibraryPreviewUrl', previewUrl);
4077 }
4078 }
4079
4080 // Any time any acf tab is clicked, we will re-scroll to the selected icon.
4081 $('.acf-tab-button').on('click', () => {
4082 this.initializeIconLists(this.get('typeAndValue'));
4083 });
4084
4085 // Fire the action which lets people know the state has been updated.
4086 acf.doAction(this.get('name') + '/type_and_value_change', typeAndValue);
4087 this.initializeIconLists(typeAndValue);
4088 this.alignMediaLibraryTabToCurrentValue(typeAndValue);
4089 },
4090 addActions() {
4091 // Set up an action listener for when the type and value changes.
4092 acf.addAction(this.get('name') + '/type_and_value_change', newTypeAndValue => {
4093 const currentType = this.$typeInput().val();
4094 const currentValue = this.$valueInput().val();
4095 if (currentType === newTypeAndValue.type && currentValue === newTypeAndValue.value) {
4096 this.alignIconListTabsToCurrentValue(newTypeAndValue);
4097 this.alignMediaLibraryTabToCurrentValue(newTypeAndValue);
4098 this.alignUrlTabToCurrentValue(newTypeAndValue);
4099 } else {
4100 const currentTypeAndValue = this.get('typeAndValue');
4101 if (currentTypeAndValue) {
4102 this.alignIconListTabsToCurrentValue(currentTypeAndValue);
4103 this.alignMediaLibraryTabToCurrentValue(currentTypeAndValue);
4104 this.alignUrlTabToCurrentValue(currentTypeAndValue);
4105 }
4106 }
4107 });
4108 },
4109 updateTypeAndValue(type, value) {
4110 const typeAndValue = {
4111 type,
4112 value
4113 };
4114
4115 // Update the values in the hidden fields, which are what will actually be saved.
4116 acf.val(this.$typeInput(), type);
4117 acf.val(this.$valueInput(), value);
4118
4119 // Set the state.
4120 this.set('typeAndValue', typeAndValue);
4121
4122 // Fire an action to let each tab set itself according to the typeAndValue state.
4123 acf.doAction(this.get('name') + '/type_and_value_change', typeAndValue);
4124 },
4125 scrollToSelectedIcon() {
4126 const innerElement = this.$selectedIcon();
4127
4128 // If no icon is selected, do nothing.
4129 if (innerElement.length === 0) {
4130 return;
4131 }
4132 const scrollingDiv = innerElement.closest('.acf-icon-list');
4133 scrollingDiv.scrollTop(0);
4134 const distance = innerElement.position().top - 50;
4135 if (distance === 0) {
4136 return;
4137 }
4138 scrollingDiv.scrollTop(distance);
4139 },
4140 initializeIconLists(typeAndValue) {
4141 const self = this;
4142 this.$('.acf-icon-list').each(function (i) {
4143 const tabName = $(this).data('parent-tab');
4144 const icons = self.getIconsList(tabName) || [];
4145 self.set(tabName, icons);
4146 self.renderIconList($(this));
4147 if (typeAndValue.type === tabName) {
4148 // Select the correct icon.
4149 self.selectIcon($(this), typeAndValue.value, false).then(() => {
4150 // Scroll to the selected icon.
4151 self.scrollToSelectedIcon();
4152 });
4153 }
4154 });
4155 },
4156 alignIconListTabsToCurrentValue(typeAndValue) {
4157 const icons = this.$('.acf-icon-list').filter(function () {
4158 return $(this).data('parent-tab') !== typeAndValue.type;
4159 });
4160 const self = this;
4161 icons.each(function () {
4162 self.unselectIcon($(this));
4163 });
4164 },
4165 renderIconHTML(tabName, icon) {
4166 const id = `${this.get('name')}-${icon.key}`;
4167 let style = '';
4168 if ('dashicons' !== tabName) {
4169 style = `background: center / contain url( ${acf.strEscape(icon.url)} ) no-repeat;`;
4170 }
4171 return `<div class="${tabName} ${acf.strEscape(icon.key)} acf-icon-picker-list-icon" role="radio" data-icon="${acf.strEscape(icon.key)}" style="${style}" title="${acf.strEscape(icon.label)}">
4172 <label for="${acf.strEscape(id)}">${acf.strEscape(icon.label)}</label>
4173 <input id="${acf.strEscape(id)}" type="radio" class="acf-icon-picker-list-icon-radio" name="acf-icon-picker-list-icon-radio" value="${acf.strEscape(icon.key)}">
4174 </div>`;
4175 },
4176 renderIconList($el) {
4177 const tabName = $el.data('parent-tab');
4178 const icons = this.get(tabName);
4179 $el.empty();
4180 if (icons) {
4181 icons.forEach(icon => {
4182 const iconHTML = this.renderIconHTML(tabName, icon);
4183 $el.append(iconHTML);
4184 });
4185 }
4186 },
4187 getIconsList(tabName) {
4188 let icons;
4189 if ('dashicons' === tabName) {
4190 const iconPickeri10n = acf.get('iconPickeri10n') || [];
4191 icons = Object.entries(iconPickeri10n).map(([key, label]) => ({
4192 key,
4193 label
4194 }));
4195 } else {
4196 const iconList = this.$(`.acf-icon-list[data-parent-tab="${tabName}"]`);
4197 if (iconList.length !== 0) {
4198 const iconsData = iconList.data('icons');
4199 icons = Array.isArray(iconsData) ? iconsData : [];
4200 }
4201 }
4202 return icons;
4203 },
4204 getIconsBySearch(searchTerm, tabName) {
4205 const lowercaseSearchTerm = searchTerm.toLowerCase();
4206 const icons = this.getIconsList(tabName);
4207 const filteredIcons = icons.filter(function (icon) {
4208 const lowercaseIconLabel = icon.label.toLowerCase();
4209 return lowercaseIconLabel.indexOf(lowercaseSearchTerm) > -1;
4210 });
4211 return filteredIcons;
4212 },
4213 selectIcon($el, icon, setFocus = true) {
4214 this.set('selectedIcon', icon);
4215
4216 // Select the new one.
4217 const $newIcon = $el.find('.acf-icon-picker-list-icon[data-icon="' + icon + '"]');
4218 $newIcon.addClass('active');
4219 const $input = $newIcon.find('input');
4220 const thePromise = $input.prop('checked', true).promise();
4221 if (setFocus) {
4222 $input.trigger('focus');
4223 }
4224 this.updateTypeAndValue($el.data('parent-tab'), icon);
4225 return thePromise;
4226 },
4227 unselectIcon($el) {
4228 // Remove the currently active dashicon, if any.
4229 $el.find('.acf-icon-picker-list-icon').removeClass('active');
4230 this.set('selectedIcon', false);
4231 },
4232 onIconRadioFocus(e) {
4233 const icon = e.target.value;
4234 const $tabs = this.$(e.target).closest('.acf-icon-picker-tabs');
4235 const $iconsList = $tabs.find('.acf-icon-list');
4236 const $newIcon = $iconsList.find('.acf-icon-picker-list-icon[data-icon="' + icon + '"]');
4237 $newIcon.addClass('focus');
4238
4239 // If this is a different icon than previously selected, select it.
4240 if (this.get('selectedIcon') !== icon) {
4241 this.unselectIcon($iconsList);
4242 this.selectIcon($iconsList, icon);
4243 }
4244 },
4245 onIconRadioBlur(e) {
4246 const icon = this.$(e.target);
4247 const iconParent = icon.parent();
4248 iconParent.removeClass('focus');
4249 },
4250 onIconClick(e) {
4251 e.preventDefault();
4252 const $iconList = this.$(e.target).closest('.acf-icon-list');
4253 const $iconElement = this.$(e.target);
4254 const icon = $iconElement.find('input').val();
4255 const $newIconElement = $iconList.find('.acf-icon-picker-list-icon[data-icon="' + icon + '"]');
4256
4257 // By forcing focus on the input, we fire onIconRadioFocus.
4258 $newIconElement.find('input').prop('checked', true).trigger('focus');
4259 },
4260 onIconSearch(e) {
4261 const $tabs = this.$(e.target).closest('.acf-icon-picker-tabs');
4262 const $iconList = $tabs.find('.acf-icon-list');
4263 const tabName = $tabs.data('tab');
4264 const searchTerm = e.target.value;
4265 const filteredIcons = this.getIconsBySearch(searchTerm, tabName);
4266 if (filteredIcons.length > 0 || !searchTerm) {
4267 this.set(tabName, filteredIcons);
4268 $tabs.find('.acf-icon-list-empty').hide();
4269 $tabs.find('.acf-icon-list ').show();
4270 this.renderIconList($iconList);
4271
4272 // Announce change of data to screen readers.
4273 wp.a11y.speak(acf.get('iconPickerA11yStrings').newResultsFoundForSearchTerm, 'polite');
4274 } else {
4275 // Truncate the search term if it's too long.
4276 const visualSearchTerm = searchTerm.length > 30 ? searchTerm.substring(0, 30) + '&hellip;' : searchTerm;
4277 $tabs.find('.acf-icon-list ').hide();
4278 $tabs.find('.acf-icon-list-empty').find('.acf-invalid-icon-list-search-term').text(visualSearchTerm);
4279 $tabs.find('.acf-icon-list-empty').css('display', 'flex');
4280 $tabs.find('.acf-icon-list-empty').show();
4281
4282 // Announce change of data to screen readers.
4283 wp.a11y.speak(acf.get('iconPickerA11yStrings').noResultsForSearchTerm, 'polite');
4284 }
4285 },
4286 onIconSearchKeyDown(e) {
4287 // Check if the pressed key is Enter (key code 13)
4288 if (e.which === 13) {
4289 // Prevent submitting the entire form if someone presses enter after searching.
4290 e.preventDefault();
4291 }
4292 },
4293 onIconKeyDown(e) {
4294 if (e.which === 13) {
4295 // If someone presses enter while an icon is focused, prevent the form from submitting.
4296 e.preventDefault();
4297 }
4298 },
4299 alignMediaLibraryTabToCurrentValue(typeAndValue) {
4300 const type = typeAndValue.type;
4301 const value = typeAndValue.value;
4302 if (type !== 'media_library' && type !== 'dashicons') {
4303 // Hide the preview container on the media library tab.
4304 this.$('.acf-icon-picker-media-library-preview').hide();
4305 }
4306 if (type === 'media_library') {
4307 const previewUrl = this.get('mediaLibraryPreviewUrl');
4308 // Set the image file preview src.
4309 this.$('.acf-icon-picker-media-library-preview-img img').attr('src', previewUrl);
4310
4311 // Hide the dashicon preview.
4312 this.$('.acf-icon-picker-media-library-preview-dashicon').hide();
4313
4314 // Show the image file preview.
4315 this.$('.acf-icon-picker-media-library-preview-img').show();
4316
4317 // Show the preview container (it may have been hidden if nothing was ever selected yet).
4318 this.$('.acf-icon-picker-media-library-preview').show();
4319 }
4320 if (type === 'dashicons') {
4321 // Set the dashicon preview class.
4322 this.$('.acf-icon-picker-media-library-preview-dashicon .dashicons').attr('class', 'dashicons ' + value);
4323
4324 // Hide the image file preview.
4325 this.$('.acf-icon-picker-media-library-preview-img').hide();
4326
4327 // Show the dashicon preview.
4328 this.$('.acf-icon-picker-media-library-preview-dashicon').show();
4329
4330 // Show the preview container (it may have been hidden if nothing was ever selected yet).
4331 this.$('.acf-icon-picker-media-library-preview').show();
4332 }
4333 },
4334 async onMediaLibraryButtonClick(e) {
4335 e.preventDefault();
4336 await this.selectAndReturnAttachment().then(attachment => {
4337 // When an attachment is selected, update the preview and the hidden fields.
4338 this.set('mediaLibraryPreviewUrl', attachment.attributes.url);
4339 this.updateTypeAndValue('media_library', attachment.id);
4340 });
4341 },
4342 selectAndReturnAttachment() {
4343 return new Promise(resolve => {
4344 acf.newMediaPopup({
4345 mode: 'select',
4346 type: 'image',
4347 title: acf.__('Select Image'),
4348 field: this.get('key'),
4349 multiple: false,
4350 library: 'all',
4351 allowedTypes: 'image',
4352 select: resolve
4353 });
4354 });
4355 },
4356 alignUrlTabToCurrentValue(typeAndValue) {
4357 if (typeAndValue.type !== 'url') {
4358 this.$('.acf-icon_url').val('');
4359 }
4360 },
4361 onUrlChange(event) {
4362 const currentValue = event.target.value;
4363 this.updateTypeAndValue('url', currentValue);
4364 }
4365 });
4366 acf.registerFieldType(Field);
4367 })(jQuery);
4368
4369 /***/ }),
4370
4371 /***/ "./assets/src/js/_acf-field-image.js":
4372 /*!*******************************************!*\
4373 !*** ./assets/src/js/_acf-field-image.js ***!
4374 \*******************************************/
4375 /***/ (() => {
4376
4377 (function ($) {
4378 const Field = acf.Field.extend({
4379 type: 'image',
4380 $control: function () {
4381 return this.$('.acf-image-uploader');
4382 },
4383 $input: function () {
4384 return this.$('input[type="hidden"]:first');
4385 },
4386 events: {
4387 'click a[data-name="add"]': 'onClickAdd',
4388 'click a[data-name="edit"]': 'onClickEdit',
4389 'click a[data-name="remove"]': 'onClickRemove',
4390 'change input[type="file"]': 'onChange',
4391 'keydown .image-wrap': 'onImageWrapKeydown'
4392 },
4393 initialize: function () {
4394 // add attribute to form
4395 if (this.get('uploader') === 'basic') {
4396 this.$el.closest('form').attr('enctype', 'multipart/form-data');
4397 }
4398 },
4399 validateAttachment: function (attachment) {
4400 // Use WP attachment attributes when available.
4401 if (attachment && attachment.attributes) {
4402 attachment = attachment.attributes;
4403 }
4404
4405 // Apply defaults.
4406 attachment = acf.parseArgs(attachment, {
4407 id: 0,
4408 url: '',
4409 alt: '',
4410 title: '',
4411 caption: '',
4412 description: '',
4413 width: 0,
4414 height: 0
4415 });
4416
4417 // Override with "preview size".
4418 const size = acf.isget(attachment, 'sizes', this.get('preview_size'));
4419 if (size) {
4420 attachment.url = size.url;
4421 attachment.width = size.width;
4422 attachment.height = size.height;
4423 }
4424
4425 // Return.
4426 return attachment;
4427 },
4428 render: function (attachment) {
4429 attachment = this.validateAttachment(attachment);
4430
4431 // Update value.
4432 acf.val(this.$input(), String(attachment.id || ''), true);
4433
4434 // Update DOM.
4435 this.$('img').attr({
4436 src: attachment.url,
4437 alt: attachment.alt
4438 });
4439 if (attachment.id) {
4440 this.$control().addClass('has-value');
4441 const imageWrap = this.$('.image-wrap');
4442 if (imageWrap.length) {
4443 imageWrap.trigger('focus');
4444 }
4445 } else {
4446 this.$control().removeClass('has-value');
4447 }
4448 },
4449 // create a new repeater row and render value
4450 append: function (attachment, parent) {
4451 // create function to find next available field within parent
4452 const getNext = function (field, parent) {
4453 // find existing file fields within parent
4454 const fields = acf.getFields({
4455 key: field.get('key'),
4456 parent: parent.$el
4457 });
4458
4459 // find the first field with no value
4460 for (let i = 0; i < fields.length; i++) {
4461 if (!fields[i].val()) {
4462 return fields[i];
4463 }
4464 }
4465
4466 // return
4467 return false;
4468 };
4469
4470 // find existing file fields within parent
4471 let field = getNext(this, parent);
4472
4473 // add new row if no available field
4474 if (!field) {
4475 parent.$('.acf-button:last').trigger('click');
4476 field = getNext(this, parent);
4477 }
4478
4479 // render
4480 if (field) {
4481 acf.val(field.$input(), String(attachment.id || attachment.attributes?.id || ''));
4482 field.render(attachment);
4483 }
4484 },
4485 selectAttachment: function () {
4486 // vars
4487 const parent = this.parent();
4488 const multiple = parent && parent.get('type') === 'repeater';
4489
4490 // new frame
4491 const frame = acf.newMediaPopup({
4492 mode: 'select',
4493 type: 'image',
4494 title: acf.__('Select Image'),
4495 field: this.get('key'),
4496 multiple: multiple,
4497 library: this.get('library'),
4498 allowedTypes: this.get('mime_types'),
4499 select: $.proxy(function (attachment, i) {
4500 if (i > 0) {
4501 this.append(attachment, parent);
4502 } else {
4503 acf.val(this.$input(), String(attachment.id || attachment.attributes?.id || ''));
4504 this.render(attachment);
4505 }
4506 }, this)
4507 });
4508 },
4509 editAttachment: function (attachment) {
4510 // vars
4511 const val = this.val();
4512 if (val) {
4513 // popup
4514 var frame = acf.newMediaPopup({
4515 mode: 'edit',
4516 title: acf.__('Edit Image'),
4517 button: acf.__('Update Image'),
4518 attachment: val,
4519 field: this.get('key'),
4520 select: $.proxy(function (attachment) {
4521 acf.val(this.$input(), String(attachment.id || attachment.attributes?.id || ''));
4522 this.render(attachment);
4523 }, this),
4524 close: $.proxy(function () {
4525 if ('edit-button' === attachment) {
4526 const edit = this.$el.find('a[data-name="edit"]');
4527 if (edit.length) {
4528 edit.trigger('focus');
4529 }
4530 } else {
4531 const imageWrap = this.$('.image-wrap');
4532 if (imageWrap.length) {
4533 imageWrap.trigger('focus');
4534 }
4535 }
4536 }, this)
4537 });
4538 }
4539 },
4540 removeAttachment: function () {
4541 acf.val(this.$input(), '');
4542 this.render(false);
4543 },
4544 onClickAdd: function (e, $el) {
4545 this.selectAttachment();
4546 },
4547 onClickEdit: function (e, $el) {
4548 this.editAttachment('edit-button');
4549 },
4550 onClickRemove: function (e, $el) {
4551 this.removeAttachment();
4552 },
4553 onChange: function (e, $el) {
4554 const $hiddenInput = this.$input();
4555 if (!$el.val()) {
4556 $hiddenInput.val('');
4557 }
4558 acf.getFileInputData($el, function (data) {
4559 $hiddenInput.val($.param(data));
4560 });
4561 },
4562 setValue: function (val) {
4563 val = val ? String(val) : '';
4564 if (acf.val(this.$input(), val, true) === false) {
4565 return;
4566 }
4567 if (val) {
4568 if (window.wp && wp.media && wp.media.attachment) {
4569 const attachment = wp.media.attachment(val);
4570 attachment.fetch().then($.proxy(function () {
4571 this.render(attachment);
4572 }, this));
4573 } else {
4574 this.$control().addClass('has-value');
4575 }
4576 } else {
4577 this.render(false);
4578 }
4579 },
4580 onImageWrapKeydown: function (event, imageWrapElement) {
4581 // Check if Enter key was pressed (keycode 13)
4582 if (event.which === 13) {
4583 // Check if the event target is the imageWrapElement itself
4584 if (event.target === imageWrapElement[0]) {
4585 // Prevent the default Enter key behavior
4586 event.preventDefault();
4587
4588 // Check if the field has a value
4589 if (this.val()) {
4590 // Check if the uploader is NOT the basic uploader
4591 if (this.get('uploader') !== 'basic') {
4592 // Open the edit attachment dialog
4593 this.editAttachment();
4594 }
4595 }
4596 }
4597 }
4598 }
4599 });
4600 acf.registerFieldType(Field);
4601 })(jQuery);
4602
4603 /***/ }),
4604
4605 /***/ "./assets/src/js/_acf-field-link.js":
4606 /*!******************************************!*\
4607 !*** ./assets/src/js/_acf-field-link.js ***!
4608 \******************************************/
4609 /***/ (() => {
4610
4611 (function ($, undefined) {
4612 var Field = acf.Field.extend({
4613 type: 'link',
4614 events: {
4615 'click a[data-name="add"]': 'onClickEdit',
4616 'click a[data-name="edit"]': 'onClickEdit',
4617 'click a[data-name="remove"]': 'onClickRemove',
4618 'change .link-node': 'onChange'
4619 },
4620 $control: function () {
4621 return this.$('.acf-link');
4622 },
4623 $node: function () {
4624 return this.$('.link-node');
4625 },
4626 getValue: function () {
4627 // vars
4628 var $node = this.$node();
4629
4630 // return false if empty
4631 if (!$node.attr('href')) {
4632 return false;
4633 }
4634
4635 // return
4636 return {
4637 title: $node.html(),
4638 url: $node.attr('href'),
4639 target: $node.attr('target')
4640 };
4641 },
4642 setValue: function (val) {
4643 // default
4644 val = acf.parseArgs(val, {
4645 title: '',
4646 url: '',
4647 target: ''
4648 });
4649
4650 // vars
4651 var $div = this.$control();
4652 var $node = this.$node();
4653
4654 // remove class
4655 $div.removeClass('-value -external');
4656
4657 // add class
4658 if (val.url) $div.addClass('-value');
4659 if (val.target === '_blank') $div.addClass('-external');
4660
4661 // update text
4662 this.$('.link-title').html(val.title);
4663 this.$('.link-url').attr('href', val.url).text(val.url);
4664
4665 // update node
4666 $node.html(val.title);
4667 $node.attr('href', val.url);
4668 $node.attr('target', val.target);
4669
4670 // update inputs
4671 this.$('.input-title').val(val.title);
4672 this.$('.input-target').val(val.target);
4673 this.$('.input-url').val(val.url).trigger('change');
4674 },
4675 onClickEdit: function (e, $el) {
4676 acf.wpLink.open(this.$node());
4677 },
4678 onClickRemove: function (e, $el) {
4679 this.setValue(false);
4680 },
4681 onChange: function (e, $el) {
4682 // get the changed value
4683 var val = this.getValue();
4684
4685 // update inputs
4686 this.setValue(val);
4687 }
4688 });
4689 acf.registerFieldType(Field);
4690
4691 // manager
4692 acf.wpLink = new acf.Model({
4693 getNodeValue: function () {
4694 var $node = this.get('node');
4695 return {
4696 title: acf.decode($node.html()),
4697 url: $node.attr('href'),
4698 target: $node.attr('target')
4699 };
4700 },
4701 setNodeValue: function (val) {
4702 var $node = this.get('node');
4703 $node.text(val.title);
4704 $node.attr('href', val.url);
4705 $node.attr('target', val.target);
4706 $node.trigger('change');
4707 },
4708 getInputValue: function () {
4709 return {
4710 title: $('#wp-link-text').val(),
4711 url: $('#wp-link-url').val(),
4712 target: $('#wp-link-target').prop('checked') ? '_blank' : ''
4713 };
4714 },
4715 setInputValue: function (val) {
4716 $('#wp-link-text').val(val.title);
4717 $('#wp-link-url').val(val.url);
4718 $('#wp-link-target').prop('checked', val.target === '_blank');
4719 },
4720 open: function ($node) {
4721 // add events
4722 this.on('wplink-open', 'onOpen');
4723 this.on('wplink-close', 'onClose');
4724
4725 // set node
4726 this.set('node', $node);
4727
4728 // create textarea
4729 var $textarea = $('<textarea id="acf-link-textarea" style="display:none;"></textarea>');
4730 $('body').append($textarea);
4731
4732 // vars
4733 var val = this.getNodeValue();
4734
4735 // open popup
4736 wpLink.open('acf-link-textarea', val.url, val.title, null);
4737 },
4738 onOpen: function () {
4739 // always show title (WP will hide title if empty)
4740 $('#wp-link-wrap').addClass('has-text-field');
4741
4742 // set inputs
4743 var val = this.getNodeValue();
4744 this.setInputValue(val);
4745
4746 // Update button text.
4747 if (val.url && wpLinkL10n) {
4748 $('#wp-link-submit').val(wpLinkL10n.update);
4749 }
4750 },
4751 close: function () {
4752 wpLink.close();
4753 },
4754 onClose: function () {
4755 // Bail early if no node.
4756 // Needed due to WP triggering this event twice.
4757 if (!this.has('node')) {
4758 return false;
4759 }
4760
4761 // Determine context.
4762 var $submit = $('#wp-link-submit');
4763 var isSubmit = $submit.is(':hover') || $submit.is(':focus');
4764
4765 // Set value
4766 if (isSubmit) {
4767 var val = this.getInputValue();
4768 this.setNodeValue(val);
4769 }
4770
4771 // Cleanup.
4772 this.off('wplink-open');
4773 this.off('wplink-close');
4774 $('#acf-link-textarea').remove();
4775 this.set('node', null);
4776 }
4777 });
4778 })(jQuery);
4779
4780 /***/ }),
4781
4782 /***/ "./assets/src/js/_acf-field-oembed.js":
4783 /*!********************************************!*\
4784 !*** ./assets/src/js/_acf-field-oembed.js ***!
4785 \********************************************/
4786 /***/ (() => {
4787
4788 (function ($, undefined) {
4789 var Field = acf.Field.extend({
4790 type: 'oembed',
4791 events: {
4792 'click [data-name="clear-button"]': 'onClickClear',
4793 'keypress .input-search': 'onKeypressSearch',
4794 'keyup .input-search': 'onKeyupSearch',
4795 'change .input-search': 'onChangeSearch'
4796 },
4797 $control: function () {
4798 return this.$('.acf-oembed');
4799 },
4800 $input: function () {
4801 return this.$('.input-value');
4802 },
4803 $search: function () {
4804 return this.$('.input-search');
4805 },
4806 getValue: function () {
4807 return this.$input().val();
4808 },
4809 getSearchVal: function () {
4810 return this.$search().val();
4811 },
4812 setValue: function (val) {
4813 // class
4814 if (val) {
4815 this.$control().addClass('has-value');
4816 } else {
4817 this.$control().removeClass('has-value');
4818 }
4819 acf.val(this.$input(), val);
4820 this.$search().val(val || '');
4821 if (val) {
4822 this.maybeSearch();
4823 } else {
4824 this.$('.canvas-media').html('');
4825 }
4826 },
4827 showLoading: function (show) {
4828 acf.showLoading(this.$('.canvas'));
4829 },
4830 hideLoading: function () {
4831 acf.hideLoading(this.$('.canvas'));
4832 },
4833 maybeSearch: function () {
4834 // vars
4835 var prevUrl = this.val();
4836 var url = this.getSearchVal();
4837
4838 // no value
4839 if (!url) {
4840 return this.clear();
4841 }
4842
4843 // fix missing 'http://' - causes the oembed code to error and fail
4844 if (url.substr(0, 4) != 'http') {
4845 url = 'http://' + url;
4846 }
4847
4848 // bail early if no change
4849 if (url === prevUrl) return;
4850
4851 // clear existing timeout
4852 var timeout = this.get('timeout');
4853 if (timeout) {
4854 clearTimeout(timeout);
4855 }
4856
4857 // set new timeout
4858 var callback = $.proxy(this.search, this, url);
4859 this.set('timeout', setTimeout(callback, 300));
4860 },
4861 search: function (url) {
4862 const ajaxData = {
4863 action: 'acf/fields/oembed/search',
4864 s: url,
4865 field_key: this.get('key'),
4866 nonce: this.get('nonce')
4867 };
4868
4869 // clear existing timeout
4870 let xhr = this.get('xhr');
4871 if (xhr) {
4872 xhr.abort();
4873 }
4874
4875 // loading
4876 this.showLoading();
4877
4878 // query
4879 xhr = $.ajax({
4880 url: acf.get('ajaxurl'),
4881 data: acf.prepareForAjax(ajaxData),
4882 type: 'post',
4883 dataType: 'json',
4884 context: this,
4885 success: function (json) {
4886 // error
4887 if (!json || !json.html) {
4888 json = {
4889 url: false,
4890 html: ''
4891 };
4892 }
4893
4894 // update vars
4895 this.val(json.url);
4896 this.$('.canvas-media').html(json.html);
4897 },
4898 complete: function () {
4899 this.hideLoading();
4900 }
4901 });
4902 this.set('xhr', xhr);
4903 },
4904 clear: function () {
4905 this.val('');
4906 this.$search().val('');
4907 this.$('.canvas-media').html('');
4908 },
4909 onClickClear: function (e, $el) {
4910 this.clear();
4911 },
4912 onKeypressSearch: function (e, $el) {
4913 if (e.which == 13) {
4914 e.preventDefault();
4915 this.maybeSearch();
4916 }
4917 },
4918 onKeyupSearch: function (e, $el) {
4919 if ($el.val()) {
4920 this.maybeSearch();
4921 }
4922 },
4923 onChangeSearch: function (e, $el) {
4924 this.maybeSearch();
4925 }
4926 });
4927 acf.registerFieldType(Field);
4928 })(jQuery);
4929
4930 /***/ }),
4931
4932 /***/ "./assets/src/js/_acf-field-page-link.js":
4933 /*!***********************************************!*\
4934 !*** ./assets/src/js/_acf-field-page-link.js ***!
4935 \***********************************************/
4936 /***/ (() => {
4937
4938 (function ($, undefined) {
4939 var Field = acf.models.SelectField.extend({
4940 type: 'page_link'
4941 });
4942 acf.registerFieldType(Field);
4943 })(jQuery);
4944
4945 /***/ }),
4946
4947 /***/ "./assets/src/js/_acf-field-post-object.js":
4948 /*!*************************************************!*\
4949 !*** ./assets/src/js/_acf-field-post-object.js ***!
4950 \*************************************************/
4951 /***/ (() => {
4952
4953 (function ($, undefined) {
4954 var Field = acf.models.SelectField.extend({
4955 type: 'post_object'
4956 });
4957 acf.registerFieldType(Field);
4958 })(jQuery);
4959
4960 /***/ }),
4961
4962 /***/ "./assets/src/js/_acf-field-radio.js":
4963 /*!*******************************************!*\
4964 !*** ./assets/src/js/_acf-field-radio.js ***!
4965 \*******************************************/
4966 /***/ (() => {
4967
4968 (function ($, undefined) {
4969 var Field = acf.Field.extend({
4970 type: 'radio',
4971 events: {
4972 'click input[type="radio"]': 'onClick',
4973 'keydown input[type="radio"]': 'onKeyDownInput'
4974 },
4975 $control: function () {
4976 return this.$('.acf-radio-list');
4977 },
4978 $input: function () {
4979 return this.$('input:checked');
4980 },
4981 $inputText: function () {
4982 return this.$('input[type="text"]');
4983 },
4984 setValue: function (val) {
4985 this.$('.selected').removeClass('selected');
4986 this.$('input[type="radio"]').prop('checked', false);
4987 if (val !== false && val !== null && val !== '') {
4988 const $input = this.$('input[type="radio"]').filter(function () {
4989 return $(this).val() === val;
4990 });
4991 if ($input.length) {
4992 $input.prop('checked', true);
4993 $input.parent('label').addClass('selected');
4994 if (this.get('other_choice')) {
4995 if (val === 'other') {
4996 this.$inputText().prop('disabled', false);
4997 } else {
4998 this.$inputText().prop('disabled', true);
4999 }
5000 }
5001 }
5002 }
5003 },
5004 getValue: function () {
5005 var val = this.$input().val();
5006 if (val === 'other' && this.get('other_choice')) {
5007 val = this.$inputText().val();
5008 }
5009 return val;
5010 },
5011 onClick: function (e, $el) {
5012 // vars
5013 var $label = $el.parent('label');
5014 var selected = $label.hasClass('selected');
5015 var val = $el.val();
5016
5017 // remove previous selected
5018 this.$('.selected').removeClass('selected');
5019
5020 // add active class
5021 $label.addClass('selected');
5022
5023 // allow null
5024 if (this.get('allow_null') && selected) {
5025 $label.removeClass('selected');
5026 $el.prop('checked', false).trigger('change');
5027 val = false;
5028 }
5029
5030 // other
5031 if (this.get('other_choice')) {
5032 // enable
5033 if (val === 'other') {
5034 this.$inputText().prop('disabled', false);
5035
5036 // disable
5037 } else {
5038 this.$inputText().prop('disabled', true);
5039 }
5040 }
5041 },
5042 onKeyDownInput: function (event, input) {
5043 if (event.which === 13) {
5044 event.preventDefault();
5045 input.prop('checked', true).trigger('change');
5046 }
5047 }
5048 });
5049 acf.registerFieldType(Field);
5050 })(jQuery);
5051
5052 /***/ }),
5053
5054 /***/ "./assets/src/js/_acf-field-range.js":
5055 /*!*******************************************!*\
5056 !*** ./assets/src/js/_acf-field-range.js ***!
5057 \*******************************************/
5058 /***/ (() => {
5059
5060 (function ($, undefined) {
5061 var Field = acf.Field.extend({
5062 type: 'range',
5063 events: {
5064 'input input[type="range"]': 'onChange',
5065 'change input': 'onChange'
5066 },
5067 $input: function () {
5068 return this.$('input[type="range"]');
5069 },
5070 $inputAlt: function () {
5071 return this.$('input[type="number"]');
5072 },
5073 setValue: function (val) {
5074 this.busy = true;
5075
5076 // Update range input (with change).
5077 acf.val(this.$input(), val);
5078
5079 // Update alt input (without change).
5080 // Read in input value to inherit min/max validation.
5081 acf.val(this.$inputAlt(), this.$input().val(), true);
5082 this.busy = false;
5083 },
5084 onChange: function (e, $el) {
5085 if (!this.busy) {
5086 this.setValue($el.val());
5087 }
5088 }
5089 });
5090 acf.registerFieldType(Field);
5091 })(jQuery);
5092
5093 /***/ }),
5094
5095 /***/ "./assets/src/js/_acf-field-relationship.js":
5096 /*!**************************************************!*\
5097 !*** ./assets/src/js/_acf-field-relationship.js ***!
5098 \**************************************************/
5099 /***/ (() => {
5100
5101 (function ($, undefined) {
5102 var Field = acf.Field.extend({
5103 type: 'relationship',
5104 events: {
5105 'keypress [data-filter]': 'onKeypressFilter',
5106 'change [data-filter]': 'onChangeFilter',
5107 'keyup [data-filter]': 'onChangeFilter',
5108 'click .choices-list .acf-rel-item': 'onClickAdd',
5109 'keypress .choices-list .acf-rel-item': 'onKeypressFilter',
5110 'keypress .values-list .acf-rel-item': 'onKeypressFilter',
5111 'click [data-name="remove_item"]': 'onClickRemove',
5112 'touchstart .values-list .acf-rel-item': 'onTouchStartValues'
5113 },
5114 $control: function () {
5115 return this.$('.acf-relationship');
5116 },
5117 $list: function (list) {
5118 return this.$('.' + list + '-list');
5119 },
5120 $listItems: function (list) {
5121 return this.$list(list).find('.acf-rel-item');
5122 },
5123 $listItem: function (list, id) {
5124 return this.$list(list).find('.acf-rel-item').filter(function () {
5125 return String($(this).data('id')) === String(id);
5126 });
5127 },
5128 getValue: function () {
5129 var val = [];
5130 this.$listItems('values').each(function () {
5131 val.push($(this).data('id'));
5132 });
5133 return val.length ? val : false;
5134 },
5135 setValue: function (value) {
5136 if (!Array.isArray(value)) {
5137 value = value ? [value] : [];
5138 }
5139 this.$list('values').html('');
5140 this.$listItems('choices').removeClass('disabled');
5141 value.forEach(id => {
5142 const $choice = this.$listItem('choices', id);
5143 const text = $choice.length ? $choice.html() : acf.strEscape(String(id));
5144 $choice.addClass('disabled');
5145 const valueHtml = this.newValue({
5146 id,
5147 text
5148 });
5149 this.$list('values').append(valueHtml);
5150 });
5151 this.$input().trigger('change');
5152 },
5153 newChoice: function (props) {
5154 return ['<li>', '<span tabindex="0" data-id="' + acf.strEscape(String(props.id)) + '" class="acf-rel-item">' + props.text + '</span>', '</li>'].join('');
5155 },
5156 newValue: function (props) {
5157 const id = acf.strEscape(String(props.id));
5158 return ['<li>', '<input type="hidden" name="' + this.getInputName() + '[]" value="' + id + '" />', '<span tabindex="0" data-id="' + id + '" class="acf-rel-item acf-rel-item-remove">' + props.text, '<a href="#" class="acf-icon -minus small dark" data-name="remove_item"></a>', '</span>', '</li>'].join('');
5159 },
5160 initialize: function () {
5161 // Delay initialization until "interacted with" or "in view".
5162 var delayed = this.proxy(acf.once(function () {
5163 // Add sortable.
5164 this.$list('values').sortable({
5165 items: 'li',
5166 zIndex: 9999,
5167 forceHelperSize: true,
5168 forcePlaceholderSize: true,
5169 scroll: true,
5170 update: this.proxy(function () {
5171 this.$input().trigger('change');
5172 })
5173 });
5174
5175 // Avoid browser remembering old scroll position and add event.
5176 this.$list('choices').scrollTop(0).on('scroll', this.proxy(this.onScrollChoices));
5177
5178 // Fetch choices.
5179 this.fetch();
5180 }));
5181
5182 // Bind "interacted with".
5183 this.$el.one('mouseover', delayed);
5184 this.$el.one('focus', 'input', delayed);
5185
5186 // Bind "in view".
5187 acf.onceInView(this.$el, delayed);
5188 },
5189 onScrollChoices: function (e) {
5190 // bail early if no more results
5191 if (this.get('loading') || !this.get('more')) {
5192 return;
5193 }
5194
5195 // Scrolled to bottom
5196 var $list = this.$list('choices');
5197 var scrollTop = Math.ceil($list.scrollTop());
5198 var scrollHeight = Math.ceil($list[0].scrollHeight);
5199 var innerHeight = Math.ceil($list.innerHeight());
5200 var paged = this.get('paged') || 1;
5201 if (scrollTop + innerHeight >= scrollHeight) {
5202 // update paged
5203 this.set('paged', paged + 1);
5204
5205 // fetch
5206 this.fetch();
5207 }
5208 },
5209 onKeypressFilter: function (e, $el) {
5210 // Receive enter key when selecting relationship items.
5211 if ($el.hasClass('acf-rel-item-add') && e.which == 13) {
5212 this.onClickAdd(e, $el);
5213 }
5214 // Receive enter key when removing relationship items.
5215 if ($el.hasClass('acf-rel-item-remove') && e.which == 13) {
5216 this.onClickRemove(e, $el);
5217 }
5218 // don't submit form
5219 if (e.which == 13) {
5220 e.preventDefault();
5221 }
5222 },
5223 onChangeFilter: function (e, $el) {
5224 // vars
5225 var val = $el.val();
5226 var filter = $el.data('filter');
5227
5228 // Bail early if filter has not changed
5229 if (this.get(filter) === val) {
5230 return;
5231 }
5232
5233 // update attr
5234 this.set(filter, val);
5235 if (filter === 's') {
5236 // If val is numeric, limit results to include.
5237 if (parseInt(val)) {
5238 this.set('include', val);
5239 }
5240 }
5241
5242 // reset paged
5243 this.set('paged', 1);
5244
5245 // fetch
5246 if ($el.is('select')) {
5247 this.fetch();
5248
5249 // search must go through timeout
5250 } else {
5251 this.maybeFetch();
5252 }
5253 },
5254 onClickAdd: function (e, $el) {
5255 // vars
5256 var val = this.val();
5257 var max = parseInt(this.get('max'));
5258
5259 // can be added?
5260 if ($el.hasClass('disabled')) {
5261 return false;
5262 }
5263
5264 // validate
5265 if (max > 0 && val && val.length >= max) {
5266 // add notice
5267 this.showNotice({
5268 text: acf.__('Maximum values reached ( {max} values )').replace('{max}', max),
5269 type: 'warning'
5270 });
5271 return false;
5272 }
5273
5274 // disable
5275 $el.addClass('disabled');
5276
5277 // add
5278 var html = this.newValue({
5279 id: $el.data('id'),
5280 text: $el.html()
5281 });
5282 this.$list('values').append(html);
5283
5284 // trigger change
5285 this.$input().trigger('change');
5286 },
5287 onClickRemove: function (e, $el) {
5288 // Prevent default here because generic handler wont be triggered.
5289 e.preventDefault();
5290 let $span;
5291 // Behavior if triggered from tabbed event.
5292 if ($el.hasClass('acf-rel-item-remove')) {
5293 $span = $el;
5294 } else {
5295 // Behavior if triggered through click event.
5296 $span = $el.parent();
5297 }
5298
5299 // vars
5300 const $li = $span.parent();
5301 const id = $span.data('id');
5302
5303 // remove value
5304 $li.remove();
5305
5306 // show choice
5307 this.$listItem('choices', id).removeClass('disabled');
5308
5309 // trigger change
5310 this.$input().trigger('change');
5311 },
5312 onTouchStartValues: function (e, $el) {
5313 $(this.$listItems('values')).removeClass('relationship-hover');
5314 $el.addClass('relationship-hover');
5315 },
5316 maybeFetch: function () {
5317 // vars
5318 var timeout = this.get('timeout');
5319
5320 // abort timeout
5321 if (timeout) {
5322 clearTimeout(timeout);
5323 }
5324
5325 // fetch
5326 timeout = this.setTimeout(this.fetch, 300);
5327 this.set('timeout', timeout);
5328 },
5329 getAjaxData: function () {
5330 // load data based on element attributes
5331 var ajaxData = this.$control().data();
5332 for (var name in ajaxData) {
5333 ajaxData[name] = this.get(name);
5334 }
5335
5336 // extra
5337 ajaxData.action = 'acf/fields/relationship/query';
5338 ajaxData.field_key = this.get('key');
5339 ajaxData.nonce = this.get('nonce');
5340
5341 // Filter.
5342 ajaxData = acf.applyFilters('relationship_ajax_data', ajaxData, this);
5343
5344 // return
5345 return ajaxData;
5346 },
5347 fetch: function () {
5348 // abort XHR if this field is already loading AJAX data
5349 var xhr = this.get('xhr');
5350 if (xhr) {
5351 xhr.abort();
5352 }
5353
5354 // add to this.o
5355 var ajaxData = this.getAjaxData();
5356
5357 // clear html if is new query
5358 var $choiceslist = this.$list('choices');
5359 if (ajaxData.paged == 1) {
5360 $choiceslist.html('');
5361 }
5362
5363 // loading
5364 var $loading = $('<li><i class="acf-loading"></i> ' + acf.__('Loading') + '</li>');
5365 $choiceslist.append($loading);
5366 this.set('loading', true);
5367
5368 // callback
5369 var onComplete = function () {
5370 this.set('loading', false);
5371 $loading.remove();
5372 };
5373 var onSuccess = function (json) {
5374 // no results
5375 if (!json || !json.results || !json.results.length) {
5376 // prevent pagination
5377 this.set('more', false);
5378
5379 // add message
5380 if (this.get('paged') == 1) {
5381 this.$list('choices').append('<li>' + acf.__('No matches found') + '</li>');
5382 }
5383
5384 // return
5385 return;
5386 }
5387
5388 // set more (allows pagination scroll)
5389 this.set('more', json.more);
5390
5391 // get new results
5392 var html = this.walkChoices(json.results);
5393 var $html = $(html);
5394
5395 // apply .disabled to left li's
5396 var val = this.val();
5397 if (val && val.length) {
5398 val.map(function (id) {
5399 $html.find('.acf-rel-item[data-id="' + id + '"]').addClass('disabled');
5400 });
5401 }
5402
5403 // append
5404 $choiceslist.append($html);
5405
5406 // merge together groups
5407 var $prevLabel = false;
5408 var $prevList = false;
5409 $choiceslist.find('.acf-rel-label').each(function () {
5410 var $label = $(this);
5411 var $list = $label.siblings('ul');
5412 if ($prevLabel && $prevLabel.text() == $label.text()) {
5413 $prevList.append($list.children());
5414 $(this).parent().remove();
5415 return;
5416 }
5417
5418 // update vars
5419 $prevLabel = $label;
5420 $prevList = $list;
5421 });
5422 };
5423
5424 // get results
5425 var xhr = $.ajax({
5426 url: acf.get('ajaxurl'),
5427 dataType: 'json',
5428 type: 'post',
5429 data: acf.prepareForAjax(ajaxData),
5430 context: this,
5431 success: onSuccess,
5432 complete: onComplete
5433 });
5434
5435 // set
5436 this.set('xhr', xhr);
5437 },
5438 walkChoices: function (data) {
5439 // walker
5440 var walk = function (data) {
5441 // vars
5442 var html = '';
5443
5444 // is array
5445 if ($.isArray(data)) {
5446 data.map(function (item) {
5447 html += walk(item);
5448 });
5449
5450 // is item
5451 } else if ($.isPlainObject(data)) {
5452 // group
5453 if (data.children !== undefined) {
5454 html += '<li><span class="acf-rel-label">' + acf.escHtml(data.text) + '</span><ul class="acf-bl">';
5455 html += walk(data.children);
5456 html += '</ul></li>';
5457
5458 // single
5459 } else {
5460 html += '<li><span tabindex="0" class="acf-rel-item acf-rel-item-add" data-id="' + acf.escAttr(data.id) + '">' + acf.escHtml(data.text) + '</span></li>';
5461 }
5462 }
5463
5464 // return
5465 return html;
5466 };
5467 return walk(data);
5468 }
5469 });
5470 acf.registerFieldType(Field);
5471 })(jQuery);
5472
5473 /***/ }),
5474
5475 /***/ "./assets/src/js/_acf-field-select.js":
5476 /*!********************************************!*\
5477 !*** ./assets/src/js/_acf-field-select.js ***!
5478 \********************************************/
5479 /***/ (() => {
5480
5481 (function ($, undefined) {
5482 var Field = acf.Field.extend({
5483 type: 'select',
5484 select2: false,
5485 wait: 'load',
5486 events: {
5487 removeField: 'onRemove',
5488 duplicateField: 'onDuplicate'
5489 },
5490 $input: function () {
5491 return this.$('select');
5492 },
5493 setValue: function (val) {
5494 const $input = this.$input();
5495 $input.val(val);
5496 if (this.select2) {
5497 $input.trigger('change');
5498 }
5499 },
5500 initialize: function () {
5501 // vars
5502 var $select = this.$input();
5503
5504 // inherit data
5505 this.inherit($select);
5506
5507 // select2
5508 if (this.get('ui')) {
5509 // populate ajax_data (allowing custom attribute to already exist)
5510 var ajaxAction = this.get('ajax_action');
5511 if (!ajaxAction) {
5512 ajaxAction = 'acf/fields/' + this.get('type') + '/query';
5513 }
5514
5515 // select2
5516 this.select2 = acf.newSelect2($select, {
5517 field: this,
5518 ajax: this.get('ajax'),
5519 multiple: this.get('multiple'),
5520 placeholder: this.get('placeholder'),
5521 allowNull: this.get('allow_null'),
5522 tags: this.get('create_options'),
5523 ajaxAction: ajaxAction
5524 });
5525 }
5526 },
5527 onRemove: function () {
5528 if (this.select2) {
5529 this.select2.destroy();
5530 }
5531 },
5532 onDuplicate: function (e, $el, $duplicate) {
5533 if (this.select2) {
5534 $duplicate.find('.select2-container').remove();
5535 $duplicate.find('select').removeClass('select2-hidden-accessible');
5536 }
5537 }
5538 });
5539 acf.registerFieldType(Field);
5540 })(jQuery);
5541
5542 /***/ }),
5543
5544 /***/ "./assets/src/js/_acf-field-tab.js":
5545 /*!*****************************************!*\
5546 !*** ./assets/src/js/_acf-field-tab.js ***!
5547 \*****************************************/
5548 /***/ (() => {
5549
5550 (function ($, undefined) {
5551 // vars
5552 var CONTEXT = 'tab';
5553 var Field = acf.Field.extend({
5554 type: 'tab',
5555 wait: '',
5556 tabs: false,
5557 tab: false,
5558 events: {
5559 duplicateField: 'onDuplicate'
5560 },
5561 findFields: function () {
5562 let filter;
5563
5564 /**
5565 * Tabs in the admin UI that can be extended by third
5566 * parties have the child settings wrapped inside an extra div,
5567 * so we need to look for that instead of an adjacent .acf-field.
5568 */
5569 switch (this.get('key')) {
5570 case 'acf_field_settings_tabs':
5571 filter = '.acf-field-settings-main';
5572 break;
5573 case 'acf_field_group_settings_tabs':
5574 filter = '.field-group-settings-tab';
5575 break;
5576 case 'acf_browse_fields_tabs':
5577 filter = '.acf-field-types-tab';
5578 break;
5579 case 'acf_icon_picker_tabs':
5580 filter = '.acf-icon-picker-tabs';
5581 break;
5582 case 'acf_post_type_tabs':
5583 filter = '.acf-post-type-advanced-settings';
5584 break;
5585 case 'acf_taxonomy_tabs':
5586 filter = '.acf-taxonomy-advanced-settings';
5587 break;
5588 case 'acf_ui_options_page_tabs':
5589 filter = '.acf-ui-options-page-advanced-settings';
5590 break;
5591 default:
5592 filter = '.acf-field';
5593 }
5594 return this.$el.nextUntil('.acf-field-tab', filter);
5595 },
5596 getFields: function () {
5597 return acf.getFields(this.findFields());
5598 },
5599 findTabs: function () {
5600 return this.$el.prevAll('.acf-tab-wrap:first');
5601 },
5602 findTab: function () {
5603 return this.$('.acf-tab-button');
5604 },
5605 initialize: function () {
5606 // bail early if is td
5607 if (this.$el.is('td')) {
5608 this.events = {};
5609 return false;
5610 }
5611
5612 // vars
5613 var $tabs = this.findTabs();
5614 var $tab = this.findTab();
5615 var settings = acf.parseArgs($tab.data(), {
5616 endpoint: false,
5617 placement: '',
5618 before: this.$el
5619 });
5620
5621 // create wrap
5622 if (!$tabs.length || settings.endpoint) {
5623 this.tabs = new Tabs(settings);
5624 } else {
5625 this.tabs = $tabs.data('acf');
5626 }
5627
5628 // add tab
5629 this.tab = this.tabs.addTab($tab, this);
5630 },
5631 isActive: function () {
5632 return this.tab.isActive();
5633 },
5634 showFields: function () {
5635 // show fields
5636 this.getFields().map(function (field) {
5637 field.show(this.cid, CONTEXT);
5638 field.hiddenByTab = false;
5639 }, this);
5640 },
5641 hideFields: function () {
5642 // hide fields
5643 this.getFields().map(function (field) {
5644 field.hide(this.cid, CONTEXT);
5645 field.hiddenByTab = this.tab;
5646 }, this);
5647 },
5648 show: function (lockKey) {
5649 // show field and store result
5650 var visible = acf.Field.prototype.show.apply(this, arguments);
5651
5652 // check if now visible
5653 if (visible) {
5654 // show tab
5655 this.tab.show();
5656
5657 // check active tabs
5658 this.tabs.refresh();
5659 }
5660
5661 // return
5662 return visible;
5663 },
5664 hide: function (lockKey) {
5665 // hide field and store result
5666 var hidden = acf.Field.prototype.hide.apply(this, arguments);
5667
5668 // check if now hidden
5669 if (hidden) {
5670 // hide tab
5671 this.tab.hide();
5672
5673 // reset tabs if this was active
5674 if (this.isActive()) {
5675 this.tabs.reset();
5676 }
5677 }
5678
5679 // return
5680 return hidden;
5681 },
5682 enable: function (lockKey) {
5683 // enable fields
5684 this.getFields().map(function (field) {
5685 field.enable(CONTEXT);
5686 });
5687 },
5688 disable: function (lockKey) {
5689 // disable fields
5690 this.getFields().map(function (field) {
5691 field.disable(CONTEXT);
5692 });
5693 },
5694 onDuplicate: function (e, $el, $duplicate) {
5695 if (this.isActive()) {
5696 $duplicate.prevAll('.acf-tab-wrap:first').remove();
5697 }
5698 }
5699 });
5700 acf.registerFieldType(Field);
5701
5702 /**
5703 * tabs
5704 *
5705 * description
5706 *
5707 * @date 8/2/18
5708 * @since ACF 5.6.5
5709 *
5710 * @param type $var Description. Default.
5711 * @return type Description.
5712 */
5713
5714 var i = 0;
5715 var Tabs = acf.Model.extend({
5716 tabs: [],
5717 active: false,
5718 actions: {
5719 refresh: 'onRefresh',
5720 close_field_object: 'onCloseFieldObject'
5721 },
5722 data: {
5723 before: false,
5724 placement: 'top',
5725 index: 0,
5726 initialized: false
5727 },
5728 setup: function (settings) {
5729 // data
5730 $.extend(this.data, settings);
5731
5732 // define this prop to avoid scope issues
5733 this.tabs = [];
5734 this.active = false;
5735
5736 // vars
5737 var placement = this.get('placement');
5738 var $before = this.get('before');
5739 var $parent = $before.parent();
5740
5741 // add sidebar for left placement
5742 if (placement == 'left' && $parent.hasClass('acf-fields')) {
5743 $parent.addClass('-sidebar');
5744 }
5745
5746 // create wrap
5747 if ($before.is('tr')) {
5748 this.$el = $('<tr class="acf-tab-wrap"><td colspan="2"><ul class="acf-hl acf-tab-group"></ul></td></tr>');
5749 } else {
5750 let ulClass = 'acf-hl acf-tab-group';
5751 if (this.get('key') === 'acf_field_settings_tabs') {
5752 ulClass = 'acf-field-settings-tab-bar';
5753 }
5754 this.$el = $('<div class="acf-tab-wrap -' + placement + '"><ul class="' + ulClass + '"></ul></div>');
5755 }
5756
5757 // append
5758 $before.before(this.$el);
5759
5760 // set index
5761 this.set('index', i, true);
5762 i++;
5763 },
5764 initializeTabs: function () {
5765 // Bail if tabs are disabled.
5766 if ('acf_field_settings_tabs' === this.get('key') && $('#acf-field-group-fields').hasClass('hide-tabs')) {
5767 return;
5768 }
5769 var tab = false;
5770
5771 // check if we've got a saved default tab.
5772 var order = acf.getPreference('this.tabs') || false;
5773 if (order) {
5774 var groupIndex = this.get('index');
5775 var tabIndex = order[groupIndex];
5776 if (this.tabs[tabIndex] && this.tabs[tabIndex].isVisible()) {
5777 tab = this.tabs[tabIndex];
5778 }
5779 }
5780
5781 // If we've got a defaultTab provided by configuration, use that.
5782 if (!tab && this.data.defaultTab && this.data.defaultTab.isVisible()) {
5783 tab = this.data.defaultTab;
5784 }
5785
5786 // find first visible tab as our default.
5787 if (!tab) {
5788 tab = this.getVisible().shift();
5789 }
5790 if (tab) {
5791 this.selectTab(tab);
5792 } else {
5793 this.closeTabs();
5794 }
5795
5796 // set local variable used by tabsManager
5797 this.set('initialized', true);
5798 },
5799 getVisible: function () {
5800 return this.tabs.filter(function (tab) {
5801 return tab.isVisible();
5802 });
5803 },
5804 getActive: function () {
5805 return this.active;
5806 },
5807 setActive: function (tab) {
5808 return this.active = tab;
5809 },
5810 hasActive: function () {
5811 return this.active !== false;
5812 },
5813 isActive: function (tab) {
5814 var active = this.getActive();
5815 return active && active.cid === tab.cid;
5816 },
5817 closeActive: function () {
5818 if (this.hasActive()) {
5819 this.closeTab(this.getActive());
5820 }
5821 },
5822 openTab: function (tab) {
5823 // close existing tab
5824 this.closeActive();
5825
5826 // open
5827 tab.open();
5828
5829 // set active
5830 this.setActive(tab);
5831
5832 // Recalculate admin menu pinning so a previously taller tab (e.g. one
5833 // containing WYSIWYG fields) doesn't leave the menu pinned against a
5834 // shorter page, which can lock page scroll.
5835 $(document).trigger('wp-pin-menu');
5836 },
5837 closeTab: function (tab) {
5838 // close
5839 tab.close();
5840
5841 // set active
5842 this.setActive(false);
5843 },
5844 closeTabs: function () {
5845 this.tabs.map(this.closeTab, this);
5846 },
5847 selectTab: function (tab) {
5848 // close other tabs
5849 this.tabs.map(function (t) {
5850 if (tab.cid !== t.cid) {
5851 this.closeTab(t);
5852 }
5853 }, this);
5854
5855 // open
5856 this.openTab(tab);
5857 },
5858 addTab: function ($a, field) {
5859 // create <li>
5860 var $li = $('<li>' + $a.outerHTML() + '</li>');
5861
5862 // add settings type class.
5863 var settingsType = $a.data('settings-type');
5864 if (settingsType) {
5865 $li.addClass('acf-settings-type-' + settingsType);
5866 }
5867
5868 // append
5869 this.$('ul').append($li);
5870
5871 // initialize
5872 var tab = new Tab({
5873 $el: $li,
5874 field: field,
5875 group: this
5876 });
5877
5878 // store
5879 this.tabs.push(tab);
5880 if ($a.data('selected')) {
5881 this.data.defaultTab = tab;
5882 }
5883
5884 // return
5885 return tab;
5886 },
5887 reset: function () {
5888 // close existing tab
5889 this.closeActive();
5890
5891 // find and active a tab
5892 return this.refresh();
5893 },
5894 refresh: function () {
5895 // bail early if active already exists
5896 if (this.hasActive()) {
5897 return false;
5898 }
5899 // find next active tab
5900 var tab = this.getVisible().shift();
5901 // open tab
5902 if (tab) {
5903 this.openTab(tab);
5904 }
5905
5906 // return
5907 return tab;
5908 },
5909 onRefresh: function () {
5910 // only for left placements
5911 if (this.get('placement') !== 'left') {
5912 return;
5913 }
5914
5915 // vars
5916 var $parent = this.$el.parent();
5917 var $list = this.$el.children('ul');
5918 var attribute = $parent.is('td') ? 'height' : 'min-height';
5919
5920 // find height (minus 1 for border-bottom)
5921 var height = $list.position().top + $list.outerHeight(true) - 1;
5922
5923 // add css
5924 $parent.css(attribute, height);
5925 },
5926 onCloseFieldObject: function (fieldObject) {
5927 const tab = this.getVisible().find(item => {
5928 const id = item.$el.closest('div[data-id]').data('id');
5929 if (fieldObject.data.id === id) {
5930 return item;
5931 }
5932 });
5933 if (tab) {
5934 // Wait for field group drawer to close
5935 setTimeout(() => {
5936 this.openTab(tab);
5937 }, 300);
5938 }
5939 }
5940 });
5941 var Tab = acf.Model.extend({
5942 group: false,
5943 field: false,
5944 events: {
5945 'click a': 'onClick'
5946 },
5947 index: function () {
5948 return this.$el.index();
5949 },
5950 isVisible: function () {
5951 return acf.isVisible(this.$el);
5952 },
5953 isActive: function () {
5954 return this.$el.hasClass('active');
5955 },
5956 open: function () {
5957 // add class
5958 this.$el.addClass('active');
5959
5960 // show field
5961 this.field.showFields();
5962 },
5963 close: function () {
5964 // remove class
5965 this.$el.removeClass('active');
5966
5967 // hide field
5968 this.field.hideFields();
5969 },
5970 onClick: function (e, $el) {
5971 // prevent default
5972 e.preventDefault();
5973
5974 // toggle
5975 this.toggle();
5976 },
5977 toggle: function () {
5978 // bail early if already active
5979 if (this.isActive()) {
5980 return;
5981 }
5982
5983 // toggle this tab
5984 this.group.openTab(this);
5985 }
5986 });
5987 var tabsManager = new acf.Model({
5988 priority: 50,
5989 actions: {
5990 prepare: 'render',
5991 append: 'render',
5992 unload: 'onUnload',
5993 show: 'render',
5994 invalid_field: 'onInvalidField'
5995 },
5996 findTabs: function () {
5997 return $('.acf-tab-wrap');
5998 },
5999 getTabs: function () {
6000 return acf.getInstances(this.findTabs());
6001 },
6002 render: function ($el) {
6003 this.getTabs().map(function (tabs) {
6004 if (!tabs.get('initialized')) {
6005 tabs.initializeTabs();
6006 }
6007 });
6008 },
6009 onInvalidField: function (field) {
6010 // bail early if busy
6011 if (this.busy) {
6012 return;
6013 }
6014
6015 // ignore if not hidden by tab
6016 if (!field.hiddenByTab) {
6017 return;
6018 }
6019
6020 // toggle tab
6021 field.hiddenByTab.toggle();
6022
6023 // ignore other invalid fields
6024 this.busy = true;
6025 this.setTimeout(function () {
6026 this.busy = false;
6027 }, 100);
6028 },
6029 onUnload: function () {
6030 // vars
6031 var order = [];
6032
6033 // loop
6034 this.getTabs().map(function (group) {
6035 // Do not save selected tab on field settings, or an acf-advanced-settings when unloading
6036 if (group.$el.children('.acf-field-settings-tab-bar').length || group.$el.parents('#acf-advanced-settings.postbox').length) {
6037 return true;
6038 }
6039 var active = group.hasActive() ? group.getActive().index() : 0;
6040 order.push(active);
6041 });
6042
6043 // bail if no tabs
6044 if (!order.length) {
6045 return;
6046 }
6047
6048 // update
6049 acf.setPreference('this.tabs', order);
6050 }
6051 });
6052 })(jQuery);
6053
6054 /***/ }),
6055
6056 /***/ "./assets/src/js/_acf-field-taxonomy.js":
6057 /*!**********************************************!*\
6058 !*** ./assets/src/js/_acf-field-taxonomy.js ***!
6059 \**********************************************/
6060 /***/ (() => {
6061
6062 (function ($, undefined) {
6063 var Field = acf.Field.extend({
6064 type: 'taxonomy',
6065 data: {
6066 ftype: 'select'
6067 },
6068 select2: false,
6069 wait: 'load',
6070 events: {
6071 'click a[data-name="add"]': 'onClickAdd',
6072 'click input[type="radio"]': 'onClickRadio',
6073 'keydown label': 'onKeyDownLabel',
6074 removeField: 'onRemove'
6075 },
6076 $control: function () {
6077 return this.$('.acf-taxonomy-field');
6078 },
6079 $input: function () {
6080 return this.getRelatedPrototype().$input.apply(this, arguments);
6081 },
6082 getRelatedType: function () {
6083 // vars
6084 var fieldType = this.get('ftype');
6085
6086 // normalize
6087 if (fieldType == 'multi_select') {
6088 fieldType = 'select';
6089 }
6090
6091 // return
6092 return fieldType;
6093 },
6094 getRelatedPrototype: function () {
6095 return acf.getFieldType(this.getRelatedType()).prototype;
6096 },
6097 getValue: function () {
6098 return this.getRelatedPrototype().getValue.apply(this, arguments);
6099 },
6100 setValue: function () {
6101 return this.getRelatedPrototype().setValue.apply(this, arguments);
6102 },
6103 initialize: function () {
6104 this.getRelatedPrototype().initialize.apply(this, arguments);
6105 },
6106 onRemove: function () {
6107 var proto = this.getRelatedPrototype();
6108 if (proto.onRemove) {
6109 proto.onRemove.apply(this, arguments);
6110 }
6111 },
6112 onClickAdd: function (e, $el) {
6113 // vars
6114 var field = this;
6115 var popup = false;
6116 var $form = false;
6117 var $name = false;
6118 var $parent = false;
6119 var $button = false;
6120 var $message = false;
6121 var notice = false;
6122
6123 // step 1.
6124 var step1 = function () {
6125 // popup
6126 popup = acf.newPopup({
6127 title: $el.attr('title'),
6128 loading: true,
6129 width: '300px'
6130 });
6131
6132 // ajax
6133 var ajaxData = {
6134 action: 'acf/fields/taxonomy/add_term',
6135 field_key: field.get('key'),
6136 nonce: field.get('nonce')
6137 };
6138
6139 // get HTML
6140 $.ajax({
6141 url: acf.get('ajaxurl'),
6142 data: acf.prepareForAjax(ajaxData),
6143 type: 'post',
6144 dataType: 'html',
6145 success: step2
6146 });
6147 };
6148
6149 // step 2.
6150 var step2 = function (html) {
6151 // update popup
6152 popup.loading(false);
6153 popup.content(html);
6154
6155 // vars
6156 $form = popup.$('form');
6157 $name = popup.$('input[name="term_name"]');
6158 $parent = popup.$('select[name="term_parent"]');
6159 $button = popup.$('.acf-submit-button');
6160
6161 // focus
6162 $name.trigger('focus');
6163
6164 // submit form
6165 popup.on('submit', 'form', step3);
6166 };
6167
6168 // step 3.
6169 var step3 = function (e, $el) {
6170 // prevent
6171 e.preventDefault();
6172 e.stopImmediatePropagation();
6173
6174 // basic validation
6175 if ($name.val() === '') {
6176 $name.trigger('focus');
6177 return false;
6178 }
6179
6180 // disable
6181 acf.startButtonLoading($button);
6182
6183 // ajax
6184 var ajaxData = {
6185 action: 'acf/fields/taxonomy/add_term',
6186 field_key: field.get('key'),
6187 nonce: field.get('nonce'),
6188 term_name: $name.val(),
6189 term_parent: $parent.length ? $parent.val() : 0
6190 };
6191 $.ajax({
6192 url: acf.get('ajaxurl'),
6193 data: acf.prepareForAjax(ajaxData),
6194 type: 'post',
6195 dataType: 'json',
6196 success: step4
6197 });
6198 };
6199
6200 // step 4.
6201 var step4 = function (json) {
6202 // enable
6203 acf.stopButtonLoading($button);
6204
6205 // remove prev notice
6206 if (notice) {
6207 notice.remove();
6208 }
6209
6210 // success
6211 if (acf.isAjaxSuccess(json)) {
6212 // clear name
6213 $name.val('');
6214
6215 // update term lists
6216 step5(json.data);
6217
6218 // notice
6219 notice = acf.newNotice({
6220 type: 'success',
6221 text: acf.getAjaxMessage(json),
6222 target: $form,
6223 timeout: 2000,
6224 dismiss: false
6225 });
6226 } else {
6227 // notice
6228 notice = acf.newNotice({
6229 type: 'error',
6230 text: acf.getAjaxError(json),
6231 target: $form,
6232 timeout: 2000,
6233 dismiss: false
6234 });
6235 }
6236
6237 // focus
6238 $name.trigger('focus');
6239 };
6240
6241 // step 5.
6242 var step5 = function (term) {
6243 // update parent dropdown
6244 var $option = $('<option value="' + term.term_id + '">' + term.term_label + '</option>');
6245 if (term.term_parent) {
6246 $parent.children('option[value="' + term.term_parent + '"]').after($option);
6247 } else {
6248 $parent.append($option);
6249 }
6250
6251 // add this new term to all taxonomy field
6252 var fields = acf.getFields({
6253 type: 'taxonomy'
6254 });
6255 fields.map(function (otherField) {
6256 if (otherField.get('taxonomy') == field.get('taxonomy')) {
6257 otherField.appendTerm(term);
6258 }
6259 });
6260
6261 // select
6262 field.selectTerm(term.term_id);
6263 };
6264
6265 // run
6266 step1();
6267 },
6268 appendTerm: function (term) {
6269 if (this.getRelatedType() == 'select') {
6270 this.appendTermSelect(term);
6271 } else {
6272 this.appendTermCheckbox(term);
6273 }
6274 },
6275 appendTermSelect: function (term) {
6276 this.select2.addOption({
6277 id: term.term_id,
6278 text: term.term_label
6279 });
6280 },
6281 appendTermCheckbox: function (term) {
6282 // vars
6283 var name = this.$('[name]:first').attr('name');
6284 var $ul = this.$('ul:first');
6285
6286 // allow multiple selection
6287 if (this.getRelatedType() == 'checkbox') {
6288 name += '[]';
6289 }
6290
6291 // create new li
6292 var $li = $(['<li data-id="' + term.term_id + '">', '<label>', '<input type="' + this.get('ftype') + '" value="' + term.term_id + '" name="' + name + '" /> ', '<span>' + term.term_name + '</span>', '</label>', '</li>'].join(''));
6293
6294 // find parent
6295 if (term.term_parent) {
6296 // vars
6297 var $parent = $ul.find('li[data-id="' + term.term_parent + '"]');
6298
6299 // update vars
6300 $ul = $parent.children('ul');
6301
6302 // create ul
6303 if (!$ul.exists()) {
6304 $ul = $('<ul class="children acf-bl"></ul>');
6305 $parent.append($ul);
6306 }
6307 }
6308
6309 // append
6310 $ul.append($li);
6311 },
6312 selectTerm: function (id) {
6313 if (this.getRelatedType() == 'select') {
6314 this.select2.selectOption(id);
6315 } else {
6316 var $input = this.$('input[value="' + id + '"]');
6317 $input.prop('checked', true).trigger('change');
6318 }
6319 },
6320 onClickRadio: function (e, $el) {
6321 // vars
6322 var $label = $el.parent('label');
6323 var selected = $label.hasClass('selected');
6324
6325 // remove previous selected
6326 this.$('.selected').removeClass('selected');
6327
6328 // add active class
6329 $label.addClass('selected');
6330
6331 // allow null
6332 if (this.get('allow_null') && selected) {
6333 $label.removeClass('selected');
6334 $el.prop('checked', false).trigger('change');
6335 }
6336 },
6337 onKeyDownLabel: function (e, $el) {
6338 // bail early if not space or enter
6339 if (e.which !== 13) {
6340 return;
6341 }
6342 e.preventDefault();
6343 const firstInput = $el.find('input').first();
6344 if (firstInput.length) {
6345 firstInput.trigger('click').trigger('focus');
6346 }
6347 }
6348 });
6349 acf.registerFieldType(Field);
6350 })(jQuery);
6351
6352 /***/ }),
6353
6354 /***/ "./assets/src/js/_acf-field-time-picker.js":
6355 /*!*************************************************!*\
6356 !*** ./assets/src/js/_acf-field-time-picker.js ***!
6357 \*************************************************/
6358 /***/ (() => {
6359
6360 (function ($, undefined) {
6361 var Field = acf.models.DatePickerField.extend({
6362 type: 'time_picker',
6363 $control: function () {
6364 return this.$('.acf-time-picker');
6365 },
6366 setValue: function (val) {
6367 acf.val(this.$input(), val);
6368 const $inputText = this.$inputText();
6369 if (val && $inputText.length) {
6370 try {
6371 const timeFormat = this.get('time_format') || $inputText.timepicker('option', 'timeFormat');
6372 const matches = val.match(/^(\d{2}):(\d{2}):(\d{2})$/);
6373 if (matches && $.datepicker && $.datepicker.formatTime) {
6374 const timeText = $.datepicker.formatTime(timeFormat, {
6375 hour: parseInt(matches[1], 10),
6376 minute: parseInt(matches[2], 10),
6377 second: parseInt(matches[3], 10)
6378 });
6379 $inputText.val(timeText);
6380 } else {
6381 $inputText.val(val);
6382 }
6383 } catch (e) {
6384 $inputText.val(val);
6385 }
6386 } else {
6387 $inputText.val('');
6388 }
6389 },
6390 initialize: function () {
6391 // vars
6392 var $input = this.$input();
6393 var $inputText = this.$inputText();
6394
6395 // args
6396 var args = {
6397 timeFormat: this.get('time_format'),
6398 altField: $input,
6399 altFieldTimeOnly: false,
6400 altTimeFormat: 'HH:mm:ss',
6401 showButtonPanel: true,
6402 controlType: 'select',
6403 oneLine: true,
6404 closeText: acf.get('dateTimePickerL10n').selectText,
6405 timeOnly: true
6406 };
6407
6408 // add custom 'Close = Select' functionality
6409 args.onClose = function (value, dp_instance, t_instance) {
6410 // vars
6411 var $close = dp_instance.dpDiv.find('.ui-datepicker-close');
6412
6413 // if clicking close button
6414 if (!value && $close.is(':hover')) {
6415 t_instance._updateDateTime();
6416 }
6417 };
6418
6419 // filter
6420 args = acf.applyFilters('time_picker_args', args, this);
6421
6422 // add date time picker
6423 acf.newTimePicker($inputText, args);
6424
6425 // action
6426 acf.doAction('time_picker_init', $inputText, args, this);
6427 }
6428 });
6429 acf.registerFieldType(Field);
6430
6431 // add
6432 acf.newTimePicker = function ($input, args) {
6433 // bail early if no datepicker library
6434 if (typeof $.timepicker === 'undefined') {
6435 return false;
6436 }
6437
6438 // defaults
6439 args = args || {};
6440
6441 // initialize
6442 $input.timepicker(args);
6443
6444 // wrap the datepicker (only if it hasn't already been wrapped)
6445 if ($('body > #ui-datepicker-div').exists()) {
6446 $('body > #ui-datepicker-div').wrap('<div class="acf-ui-datepicker" />');
6447 }
6448 };
6449 })(jQuery);
6450
6451 /***/ }),
6452
6453 /***/ "./assets/src/js/_acf-field-true-false.js":
6454 /*!************************************************!*\
6455 !*** ./assets/src/js/_acf-field-true-false.js ***!
6456 \************************************************/
6457 /***/ (() => {
6458
6459 (function ($, undefined) {
6460 var Field = acf.Field.extend({
6461 type: 'true_false',
6462 events: {
6463 'change .acf-switch-input': 'onChange',
6464 'focus .acf-switch-input': 'onFocus',
6465 'blur .acf-switch-input': 'onBlur',
6466 'keypress .acf-switch-input': 'onKeypress'
6467 },
6468 $input: function () {
6469 return this.$('input[type="checkbox"]');
6470 },
6471 $switch: function () {
6472 return this.$('.acf-switch');
6473 },
6474 setValue: function (val) {
6475 if (val && val !== '0') {
6476 this.switchOn();
6477 } else {
6478 this.switchOff();
6479 }
6480 },
6481 getValue: function () {
6482 return this.$input().prop('checked') ? 1 : 0;
6483 },
6484 initialize: function () {
6485 this.render();
6486 },
6487 render: function () {
6488 // vars
6489 var $switch = this.$switch();
6490
6491 // bail early if no $switch
6492 if (!$switch.length) return;
6493
6494 // vars
6495 var $on = $switch.children('.acf-switch-on');
6496 var $off = $switch.children('.acf-switch-off');
6497 var width = Math.max($on.width(), $off.width());
6498
6499 // bail early if no width
6500 if (!width) return;
6501
6502 // set widths
6503 $on.css('min-width', width);
6504 $off.css('min-width', width);
6505 },
6506 switchOn: function () {
6507 this.$input().prop('checked', true);
6508 this.$switch().addClass('-on');
6509 },
6510 switchOff: function () {
6511 this.$input().prop('checked', false);
6512 this.$switch().removeClass('-on');
6513 },
6514 onChange: function (e, $el) {
6515 if ($el.prop('checked')) {
6516 this.switchOn();
6517 } else {
6518 this.switchOff();
6519 }
6520 },
6521 onFocus: function (e, $el) {
6522 this.$switch().addClass('-focus');
6523 },
6524 onBlur: function (e, $el) {
6525 this.$switch().removeClass('-focus');
6526 },
6527 onKeypress: function (e, $el) {
6528 // left
6529 if (e.keyCode === 37) {
6530 return this.switchOff();
6531 }
6532
6533 // right
6534 if (e.keyCode === 39) {
6535 return this.switchOn();
6536 }
6537 }
6538 });
6539 acf.registerFieldType(Field);
6540 })(jQuery);
6541
6542 /***/ }),
6543
6544 /***/ "./assets/src/js/_acf-field-url.js":
6545 /*!*****************************************!*\
6546 !*** ./assets/src/js/_acf-field-url.js ***!
6547 \*****************************************/
6548 /***/ (() => {
6549
6550 (function ($, undefined) {
6551 var Field = acf.Field.extend({
6552 type: 'url',
6553 events: {
6554 'keyup input[type="url"]': 'onkeyup'
6555 },
6556 $control: function () {
6557 return this.$('.acf-input-wrap');
6558 },
6559 $input: function () {
6560 return this.$('input[type="url"]');
6561 },
6562 initialize: function () {
6563 this.render();
6564 },
6565 isValid: function () {
6566 // vars
6567 var val = this.val();
6568
6569 // bail early if no val
6570 if (!val) {
6571 return false;
6572 }
6573
6574 // url
6575 if (val.indexOf('://') !== -1) {
6576 return true;
6577 }
6578
6579 // protocol relative url
6580 if (val.indexOf('//') === 0) {
6581 return true;
6582 }
6583
6584 // return
6585 return false;
6586 },
6587 render: function () {
6588 // add class
6589 if (this.isValid()) {
6590 this.$control().addClass('-valid');
6591 } else {
6592 this.$control().removeClass('-valid');
6593 }
6594 },
6595 onkeyup: function (e, $el) {
6596 this.render();
6597 }
6598 });
6599 acf.registerFieldType(Field);
6600 })(jQuery);
6601
6602 /***/ }),
6603
6604 /***/ "./assets/src/js/_acf-field-user.js":
6605 /*!******************************************!*\
6606 !*** ./assets/src/js/_acf-field-user.js ***!
6607 \******************************************/
6608 /***/ (() => {
6609
6610 (function ($, undefined) {
6611 var Field = acf.models.SelectField.extend({
6612 type: 'user'
6613 });
6614 acf.registerFieldType(Field);
6615 })(jQuery);
6616
6617 /***/ }),
6618
6619 /***/ "./assets/src/js/_acf-field-wysiwyg.js":
6620 /*!*********************************************!*\
6621 !*** ./assets/src/js/_acf-field-wysiwyg.js ***!
6622 \*********************************************/
6623 /***/ (() => {
6624
6625 (function ($, undefined) {
6626 var Field = acf.Field.extend({
6627 type: 'wysiwyg',
6628 wait: 'load',
6629 events: {
6630 'mousedown .acf-editor-wrap.delay': 'onMousedown',
6631 unmountField: 'disableEditor',
6632 remountField: 'enableEditor',
6633 removeField: 'disableEditor'
6634 },
6635 $control: function () {
6636 return this.$('.acf-editor-wrap');
6637 },
6638 $input: function () {
6639 return this.$('textarea');
6640 },
6641 setValue: function (val) {
6642 acf.val(this.$input(), val);
6643 if (this.getMode() === 'visual') {
6644 const id = this.get('id');
6645 const editor = window.tinymce && tinymce.get(id);
6646 if (editor && !editor.isHidden()) {
6647 editor.setContent(val || '');
6648 }
6649 }
6650 },
6651 getMode: function () {
6652 return this.$control().hasClass('tmce-active') ? 'visual' : 'text';
6653 },
6654 initialize: function () {
6655 // initializeEditor if no delay
6656 if (!this.$control().hasClass('delay')) {
6657 this.initializeEditor();
6658 }
6659 },
6660 initializeEditor: function () {
6661 // vars
6662 var $wrap = this.$control();
6663 var $textarea = this.$input();
6664 var args = {
6665 tinymce: true,
6666 quicktags: true,
6667 toolbar: this.get('toolbar'),
6668 mode: this.getMode(),
6669 field: this
6670 };
6671
6672 // generate new id
6673 var oldId = $textarea.attr('id');
6674 var newId = acf.uniqueId('acf-editor-');
6675
6676 // Backup textarea data.
6677 var inputData = $textarea.data();
6678 var inputVal = $textarea.val();
6679
6680 // rename
6681 acf.rename({
6682 target: $wrap,
6683 search: oldId,
6684 replace: newId,
6685 destructive: true
6686 });
6687
6688 // update id
6689 this.set('id', newId, true);
6690
6691 // apply data to new textarea (acf.rename creates a new textarea element due to destructive mode)
6692 // fixes bug where conditional logic "disabled" is lost during "screen_check"
6693 this.$input().data(inputData).val(inputVal);
6694
6695 // initialize
6696 acf.tinymce.initialize(newId, args);
6697 },
6698 onMousedown: function (e) {
6699 // prevent default
6700 e.preventDefault();
6701
6702 // remove delay class
6703 var $wrap = this.$control();
6704 $wrap.removeClass('delay');
6705 $wrap.find('.acf-editor-toolbar').remove();
6706
6707 // initialize
6708 this.initializeEditor();
6709 },
6710 enableEditor: function () {
6711 if (this.getMode() == 'visual') {
6712 acf.tinymce.enable(this.get('id'));
6713 }
6714 },
6715 disableEditor: function () {
6716 acf.tinymce.destroy(this.get('id'));
6717 }
6718 });
6719 acf.registerFieldType(Field);
6720 })(jQuery);
6721
6722 /***/ }),
6723
6724 /***/ "./assets/src/js/_acf-field.js":
6725 /*!*************************************!*\
6726 !*** ./assets/src/js/_acf-field.js ***!
6727 \*************************************/
6728 /***/ (() => {
6729
6730 (function ($, undefined) {
6731 // vars
6732 var storage = [];
6733
6734 /**
6735 * acf.Field
6736 *
6737 * description
6738 *
6739 * @date 23/3/18
6740 * @since ACF 5.6.9
6741 *
6742 * @param type $var Description. Default.
6743 * @return type Description.
6744 */
6745
6746 acf.Field = acf.Model.extend({
6747 // field type
6748 type: '',
6749 // class used to avoid nested event triggers
6750 eventScope: '.acf-field',
6751 // initialize events on 'ready'
6752 wait: 'ready',
6753 /**
6754 * setup
6755 *
6756 * Called during the constructor function to setup this field ready for initialization
6757 *
6758 * @date 8/5/18
6759 * @since ACF 5.6.9
6760 *
6761 * @param jQuery $field The field element.
6762 * @return void
6763 */
6764
6765 setup: function ($field) {
6766 // set $el
6767 this.$el = $field;
6768
6769 // inherit $field data
6770 this.inherit($field);
6771
6772 // inherit control data
6773 this.inherit(this.$control());
6774 },
6775 /**
6776 * val
6777 *
6778 * Sets or returns the field's value
6779 *
6780 * @date 8/5/18
6781 * @since ACF 5.6.9
6782 *
6783 * @param mixed val Optional. The value to set
6784 * @return mixed
6785 */
6786
6787 val: function (val) {
6788 // Set.
6789 if (val !== undefined) {
6790 return this.setValue(val);
6791
6792 // Get.
6793 } else {
6794 return this.prop('disabled') ? null : this.getValue();
6795 }
6796 },
6797 /**
6798 * getValue
6799 *
6800 * returns the field's value
6801 *
6802 * @date 8/5/18
6803 * @since ACF 5.6.9
6804 *
6805 * @param void
6806 * @return mixed
6807 */
6808
6809 getValue: function () {
6810 return this.$input().val();
6811 },
6812 /**
6813 * setValue
6814 *
6815 * sets the field's value and returns true if changed
6816 *
6817 * @date 8/5/18
6818 * @since ACF 5.6.9
6819 *
6820 * @param mixed val
6821 * @return boolean. True if changed.
6822 */
6823
6824 setValue: function (val) {
6825 return acf.val(this.$input(), val);
6826 },
6827 /**
6828 * __
6829 *
6830 * i18n helper to be removed
6831 *
6832 * @date 8/5/18
6833 * @since ACF 5.6.9
6834 *
6835 * @param type $var Description. Default.
6836 * @return type Description.
6837 */
6838
6839 __: function (string) {
6840 return acf._e(this.type, string);
6841 },
6842 /**
6843 * $control
6844 *
6845 * returns the control jQuery element used for inheriting data. Uses this.control setting.
6846 *
6847 * @date 8/5/18
6848 * @since ACF 5.6.9
6849 *
6850 * @param void
6851 * @return jQuery
6852 */
6853
6854 $control: function () {
6855 return false;
6856 },
6857 /**
6858 * $input
6859 *
6860 * returns the input jQuery element used for saving values. Uses this.input setting.
6861 *
6862 * @date 8/5/18
6863 * @since ACF 5.6.9
6864 *
6865 * @param void
6866 * @return jQuery
6867 */
6868
6869 $input: function () {
6870 return this.$('[name]:first');
6871 },
6872 /**
6873 * $inputWrap
6874 *
6875 * description
6876 *
6877 * @date 12/5/18
6878 * @since ACF 5.6.9
6879 *
6880 * @param type $var Description. Default.
6881 * @return type Description.
6882 */
6883
6884 $inputWrap: function () {
6885 return this.$('.acf-input:first');
6886 },
6887 /**
6888 * $inputWrap
6889 *
6890 * description
6891 *
6892 * @date 12/5/18
6893 * @since ACF 5.6.9
6894 *
6895 * @param type $var Description. Default.
6896 * @return type Description.
6897 */
6898
6899 $labelWrap: function () {
6900 return this.$('.acf-label:first');
6901 },
6902 /**
6903 * getInputName
6904 *
6905 * Returns the field's input name
6906 *
6907 * @date 8/5/18
6908 * @since ACF 5.6.9
6909 *
6910 * @param void
6911 * @return string
6912 */
6913
6914 getInputName: function () {
6915 return this.$input().attr('name') || '';
6916 },
6917 /**
6918 * parent
6919 *
6920 * returns the field's parent field or false on failure.
6921 *
6922 * @date 8/5/18
6923 * @since ACF 5.6.9
6924 *
6925 * @param void
6926 * @return object|false
6927 */
6928
6929 parent: function () {
6930 // vars
6931 var parents = this.parents();
6932
6933 // return
6934 return parents.length ? parents[0] : false;
6935 },
6936 /**
6937 * parents
6938 *
6939 * description
6940 *
6941 * @date 9/7/18
6942 * @since ACF 5.6.9
6943 *
6944 * @param type $var Description. Default.
6945 * @return type Description.
6946 */
6947
6948 parents: function () {
6949 // vars
6950 var $parents = this.$el.parents('.acf-field');
6951
6952 // convert
6953 var parents = acf.getFields($parents);
6954
6955 // return
6956 return parents;
6957 },
6958 show: function (lockKey, context) {
6959 // show field and store result
6960 var changed = acf.show(this.$el, lockKey);
6961
6962 // do action if visibility has changed
6963 if (changed) {
6964 this.prop('hidden', false);
6965 acf.doAction('show_field', this, context);
6966 if (context === 'conditional_logic') {
6967 this.setFieldSettingsLastVisible();
6968 }
6969 }
6970
6971 // return
6972 return changed;
6973 },
6974 hide: function (lockKey, context) {
6975 // hide field and store result
6976 var changed = acf.hide(this.$el, lockKey);
6977
6978 // do action if visibility has changed
6979 if (changed) {
6980 this.prop('hidden', true);
6981 acf.doAction('hide_field', this, context);
6982 if (context === 'conditional_logic') {
6983 this.setFieldSettingsLastVisible();
6984 }
6985 }
6986
6987 // return
6988 return changed;
6989 },
6990 setFieldSettingsLastVisible: function () {
6991 // Ensure this conditional logic trigger has happened inside a field settings tab.
6992 var $parents = this.$el.parents('.acf-field-settings-main');
6993 if (!$parents.length) return;
6994 var $fields = $parents.find('.acf-field');
6995 $fields.removeClass('acf-last-visible');
6996 $fields.not('.acf-hidden').last().addClass('acf-last-visible');
6997 },
6998 enable: function (lockKey, context) {
6999 // enable field and store result
7000 var changed = acf.enable(this.$el, lockKey);
7001
7002 // do action if disabled has changed
7003 if (changed) {
7004 this.prop('disabled', false);
7005 acf.doAction('enable_field', this, context);
7006 }
7007
7008 // return
7009 return changed;
7010 },
7011 disable: function (lockKey, context) {
7012 // disabled field and store result
7013 var changed = acf.disable(this.$el, lockKey);
7014
7015 // do action if disabled has changed
7016 if (changed) {
7017 this.prop('disabled', true);
7018 acf.doAction('disable_field', this, context);
7019 }
7020
7021 // return
7022 return changed;
7023 },
7024 showEnable: function (lockKey, context) {
7025 // enable
7026 this.enable.apply(this, arguments);
7027
7028 // show and return true if changed
7029 return this.show.apply(this, arguments);
7030 },
7031 hideDisable: function (lockKey, context) {
7032 // disable
7033 this.disable.apply(this, arguments);
7034
7035 // hide and return true if changed
7036 return this.hide.apply(this, arguments);
7037 },
7038 showNotice: function (props) {
7039 // ensure object
7040 if (typeof props !== 'object') {
7041 props = {
7042 text: props
7043 };
7044 }
7045
7046 // remove old notice
7047 if (this.notice) {
7048 this.notice.remove();
7049 }
7050
7051 // create new notice
7052 props.target = this.$inputWrap();
7053 this.notice = acf.newNotice(props);
7054 },
7055 removeNotice: function (timeout) {
7056 if (this.notice) {
7057 this.notice.away(timeout || 0);
7058 this.notice = false;
7059 }
7060 },
7061 showError: function (message, location = 'before') {
7062 // add class
7063 this.$el.addClass('acf-error');
7064
7065 // add message
7066 if (message !== undefined) {
7067 this.showNotice({
7068 text: message,
7069 type: 'error',
7070 dismiss: false,
7071 location: location
7072 });
7073 }
7074
7075 // action
7076 acf.doAction('invalid_field', this);
7077
7078 // add event
7079 this.$el.one('focus change', 'input, select, textarea', $.proxy(this.removeError, this));
7080 },
7081 removeError: function () {
7082 // remove class
7083 this.$el.removeClass('acf-error');
7084
7085 // remove notice
7086 this.removeNotice(250);
7087
7088 // action
7089 acf.doAction('valid_field', this);
7090 },
7091 trigger: function (name, args, bubbles) {
7092 // allow some events to bubble
7093 if (name == 'invalidField') {
7094 bubbles = true;
7095 }
7096
7097 // return
7098 return acf.Model.prototype.trigger.apply(this, [name, args, bubbles]);
7099 }
7100 });
7101
7102 /**
7103 * newField
7104 *
7105 * description
7106 *
7107 * @date 14/12/17
7108 * @since ACF 5.6.5
7109 *
7110 * @param type $var Description. Default.
7111 * @return type Description.
7112 */
7113
7114 acf.newField = function ($field) {
7115 // vars
7116 var type = $field.data('type');
7117 var mid = modelId(type);
7118 var model = acf.models[mid] || acf.Field;
7119
7120 // instantiate
7121 var field = new model($field);
7122
7123 // actions
7124 acf.doAction('new_field', field);
7125
7126 // return
7127 return field;
7128 };
7129
7130 /**
7131 * mid
7132 *
7133 * Calculates the model ID for a field type
7134 *
7135 * @date 15/12/17
7136 * @since ACF 5.6.5
7137 *
7138 * @param string type
7139 * @return string
7140 */
7141
7142 var modelId = function (type) {
7143 return acf.strPascalCase(type || '') + 'Field';
7144 };
7145
7146 /**
7147 * registerFieldType
7148 *
7149 * description
7150 *
7151 * @date 14/12/17
7152 * @since ACF 5.6.5
7153 *
7154 * @param type $var Description. Default.
7155 * @return type Description.
7156 */
7157
7158 acf.registerFieldType = function (model) {
7159 // vars
7160 var proto = model.prototype;
7161 var type = proto.type;
7162 var mid = modelId(type);
7163
7164 // store model
7165 acf.models[mid] = model;
7166
7167 // store reference
7168 storage.push(type);
7169 };
7170
7171 /**
7172 * acf.getFieldType
7173 *
7174 * description
7175 *
7176 * @date 1/2/18
7177 * @since ACF 5.6.5
7178 *
7179 * @param type $var Description. Default.
7180 * @return type Description.
7181 */
7182
7183 acf.getFieldType = function (type) {
7184 var mid = modelId(type);
7185 return acf.models[mid] || false;
7186 };
7187
7188 /**
7189 * acf.getFieldTypes
7190 *
7191 * description
7192 *
7193 * @date 1/2/18
7194 * @since ACF 5.6.5
7195 *
7196 * @param type $var Description. Default.
7197 * @return type Description.
7198 */
7199
7200 acf.getFieldTypes = function (args) {
7201 // defaults
7202 args = acf.parseArgs(args, {
7203 category: ''
7204 // hasValue: true
7205 });
7206
7207 // clone available types
7208 var types = [];
7209
7210 // loop
7211 storage.map(function (type) {
7212 // vars
7213 var model = acf.getFieldType(type);
7214 var proto = model.prototype;
7215
7216 // check operator
7217 if (args.category && proto.category !== args.category) {
7218 return;
7219 }
7220
7221 // append
7222 types.push(model);
7223 });
7224
7225 // return
7226 return types;
7227 };
7228 })(jQuery);
7229
7230 /***/ }),
7231
7232 /***/ "./assets/src/js/_acf-fields.js":
7233 /*!**************************************!*\
7234 !*** ./assets/src/js/_acf-fields.js ***!
7235 \**************************************/
7236 /***/ (() => {
7237
7238 (function ($, undefined) {
7239 /**
7240 * findFields
7241 *
7242 * Returns a jQuery selection object of acf fields.
7243 *
7244 * @date 14/12/17
7245 * @since ACF 5.6.5
7246 *
7247 * @param object $args {
7248 * Optional. Arguments to find fields.
7249 *
7250 * @type string key The field's key (data-attribute).
7251 * @type string name The field's name (data-attribute).
7252 * @type string type The field's type (data-attribute).
7253 * @type string is jQuery selector to compare against.
7254 * @type jQuery parent jQuery element to search within.
7255 * @type jQuery sibling jQuery element to search alongside.
7256 * @type limit int The number of fields to find.
7257 * @type suppressFilters bool Whether to allow filters to add/remove results. Default behaviour will ignore clone fields.
7258 * }
7259 * @return jQuery
7260 */
7261
7262 acf.findFields = function (args) {
7263 // vars
7264 var selector = '.acf-field';
7265 var $fields = false;
7266
7267 // args
7268 args = acf.parseArgs(args, {
7269 key: '',
7270 name: '',
7271 type: '',
7272 is: '',
7273 parent: false,
7274 sibling: false,
7275 limit: false,
7276 visible: false,
7277 suppressFilters: false,
7278 excludeSubFields: false
7279 });
7280
7281 // filter args
7282 if (!args.suppressFilters) {
7283 args = acf.applyFilters('find_fields_args', args);
7284 }
7285
7286 // key
7287 if (args.key) {
7288 selector += '[data-key="' + args.key + '"]';
7289 }
7290
7291 // type
7292 if (args.type) {
7293 selector += '[data-type="' + args.type + '"]';
7294 }
7295
7296 // name
7297 if (args.name) {
7298 selector += '[data-name="' + args.name + '"]';
7299 }
7300
7301 // is
7302 if (args.is) {
7303 selector += args.is;
7304 }
7305
7306 // visibility
7307 if (args.visible) {
7308 selector += ':visible';
7309 }
7310 if (!args.suppressFilters) {
7311 selector = acf.applyFilters('find_fields_selector', selector, args);
7312 }
7313
7314 // query
7315 if (args.parent) {
7316 $fields = args.parent.find(selector);
7317 // exclude sub fields if required (only if a parent is provided)
7318 if (args.excludeSubFields) {
7319 $fields = $fields.not(args.parent.find('.acf-is-subfields .acf-field'));
7320 }
7321 } else if (args.sibling) {
7322 $fields = args.sibling.siblings(selector);
7323 } else {
7324 $fields = $(selector);
7325 }
7326
7327 // filter
7328 if (!args.suppressFilters) {
7329 $fields = $fields.not('.acf-clone .acf-field');
7330 $fields = acf.applyFilters('find_fields', $fields);
7331 }
7332
7333 // limit
7334 if (args.limit) {
7335 $fields = $fields.slice(0, args.limit);
7336 }
7337
7338 // return
7339 return $fields;
7340 };
7341
7342 /**
7343 * findField
7344 *
7345 * Finds a specific field with jQuery
7346 *
7347 * @date 14/12/17
7348 * @since ACF 5.6.5
7349 *
7350 * @param string key The field's key.
7351 * @param jQuery $parent jQuery element to search within.
7352 * @return jQuery
7353 */
7354
7355 acf.findField = function (key, $parent) {
7356 return acf.findFields({
7357 key: key,
7358 limit: 1,
7359 parent: $parent,
7360 suppressFilters: true
7361 });
7362 };
7363
7364 /**
7365 * getField
7366 *
7367 * Returns a field instance
7368 *
7369 * @date 14/12/17
7370 * @since ACF 5.6.5
7371 *
7372 * @param jQuery|string $field jQuery element or field key.
7373 * @return object
7374 */
7375
7376 acf.getField = function ($field) {
7377 // allow jQuery
7378 if ($field instanceof jQuery) {
7379 // find fields
7380 } else {
7381 $field = acf.findField($field);
7382 }
7383
7384 // instantiate
7385 var field = $field.data('acf');
7386 if (!field) {
7387 field = acf.newField($field);
7388 }
7389
7390 // return
7391 return field;
7392 };
7393
7394 /**
7395 * getFields
7396 *
7397 * Returns multiple field instances
7398 *
7399 * @date 14/12/17
7400 * @since ACF 5.6.5
7401 *
7402 * @param jQuery|object $fields jQuery elements or query args.
7403 * @return array
7404 */
7405
7406 acf.getFields = function ($fields) {
7407 // allow jQuery
7408 if ($fields instanceof jQuery) {
7409 // find fields
7410 } else {
7411 $fields = acf.findFields($fields);
7412 }
7413
7414 // loop
7415 var fields = [];
7416 $fields.each(function () {
7417 var field = acf.getField($(this));
7418 fields.push(field);
7419 });
7420
7421 // return
7422 return fields;
7423 };
7424
7425 /**
7426 * findClosestField
7427 *
7428 * Returns the closest jQuery field element
7429 *
7430 * @date 9/4/18
7431 * @since ACF 5.6.9
7432 *
7433 * @param jQuery $el
7434 * @return jQuery
7435 */
7436
7437 acf.findClosestField = function ($el) {
7438 return $el.closest('.acf-field');
7439 };
7440
7441 /**
7442 * getClosestField
7443 *
7444 * Returns the closest field instance
7445 *
7446 * @date 22/1/18
7447 * @since ACF 5.6.5
7448 *
7449 * @param jQuery $el
7450 * @return object
7451 */
7452
7453 acf.getClosestField = function ($el) {
7454 var $field = acf.findClosestField($el);
7455 return this.getField($field);
7456 };
7457
7458 /**
7459 * addGlobalFieldAction
7460 *
7461 * Sets up callback logic for global field actions
7462 *
7463 * @date 15/6/18
7464 * @since ACF 5.6.9
7465 *
7466 * @param string action
7467 * @return void
7468 */
7469
7470 var addGlobalFieldAction = function (action) {
7471 // vars
7472 var globalAction = action;
7473 var pluralAction = action + '_fields'; // ready_fields
7474 var singleAction = action + '_field'; // ready_field
7475
7476 // global action
7477 var globalCallback = function ($el /*, arg1, arg2, etc*/) {
7478 //console.log( action, arguments );
7479
7480 // get args [$el, ...]
7481 var args = acf.arrayArgs(arguments);
7482 var extraArgs = args.slice(1);
7483
7484 // find fields
7485 var fields = acf.getFields({
7486 parent: $el
7487 });
7488
7489 // check
7490 if (fields.length) {
7491 // pluralAction
7492 var pluralArgs = [pluralAction, fields].concat(extraArgs);
7493 acf.doAction.apply(null, pluralArgs);
7494 }
7495 };
7496
7497 // plural action
7498 var pluralCallback = function (fields /*, arg1, arg2, etc*/) {
7499 //console.log( pluralAction, arguments );
7500
7501 // get args [fields, ...]
7502 var args = acf.arrayArgs(arguments);
7503 var extraArgs = args.slice(1);
7504
7505 // loop
7506 fields.map(function (field, i) {
7507 //setTimeout(function(){
7508 // singleAction
7509 var singleArgs = [singleAction, field].concat(extraArgs);
7510 acf.doAction.apply(null, singleArgs);
7511 //}, i * 100);
7512 });
7513 };
7514
7515 // add actions
7516 acf.addAction(globalAction, globalCallback);
7517 acf.addAction(pluralAction, pluralCallback);
7518
7519 // also add single action
7520 addSingleFieldAction(action);
7521 };
7522
7523 /**
7524 * addSingleFieldAction
7525 *
7526 * Sets up callback logic for single field actions
7527 *
7528 * @date 15/6/18
7529 * @since ACF 5.6.9
7530 *
7531 * @param string action
7532 * @return void
7533 */
7534
7535 var addSingleFieldAction = function (action) {
7536 // vars
7537 var singleAction = action + '_field'; // ready_field
7538 var singleEvent = action + 'Field'; // readyField
7539
7540 // single action
7541 var singleCallback = function (field /*, arg1, arg2, etc*/) {
7542 //console.log( singleAction, arguments );
7543
7544 // get args [field, ...]
7545 var args = acf.arrayArgs(arguments);
7546 var extraArgs = args.slice(1);
7547
7548 // action variations (ready_field/type=image)
7549 var variations = ['type', 'name', 'key'];
7550 variations.map(function (variation) {
7551 // vars
7552 var prefix = '/' + variation + '=' + field.get(variation);
7553
7554 // singleAction
7555 args = [singleAction + prefix, field].concat(extraArgs);
7556 acf.doAction.apply(null, args);
7557 });
7558
7559 // event
7560 if (singleFieldEvents.indexOf(action) > -1) {
7561 field.trigger(singleEvent, extraArgs);
7562 }
7563 };
7564
7565 // add actions
7566 acf.addAction(singleAction, singleCallback);
7567 };
7568
7569 // vars
7570 var globalFieldActions = ['prepare', 'ready', 'load', 'append', 'remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload'];
7571 var singleFieldActions = ['valid', 'invalid', 'enable', 'disable', 'new', 'duplicate'];
7572 var singleFieldEvents = ['remove', 'unmount', 'remount', 'sortstart', 'sortstop', 'show', 'hide', 'unload', 'valid', 'invalid', 'enable', 'disable', 'duplicate'];
7573
7574 // add
7575 globalFieldActions.map(addGlobalFieldAction);
7576 singleFieldActions.map(addSingleFieldAction);
7577
7578 /**
7579 * fieldsEventManager
7580 *
7581 * Manages field actions and events
7582 *
7583 * @date 15/12/17
7584 * @since ACF 5.6.5
7585 *
7586 * @param void
7587 * @param void
7588 */
7589
7590 var fieldsEventManager = new acf.Model({
7591 id: 'fieldsEventManager',
7592 events: {
7593 'click .acf-field a[href="#"]': 'onClick',
7594 'change .acf-field': 'onChange'
7595 },
7596 onClick: function (e) {
7597 // prevent default of any link with an href of #
7598 e.preventDefault();
7599 },
7600 onChange: function () {
7601 // preview hack allows post to save with no title or content
7602 $('#_acf_changed').val(1);
7603 if (acf.isGutenbergPostEditor()) {
7604 try {
7605 wp.data.dispatch('core/editor').editPost({
7606 meta: {
7607 _acf_changed: 1
7608 }
7609 });
7610 } catch (error) {
7611 console.log('ACF: Failed to update _acf_changed meta', error);
7612 }
7613 }
7614 }
7615 });
7616 var duplicateFieldsManager = new acf.Model({
7617 id: 'duplicateFieldsManager',
7618 actions: {
7619 duplicate: 'onDuplicate',
7620 duplicate_fields: 'onDuplicateFields'
7621 },
7622 onDuplicate: function ($el, $el2) {
7623 var fields = acf.getFields({
7624 parent: $el
7625 });
7626 if (fields.length) {
7627 var $fields = acf.findFields({
7628 parent: $el2
7629 });
7630 acf.doAction('duplicate_fields', fields, $fields);
7631 }
7632 },
7633 onDuplicateFields: function (fields, duplicates) {
7634 fields.map(function (field, i) {
7635 acf.doAction('duplicate_field', field, $(duplicates[i]));
7636 });
7637 }
7638 });
7639 })(jQuery);
7640
7641 /***/ }),
7642
7643 /***/ "./assets/src/js/_acf-helpers.js":
7644 /*!***************************************!*\
7645 !*** ./assets/src/js/_acf-helpers.js ***!
7646 \***************************************/
7647 /***/ (() => {
7648
7649 (function ($, undefined) {
7650 /**
7651 * refreshHelper
7652 *
7653 * description
7654 *
7655 * @date 1/7/18
7656 * @since ACF 5.6.9
7657 *
7658 * @param type $var Description. Default.
7659 * @return type Description.
7660 */
7661
7662 var refreshHelper = new acf.Model({
7663 priority: 90,
7664 actions: {
7665 new_field: 'refresh',
7666 show_field: 'refresh',
7667 hide_field: 'refresh',
7668 remove_field: 'refresh',
7669 unmount_field: 'refresh',
7670 remount_field: 'refresh'
7671 },
7672 refresh: function () {
7673 acf.refresh();
7674 }
7675 });
7676
7677 /**
7678 * mountHelper
7679 *
7680 * Adds compatibility for the 'unmount' and 'remount' actions added in 5.8.0
7681 *
7682 * @date 7/3/19
7683 * @since ACF 5.7.14
7684 *
7685 * @param void
7686 * @return void
7687 */
7688 var mountHelper = new acf.Model({
7689 priority: 1,
7690 actions: {
7691 sortstart: 'onSortstart',
7692 sortstop: 'onSortstop'
7693 },
7694 onSortstart: function ($item) {
7695 acf.doAction('unmount', $item);
7696 },
7697 onSortstop: function ($item) {
7698 acf.doAction('remount', $item);
7699 }
7700 });
7701
7702 /**
7703 * sortableHelper
7704 *
7705 * Adds compatibility for sorting a <tr> element
7706 *
7707 * @date 6/3/18
7708 * @since ACF 5.6.9
7709 *
7710 * @param void
7711 * @return void
7712 */
7713
7714 var sortableHelper = new acf.Model({
7715 actions: {
7716 sortstart: 'onSortstart'
7717 },
7718 onSortstart: function ($item, $placeholder) {
7719 // if $item is a tr, apply some css to the elements
7720 if ($item.is('tr')) {
7721 // replace $placeholder children with a single td
7722 // fixes "width calculation issues" due to conditional logic hiding some children
7723 $placeholder.html('<td style="padding:0;" colspan="' + $placeholder.children().length + '"></td>');
7724
7725 // add helper class to remove absolute positioning
7726 $item.addClass('acf-sortable-tr-helper');
7727
7728 // set fixed widths for children
7729 $item.children().each(function () {
7730 $(this).width($(this).width());
7731 });
7732
7733 // mimic height
7734 $placeholder.height($item.height() + 'px');
7735
7736 // remove class
7737 $item.removeClass('acf-sortable-tr-helper');
7738 }
7739 }
7740 });
7741
7742 /**
7743 * duplicateHelper
7744 *
7745 * Fixes browser bugs when duplicating an element
7746 *
7747 * @date 6/3/18
7748 * @since ACF 5.6.9
7749 *
7750 * @param void
7751 * @return void
7752 */
7753
7754 var duplicateHelper = new acf.Model({
7755 actions: {
7756 after_duplicate: 'onAfterDuplicate'
7757 },
7758 onAfterDuplicate: function ($el, $el2) {
7759 // get original values
7760 var vals = [];
7761 $el.find('select').each(function (i) {
7762 vals.push($(this).val());
7763 });
7764
7765 // set duplicate values
7766 $el2.find('select').each(function (i) {
7767 $(this).val(vals[i]);
7768 });
7769 }
7770 });
7771
7772 /**
7773 * tableHelper
7774 *
7775 * description
7776 *
7777 * @date 6/3/18
7778 * @since ACF 5.6.9
7779 *
7780 * @param type $var Description. Default.
7781 * @return type Description.
7782 */
7783
7784 var tableHelper = new acf.Model({
7785 id: 'tableHelper',
7786 priority: 20,
7787 actions: {
7788 refresh: 'renderTables'
7789 },
7790 renderTables: function ($el) {
7791 // loop
7792 var self = this;
7793 $('.acf-table:visible').each(function () {
7794 self.renderTable($(this));
7795 });
7796 },
7797 renderTable: function ($table) {
7798 // vars
7799 var $ths = $table.find('> thead > tr:visible > th[data-key]');
7800 var $tds = $table.find('> tbody > tr:visible > td[data-key]');
7801
7802 // bail early if no thead
7803 if (!$ths.length || !$tds.length) {
7804 return false;
7805 }
7806
7807 // visibility
7808 $ths.each(function (i) {
7809 // vars
7810 var $th = $(this);
7811 var key = $th.data('key');
7812 var $cells = $tds.filter('[data-key="' + key + '"]');
7813 var $hidden = $cells.filter('.acf-hidden');
7814
7815 // always remove empty and allow cells to be hidden
7816 $cells.removeClass('acf-empty');
7817
7818 // hide $th if all cells are hidden
7819 if ($cells.length === $hidden.length) {
7820 acf.hide($th);
7821
7822 // force all hidden cells to appear empty
7823 } else {
7824 acf.show($th);
7825 $hidden.addClass('acf-empty');
7826 }
7827 });
7828
7829 // clear width
7830 $ths.css('width', 'auto');
7831
7832 // get visible
7833 $ths = $ths.not('.acf-hidden');
7834
7835 // vars
7836 var availableWidth = 100;
7837 var colspan = $ths.length;
7838
7839 // set custom widths first
7840 var $fixedWidths = $ths.filter('[data-width]');
7841 $fixedWidths.each(function () {
7842 var width = $(this).data('width');
7843 $(this).css('width', width + '%');
7844 availableWidth -= width;
7845 });
7846
7847 // set auto widths
7848 var $auoWidths = $ths.not('[data-width]');
7849 if ($auoWidths.length) {
7850 var width = availableWidth / $auoWidths.length;
7851 $auoWidths.css('width', width + '%');
7852 availableWidth = 0;
7853 }
7854
7855 // avoid stretching issue
7856 if (availableWidth > 0) {
7857 $ths.last().css('width', 'auto');
7858 }
7859
7860 // update colspan on collapsed
7861 $tds.filter('.-collapsed-target').each(function () {
7862 // vars
7863 var $td = $(this);
7864
7865 // check if collapsed
7866 if ($td.parent().hasClass('-collapsed')) {
7867 $td.attr('colspan', $ths.length);
7868 } else {
7869 $td.removeAttr('colspan');
7870 }
7871 });
7872 }
7873 });
7874
7875 /**
7876 * fieldsHelper
7877 *
7878 * description
7879 *
7880 * @date 6/3/18
7881 * @since ACF 5.6.9
7882 *
7883 * @param type $var Description. Default.
7884 * @return type Description.
7885 */
7886
7887 var fieldsHelper = new acf.Model({
7888 id: 'fieldsHelper',
7889 priority: 30,
7890 actions: {
7891 refresh: 'renderGroups'
7892 },
7893 renderGroups: function () {
7894 // loop
7895 var self = this;
7896 $('.acf-fields:visible').each(function () {
7897 self.renderGroup($(this));
7898 });
7899 },
7900 renderGroup: function ($el) {
7901 // vars
7902 var top = 0;
7903 var height = 0;
7904 var $row = $();
7905
7906 // get fields
7907 var $fields = $el.children('.acf-field[data-width]:visible');
7908
7909 // bail early if no fields
7910 if (!$fields.length) {
7911 return false;
7912 }
7913
7914 // bail early if is .-left
7915 if ($el.hasClass('-left')) {
7916 $fields.removeAttr('data-width');
7917 $fields.css('width', 'auto');
7918 return false;
7919 }
7920
7921 // reset fields
7922 $fields.removeClass('-r0 -c0').css({
7923 'min-height': 0
7924 });
7925
7926 // loop
7927 $fields.each(function (i) {
7928 // vars
7929 var $field = $(this);
7930 var position = $field.position();
7931 var thisTop = Math.ceil(position.top);
7932 var thisLeft = Math.ceil(position.left);
7933
7934 // detect change in row
7935 if ($row.length && thisTop > top) {
7936 // set previous heights
7937 $row.css({
7938 'min-height': height + 'px'
7939 });
7940
7941 // update position due to change in row above
7942 position = $field.position();
7943 thisTop = Math.ceil(position.top);
7944 thisLeft = Math.ceil(position.left);
7945
7946 // reset vars
7947 top = 0;
7948 height = 0;
7949 $row = $();
7950 }
7951
7952 // rtl
7953 if (acf.get('rtl')) {
7954 thisLeft = Math.ceil($field.parent().width() - (position.left + $field.outerWidth()));
7955 }
7956
7957 // add classes
7958 if (thisTop == 0) {
7959 $field.addClass('-r0');
7960 } else if (thisLeft == 0) {
7961 $field.addClass('-c0');
7962 }
7963
7964 // get height after class change
7965 // - add 1 for subpixel rendering
7966 var thisHeight = Math.ceil($field.outerHeight()) + 1;
7967
7968 // set height
7969 height = Math.max(height, thisHeight);
7970
7971 // set y
7972 top = Math.max(top, thisTop);
7973
7974 // append
7975 $row = $row.add($field);
7976 });
7977
7978 // clean up
7979 if ($row.length) {
7980 $row.css({
7981 'min-height': height + 'px'
7982 });
7983 }
7984 }
7985 });
7986
7987 /**
7988 * Adds a body class when holding down the "shift" key.
7989 *
7990 * @date 06/05/2020
7991 * @since ACF 5.9.0
7992 */
7993 var bodyClassShiftHelper = new acf.Model({
7994 id: 'bodyClassShiftHelper',
7995 events: {
7996 keydown: 'onKeyDown',
7997 keyup: 'onKeyUp'
7998 },
7999 isShiftKey: function (e) {
8000 return e.keyCode === 16;
8001 },
8002 onKeyDown: function (e) {
8003 if (this.isShiftKey(e)) {
8004 $('body').addClass('acf-keydown-shift');
8005 }
8006 },
8007 onKeyUp: function (e) {
8008 if (this.isShiftKey(e)) {
8009 $('body').removeClass('acf-keydown-shift');
8010 }
8011 }
8012 });
8013 })(jQuery);
8014
8015 /***/ }),
8016
8017 /***/ "./assets/src/js/_acf-media.js":
8018 /*!*************************************!*\
8019 !*** ./assets/src/js/_acf-media.js ***!
8020 \*************************************/
8021 /***/ (() => {
8022
8023 (function ($, undefined) {
8024 /**
8025 * acf.newMediaPopup
8026 *
8027 * description
8028 *
8029 * @date 10/1/18
8030 * @since ACF 5.6.5
8031 *
8032 * @param type $var Description. Default.
8033 * @return type Description.
8034 */
8035
8036 acf.newMediaPopup = function (args) {
8037 // args
8038 var popup = null;
8039 var args = acf.parseArgs(args, {
8040 mode: 'select',
8041 // 'select', 'edit'
8042 title: '',
8043 // 'Upload Image'
8044 button: '',
8045 // 'Select Image'
8046 type: '',
8047 // 'image', ''
8048 field: false,
8049 // field instance
8050 allowedTypes: '',
8051 // '.jpg, .png, etc'
8052 library: 'all',
8053 // 'all', 'uploadedTo'
8054 multiple: false,
8055 // false, true, 'add'
8056 attachment: 0,
8057 // the attachment to edit
8058 autoOpen: true,
8059 // open the popup automatically
8060 open: function () {},
8061 // callback after close
8062 select: function () {},
8063 // callback after select
8064 close: function () {} // callback after close
8065 });
8066
8067 // initialize
8068 if (args.mode == 'edit') {
8069 popup = new acf.models.EditMediaPopup(args);
8070 } else {
8071 popup = new acf.models.SelectMediaPopup(args);
8072 }
8073
8074 // open popup (allow frame customization before opening)
8075 if (args.autoOpen) {
8076 setTimeout(function () {
8077 popup.open();
8078 }, 1);
8079 }
8080
8081 // action
8082 acf.doAction('new_media_popup', popup);
8083
8084 // return
8085 return popup;
8086 };
8087
8088 /**
8089 * getPostID
8090 *
8091 * description
8092 *
8093 * @date 10/1/18
8094 * @since ACF 5.6.5
8095 *
8096 * @param type $var Description. Default.
8097 * @return type Description.
8098 */
8099
8100 var getPostID = function () {
8101 var postID = acf.get('post_id');
8102 return acf.isNumeric(postID) ? postID : 0;
8103 };
8104
8105 /**
8106 * acf.getMimeTypes
8107 *
8108 * description
8109 *
8110 * @date 11/1/18
8111 * @since ACF 5.6.5
8112 *
8113 * @param type $var Description. Default.
8114 * @return type Description.
8115 */
8116
8117 acf.getMimeTypes = function () {
8118 return this.get('mimeTypes');
8119 };
8120 acf.getMimeType = function (name) {
8121 // vars
8122 var allTypes = acf.getMimeTypes();
8123
8124 // search
8125 if (allTypes[name] !== undefined) {
8126 return allTypes[name];
8127 }
8128
8129 // some types contain a mixed key such as "jpg|jpeg|jpe"
8130 for (var key in allTypes) {
8131 if (key.indexOf(name) !== -1) {
8132 return allTypes[key];
8133 }
8134 }
8135
8136 // return
8137 return false;
8138 };
8139
8140 /**
8141 * MediaPopup
8142 *
8143 * description
8144 *
8145 * @date 10/1/18
8146 * @since ACF 5.6.5
8147 *
8148 * @param type $var Description. Default.
8149 * @return type Description.
8150 */
8151
8152 var MediaPopup = acf.Model.extend({
8153 id: 'MediaPopup',
8154 data: {},
8155 defaults: {},
8156 frame: false,
8157 setup: function (props) {
8158 $.extend(this.data, props);
8159 },
8160 initialize: function () {
8161 // vars
8162 var options = this.getFrameOptions();
8163
8164 // add states
8165 this.addFrameStates(options);
8166
8167 // create frame
8168 var frame = wp.media(options);
8169
8170 // add args reference
8171 frame.acf = this;
8172
8173 // add events
8174 this.addFrameEvents(frame, options);
8175
8176 // store frame
8177 this.frame = frame;
8178 },
8179 open: function () {
8180 this.frame.open();
8181 },
8182 close: function () {
8183 this.frame.close();
8184 },
8185 remove: function () {
8186 this.frame.detach();
8187 this.frame.remove();
8188 },
8189 getFrameOptions: function () {
8190 // vars
8191 var options = {
8192 title: this.get('title'),
8193 multiple: this.get('multiple'),
8194 library: {},
8195 states: []
8196 };
8197
8198 // type
8199 if (this.get('type')) {
8200 options.library.type = this.get('type');
8201 }
8202
8203 // type
8204 if (this.get('library') === 'uploadedTo') {
8205 options.library.uploadedTo = getPostID();
8206 }
8207
8208 // attachment
8209 if (this.get('attachment')) {
8210 options.library.post__in = [this.get('attachment')];
8211 }
8212
8213 // button
8214 if (this.get('button')) {
8215 options.button = {
8216 text: this.get('button')
8217 };
8218 }
8219
8220 // return
8221 return options;
8222 },
8223 addFrameStates: function (options) {
8224 // create query
8225 var Query = wp.media.query(options.library);
8226
8227 // add _acfuploader
8228 // this is super wack!
8229 // if you add _acfuploader to the options.library args, new uploads will not be added to the library view.
8230 // this has been traced back to the wp.media.model.Query initialize function (which can't be overridden)
8231 // Adding any custom args will cause the Attachments to not observe the uploader queue
8232 // To bypass this security issue, we add in the args AFTER the Query has been initialized
8233 // options.library._acfuploader = settings.field;
8234 if (this.get('field') && acf.isset(Query, 'mirroring', 'args')) {
8235 Query.mirroring.args._acfuploader = this.get('field');
8236 }
8237
8238 // add states
8239 options.states.push(
8240 // main state
8241 new wp.media.controller.Library({
8242 library: Query,
8243 multiple: this.get('multiple'),
8244 title: this.get('title'),
8245 priority: 20,
8246 filterable: 'all',
8247 editable: true,
8248 allowLocalEdits: true
8249 }));
8250
8251 // edit image functionality (added in WP 3.9)
8252 if (acf.isset(wp, 'media', 'controller', 'EditImage')) {
8253 options.states.push(new wp.media.controller.EditImage());
8254 }
8255 },
8256 addFrameEvents: function (frame, options) {
8257 // log all events
8258 //frame.on('all', function( e ) {
8259 // console.log( 'frame all: %o', e );
8260 //});
8261
8262 // add class
8263 frame.on('open', function () {
8264 this.$el.closest('.media-modal').addClass('acf-media-modal -' + this.acf.get('mode'));
8265 }, frame);
8266
8267 // edit image view
8268 // source: media-views.js:2410 editImageContent()
8269 frame.on('content:render:edit-image', function () {
8270 var image = this.state().get('image');
8271 var view = new wp.media.view.EditImage({
8272 model: image,
8273 controller: this
8274 }).render();
8275 this.content.set(view);
8276
8277 // after creating the wrapper view, load the actual editor via an ajax call
8278 view.loadEditor();
8279 }, frame);
8280
8281 // update toolbar button
8282 //frame.on( 'toolbar:create:select', function( toolbar ) {
8283 // toolbar.view = new wp.media.view.Toolbar.Select({
8284 // text: frame.options._button,
8285 // controller: this
8286 // });
8287 //}, frame );
8288
8289 // on select
8290 frame.on('select', function () {
8291 // vars
8292 var selection = frame.state().get('selection');
8293
8294 // if selecting images
8295 if (selection) {
8296 // loop
8297 selection.each(function (attachment, i) {
8298 frame.acf.get('select').apply(frame.acf, [attachment, i]);
8299 });
8300 }
8301 });
8302
8303 // on close
8304 frame.on('close', function () {
8305 // callback and remove
8306 setTimeout(function () {
8307 frame.acf.get('close').apply(frame.acf);
8308 frame.acf.remove();
8309 }, 1);
8310 });
8311 }
8312 });
8313
8314 /**
8315 * acf.models.SelectMediaPopup
8316 *
8317 * description
8318 *
8319 * @date 10/1/18
8320 * @since ACF 5.6.5
8321 *
8322 * @param type $var Description. Default.
8323 * @return type Description.
8324 */
8325
8326 acf.models.SelectMediaPopup = MediaPopup.extend({
8327 id: 'SelectMediaPopup',
8328 setup: function (props) {
8329 // default button
8330 if (!props.button) {
8331 props.button = acf._x('Select', 'verb');
8332 }
8333
8334 // parent
8335 MediaPopup.prototype.setup.apply(this, arguments);
8336 },
8337 addFrameEvents: function (frame, options) {
8338 // plupload
8339 // adds _acfuploader param to validate uploads
8340 if (acf.isset(_wpPluploadSettings, 'defaults', 'multipart_params')) {
8341 // add _acfuploader so that Uploader will inherit
8342 _wpPluploadSettings.defaults.multipart_params._acfuploader = this.get('field');
8343
8344 // remove acf_field so future Uploaders won't inherit
8345 frame.on('open', function () {
8346 delete _wpPluploadSettings.defaults.multipart_params._acfuploader;
8347 });
8348 }
8349
8350 // browse
8351 frame.on('content:activate:browse', function () {
8352 // vars
8353 var toolbar = false;
8354
8355 // populate above vars making sure to allow for failure
8356 // perhaps toolbar does not exist because the frame open is Upload Files
8357 try {
8358 toolbar = frame.content.get().toolbar;
8359 } catch (e) {
8360 console.log(e);
8361 return;
8362 }
8363
8364 // callback
8365 frame.acf.customizeFilters.apply(frame.acf, [toolbar]);
8366 });
8367
8368 // parent
8369 MediaPopup.prototype.addFrameEvents.apply(this, arguments);
8370 },
8371 customizeFilters: function (toolbar) {
8372 // Get the AttachmentFilters view from the toolbar.
8373 // WP < 7.0: toolbar.get('filters') returns the AttachmentFilters view directly.
8374 // WP 7.0+: toolbar.get('filters') returns a wrapper View; the
8375 // AttachmentFilters view is nested inside its subviews.
8376 var filtersView = toolbar.get('filters');
8377 var filters = filtersView;
8378 if (filtersView && !filtersView.filters) {
8379 // WP 7.0+: find the AttachmentFilters view in the container's subviews.
8380 var subviews = filtersView.views ? filtersView.views.get() : [];
8381 for (var i = 0; i < subviews.length; i++) {
8382 if (subviews[i].filters) {
8383 filters = subviews[i];
8384 break;
8385 }
8386 }
8387 }
8388
8389 // Bail if the AttachmentFilters view couldn't be resolved (e.g. core
8390 // moves the view again), so the modal degrades to the default filters
8391 // instead of crashing.
8392 if (!filters || !filters.filters) {
8393 return;
8394 }
8395
8396 // image
8397 if (this.get('type') == 'image') {
8398 // update all
8399 filters.filters.all.text = acf.__('All images');
8400
8401 // remove some filters
8402 delete filters.filters.audio;
8403 delete filters.filters.video;
8404 delete filters.filters.image;
8405
8406 // update all filters to show images
8407 $.each(filters.filters, function (i, filter) {
8408 filter.props.type = filter.props.type || 'image';
8409 });
8410 }
8411
8412 // specific types
8413 if (this.get('allowedTypes')) {
8414 // convert ".jpg, .png" into ["jpg", "png"]
8415 var allowedTypes = this.get('allowedTypes').split(' ').join('').split('.').join('').split(',');
8416
8417 // loop
8418 allowedTypes.map(function (name) {
8419 // get type
8420 var mimeType = acf.getMimeType(name);
8421
8422 // bail early if no type
8423 if (!mimeType) return;
8424
8425 // create new filter
8426 var newFilter = {
8427 text: mimeType,
8428 props: {
8429 status: null,
8430 type: mimeType,
8431 uploadedTo: null,
8432 orderby: 'date',
8433 order: 'DESC'
8434 },
8435 priority: 20
8436 };
8437
8438 // append
8439 filters.filters[mimeType] = newFilter;
8440 });
8441 }
8442
8443 // uploaded to post
8444 if (this.get('library') === 'uploadedTo') {
8445 // vars
8446 var uploadedTo = this.frame.options.library.uploadedTo;
8447
8448 // remove some filters
8449 delete filters.filters.unattached;
8450 delete filters.filters.uploaded;
8451
8452 // add uploadedTo to filters
8453 $.each(filters.filters, function (i, filter) {
8454 filter.text += ' (' + acf.__('Uploaded to this post') + ')';
8455 filter.props.uploadedTo = uploadedTo;
8456 });
8457 }
8458
8459 // add _acfuploader to filters
8460 var field = this.get('field');
8461 $.each(filters.filters, function (k, filter) {
8462 filter.props._acfuploader = field;
8463 });
8464
8465 // add _acfuploader to search
8466 var search = toolbar.get('search');
8467 search.model.attributes._acfuploader = field;
8468
8469 // render (custom function added to prototype)
8470 if (filters.renderFilters) {
8471 filters.renderFilters();
8472 }
8473 }
8474 });
8475
8476 /**
8477 * acf.models.EditMediaPopup
8478 *
8479 * description
8480 *
8481 * @date 10/1/18
8482 * @since ACF 5.6.5
8483 *
8484 * @param type $var Description. Default.
8485 * @return type Description.
8486 */
8487
8488 acf.models.EditMediaPopup = MediaPopup.extend({
8489 id: 'SelectMediaPopup',
8490 setup: function (props) {
8491 // default button
8492 if (!props.button) {
8493 props.button = acf._x('Update', 'verb');
8494 }
8495
8496 // parent
8497 MediaPopup.prototype.setup.apply(this, arguments);
8498 },
8499 addFrameEvents: function (frame, options) {
8500 // add class
8501 frame.on('open', function () {
8502 // add class
8503 this.$el.closest('.media-modal').addClass('acf-expanded');
8504
8505 // set to browse
8506 if (this.content.mode() != 'browse') {
8507 this.content.mode('browse');
8508 }
8509
8510 // set selection
8511 var state = this.state();
8512 var selection = state.get('selection');
8513 var attachment = wp.media.attachment(frame.acf.get('attachment'));
8514 selection.add(attachment);
8515 }, frame);
8516
8517 // parent
8518 MediaPopup.prototype.addFrameEvents.apply(this, arguments);
8519 }
8520 });
8521
8522 /**
8523 * customizePrototypes
8524 *
8525 * description
8526 *
8527 * @date 11/1/18
8528 * @since ACF 5.6.5
8529 *
8530 * @param type $var Description. Default.
8531 * @return type Description.
8532 */
8533
8534 var customizePrototypes = new acf.Model({
8535 id: 'customizePrototypes',
8536 wait: 'ready',
8537 initialize: function () {
8538 // bail early if no media views
8539 if (!acf.isset(window, 'wp', 'media', 'view')) {
8540 return;
8541 }
8542
8543 // fix bug where CPT without "editor" does not set post.id setting which then prevents uploadedTo from working
8544 var postID = getPostID();
8545 if (postID && acf.isset(wp, 'media', 'view', 'settings', 'post')) {
8546 wp.media.view.settings.post.id = postID;
8547 }
8548
8549 // customize
8550 this.customizeAttachmentsButton();
8551 this.customizeAttachmentsRouter();
8552 this.customizeAttachmentFilters();
8553 this.customizeAttachmentCompat();
8554 this.customizeAttachmentLibrary();
8555 },
8556 customizeAttachmentsButton: function () {
8557 // validate
8558 if (!acf.isset(wp, 'media', 'view', 'Button')) {
8559 return;
8560 }
8561
8562 // Extend
8563 var Button = wp.media.view.Button;
8564 wp.media.view.Button = Button.extend({
8565 // Fix bug where "Select" button appears blank after editing an image.
8566 // Do this by simplifying Button initialize function and avoid deleting this.options.
8567 initialize: function () {
8568 var options = _.defaults(this.options, this.defaults);
8569 this.model = new Backbone.Model(options);
8570 this.listenTo(this.model, 'change', this.render);
8571 }
8572 });
8573 },
8574 customizeAttachmentsRouter: function () {
8575 // validate
8576 if (!acf.isset(wp, 'media', 'view', 'Router')) {
8577 return;
8578 }
8579
8580 // vars
8581 var Parent = wp.media.view.Router;
8582
8583 // extend
8584 wp.media.view.Router = Parent.extend({
8585 addExpand: function () {
8586 // vars
8587 var $a = $(['<a href="#" class="acf-expand-details">', '<span class="is-closed"><i class="acf-icon -left -small"></i>' + acf.__('Expand Details') + '</span>', '<span class="is-open"><i class="acf-icon -right -small"></i>' + acf.__('Collapse Details') + '</span>', '</a>'].join(''));
8588
8589 // add events
8590 $a.on('click', function (e) {
8591 e.preventDefault();
8592 var $div = $(this).closest('.media-modal');
8593 if ($div.hasClass('acf-expanded')) {
8594 $div.removeClass('acf-expanded');
8595 } else {
8596 $div.addClass('acf-expanded');
8597 }
8598 });
8599
8600 // append
8601 this.$el.append($a);
8602 },
8603 initialize: function () {
8604 // initialize
8605 Parent.prototype.initialize.apply(this, arguments);
8606
8607 // add buttons
8608 this.addExpand();
8609
8610 // return
8611 return this;
8612 }
8613 });
8614 },
8615 customizeAttachmentFilters: function () {
8616 // validate
8617 if (!acf.isset(wp, 'media', 'view', 'AttachmentFilters', 'All')) {
8618 return;
8619 }
8620
8621 // vars
8622 var Parent = wp.media.view.AttachmentFilters.All;
8623
8624 // renderFilters
8625 // copied from media-views.js:6939
8626 Parent.prototype.renderFilters = function () {
8627 // Build `<option>` elements.
8628 this.$el.html(_.chain(this.filters).map(function (filter, value) {
8629 return {
8630 el: $('<option></option>').val(value).html(filter.text)[0],
8631 priority: filter.priority || 50
8632 };
8633 }, this).sortBy('priority').pluck('el').value());
8634 };
8635 },
8636 customizeAttachmentCompat: function () {
8637 // validate
8638 if (!acf.isset(wp, 'media', 'view', 'AttachmentCompat')) {
8639 return;
8640 }
8641
8642 // vars
8643 var AttachmentCompat = wp.media.view.AttachmentCompat;
8644 var timeout = false;
8645
8646 // extend
8647 wp.media.view.AttachmentCompat = AttachmentCompat.extend({
8648 render: function () {
8649 // WP bug
8650 // When multiple media frames exist on the same page (WP content, WYSIWYG, image, file ),
8651 // WP creates multiple instances of this AttachmentCompat view.
8652 // Each instance will attempt to render when a new modal is created.
8653 // Use a property to avoid this and only render once per instance.
8654 if (this.rendered) {
8655 return this;
8656 }
8657
8658 // render HTML
8659 AttachmentCompat.prototype.render.apply(this, arguments);
8660
8661 // when uploading, render is called twice.
8662 // ignore first render by checking for #acf-form-data element
8663 if (!this.$('#acf-form-data').length) {
8664 return this;
8665 }
8666
8667 // clear timeout
8668 clearTimeout(timeout);
8669
8670 // setTimeout
8671 timeout = setTimeout($.proxy(function () {
8672 this.rendered = true;
8673 acf.doAction('append', this.$el);
8674 }, this), 50);
8675
8676 // return
8677 return this;
8678 },
8679 save: function (event) {
8680 var data = {};
8681 if (event) {
8682 event.preventDefault();
8683 }
8684
8685 //_.each( this.$el.serializeArray(), function( pair ) {
8686 // data[ pair.name ] = pair.value;
8687 //});
8688
8689 // Serialize data more thoroughly to allow checkbox inputs to save.
8690 data = acf.serializeForAjax(this.$el);
8691 this.controller.trigger('attachment:compat:waiting', ['waiting']);
8692 this.model.saveCompat(data).always(_.bind(this.postSave, this));
8693 }
8694 });
8695 },
8696 customizeAttachmentLibrary: function () {
8697 // validate
8698 if (!acf.isset(wp, 'media', 'view', 'Attachment', 'Library')) {
8699 return;
8700 }
8701
8702 // vars
8703 var AttachmentLibrary = wp.media.view.Attachment.Library;
8704
8705 // extend
8706 wp.media.view.Attachment.Library = AttachmentLibrary.extend({
8707 render: function () {
8708 // vars
8709 var popup = acf.isget(this, 'controller', 'acf');
8710 var attributes = acf.isget(this, 'model', 'attributes');
8711
8712 // check vars exist to avoid errors
8713 if (popup && attributes) {
8714 // show errors
8715 if (attributes.acf_errors) {
8716 this.$el.addClass('acf-disabled');
8717 }
8718
8719 // disable selected
8720 var selected = popup.get('selected');
8721 if (selected && selected.indexOf(attributes.id) > -1) {
8722 this.$el.addClass('acf-selected');
8723 }
8724 }
8725
8726 // render
8727 return AttachmentLibrary.prototype.render.apply(this, arguments);
8728 },
8729 /*
8730 * toggleSelection
8731 *
8732 * This function is called before an attachment is selected
8733 * A good place to check for errors and prevent the 'select' function from being fired
8734 *
8735 * @type function
8736 * @date 29/09/2016
8737 * @since ACF 5.4.0
8738 *
8739 * @param options (object)
8740 * @return n/a
8741 */
8742
8743 toggleSelection: function (options) {
8744 // vars
8745 // source: wp-includes/js/media-views.js:2880
8746 var collection = this.collection,
8747 selection = this.options.selection,
8748 model = this.model,
8749 single = selection.single();
8750
8751 // vars
8752 var frame = this.controller;
8753 var errors = acf.isget(this, 'model', 'attributes', 'acf_errors');
8754 var $sidebar = frame.$el.find('.media-frame-content .media-sidebar');
8755
8756 // remove previous error
8757 $sidebar.children('.acf-selection-error').remove();
8758
8759 // show attachment details
8760 $sidebar.children().removeClass('acf-hidden');
8761
8762 // add message
8763 if (frame && errors) {
8764 // vars
8765 var filename = acf.isget(this, 'model', 'attributes', 'filename');
8766
8767 // hide attachment details
8768 // Gallery field continues to show previously selected attachment...
8769 $sidebar.children().addClass('acf-hidden');
8770
8771 // append message
8772 $sidebar.prepend(['<div class="acf-selection-error">', '<span class="selection-error-label">' + acf.__('Restricted') + '</span>', '<span class="selection-error-filename">' + filename + '</span>', '<span class="selection-error-message">' + errors + '</span>', '</div>'].join(''));
8773
8774 // reset selection (unselects all attachments)
8775 selection.reset();
8776
8777 // set single (attachment displayed in sidebar)
8778 selection.single(model);
8779
8780 // return and prevent 'select' form being fired
8781 return;
8782 }
8783
8784 // return
8785 return AttachmentLibrary.prototype.toggleSelection.apply(this, arguments);
8786 }
8787 });
8788 }
8789 });
8790 })(jQuery);
8791
8792 /***/ }),
8793
8794 /***/ "./assets/src/js/_acf-postbox.js":
8795 /*!***************************************!*\
8796 !*** ./assets/src/js/_acf-postbox.js ***!
8797 \***************************************/
8798 /***/ (() => {
8799
8800 (function ($, undefined) {
8801 /**
8802 * postboxManager
8803 *
8804 * Manages postboxes on the screen.
8805 *
8806 * @date 25/5/19
8807 * @since ACF 5.8.1
8808 *
8809 * @param void
8810 * @return void
8811 */
8812 var postboxManager = new acf.Model({
8813 wait: 'prepare',
8814 priority: 1,
8815 initialize: function () {
8816 (acf.get('postboxes') || []).map(acf.newPostbox);
8817 }
8818 });
8819
8820 /**
8821 * acf.getPostbox
8822 *
8823 * Returns a postbox instance.
8824 *
8825 * @date 23/9/18
8826 * @since ACF 5.7.7
8827 *
8828 * @param mixed $el Either a jQuery element or the postbox id.
8829 * @return object
8830 */
8831 acf.getPostbox = function ($el) {
8832 // allow string parameter
8833 if (typeof arguments[0] == 'string') {
8834 $el = $('#' + arguments[0]);
8835 }
8836
8837 // return instance
8838 return acf.getInstance($el);
8839 };
8840
8841 /**
8842 * acf.getPostboxes
8843 *
8844 * Returns an array of postbox instances.
8845 *
8846 * @date 23/9/18
8847 * @since ACF 5.7.7
8848 *
8849 * @param void
8850 * @return array
8851 */
8852 acf.getPostboxes = function () {
8853 return acf.getInstances($('.acf-postbox'));
8854 };
8855
8856 /**
8857 * acf.newPostbox
8858 *
8859 * Returns a new postbox instance for the given props.
8860 *
8861 * @date 20/9/18
8862 * @since ACF 5.7.6
8863 *
8864 * @param object props The postbox properties.
8865 * @return object
8866 */
8867 acf.newPostbox = function (props) {
8868 return new acf.models.Postbox(props);
8869 };
8870
8871 /**
8872 * acf.models.Postbox
8873 *
8874 * The postbox model.
8875 *
8876 * @date 20/9/18
8877 * @since ACF 5.7.6
8878 *
8879 * @param void
8880 * @return void
8881 */
8882 acf.models.Postbox = acf.Model.extend({
8883 data: {
8884 id: '',
8885 key: '',
8886 style: 'default',
8887 label: 'top',
8888 edit: ''
8889 },
8890 setup: function (props) {
8891 // compatibility
8892 if (props.editLink) {
8893 props.edit = props.editLink;
8894 }
8895
8896 // extend data
8897 $.extend(this.data, props);
8898
8899 // set $el
8900 this.$el = this.$postbox();
8901 },
8902 $postbox: function () {
8903 return $('#' + this.get('id'));
8904 },
8905 $hide: function () {
8906 return $('#' + this.get('id') + '-hide');
8907 },
8908 $hideLabel: function () {
8909 return this.$hide().parent();
8910 },
8911 $hndle: function () {
8912 return this.$('> .hndle');
8913 },
8914 $handleActions: function () {
8915 return this.$('> .postbox-header .handle-actions');
8916 },
8917 $inside: function () {
8918 return this.$('> .inside');
8919 },
8920 isVisible: function () {
8921 return this.$el.hasClass('acf-hidden');
8922 },
8923 isHiddenByScreenOptions: function () {
8924 return this.$el.hasClass('hide-if-js') || this.$el.css('display') == 'none';
8925 },
8926 initialize: function () {
8927 // Add default class.
8928 this.$el.addClass('acf-postbox');
8929
8930 // Add field group style class (ignore in block editor).
8931 if (acf.get('editor') !== 'block') {
8932 var style = this.get('style');
8933 if (style !== 'default') {
8934 this.$el.addClass(style);
8935 }
8936 }
8937
8938 // Add .inside class.
8939 this.$inside().addClass('acf-fields').addClass('-' + this.get('label'));
8940
8941 // Append edit link.
8942 var edit = this.get('edit');
8943 if (edit) {
8944 var html = '<a href="' + edit + '" class="dashicons dashicons-admin-generic acf-hndle-cog acf-js-tooltip" title="' + acf.__('Edit field group') + '"></a>';
8945 var $handleActions = this.$handleActions();
8946 if ($handleActions.length) {
8947 $handleActions.prepend(html);
8948 } else {
8949 this.$hndle().append(html);
8950 }
8951 }
8952
8953 // Show postbox.
8954 this.show();
8955 },
8956 show: function () {
8957 // If disabled by screen options, set checked to false and return.
8958 if (this.$el.hasClass('hide-if-js')) {
8959 this.$hide().prop('checked', false);
8960 return;
8961 }
8962
8963 // Show label.
8964 this.$hideLabel().show();
8965
8966 // toggle on checkbox
8967 this.$hide().prop('checked', true);
8968
8969 // Show postbox
8970 this.$el.show().removeClass('acf-hidden');
8971
8972 // Do action.
8973 acf.doAction('show_postbox', this);
8974 },
8975 enable: function () {
8976 acf.enable(this.$el, 'postbox');
8977 },
8978 showEnable: function () {
8979 this.enable();
8980 this.show();
8981 },
8982 hide: function () {
8983 // Hide label.
8984 this.$hideLabel().hide();
8985
8986 // Hide postbox
8987 this.$el.hide().addClass('acf-hidden');
8988
8989 // Do action.
8990 acf.doAction('hide_postbox', this);
8991 },
8992 disable: function () {
8993 acf.disable(this.$el, 'postbox');
8994 },
8995 hideDisable: function () {
8996 this.disable();
8997 this.hide();
8998 },
8999 html: function (html) {
9000 // Update HTML.
9001 this.$inside().html(html);
9002
9003 // Do action.
9004 acf.doAction('append', this.$el);
9005 }
9006 });
9007 })(jQuery);
9008
9009 /***/ }),
9010
9011 /***/ "./assets/src/js/_acf-screen.js":
9012 /*!**************************************!*\
9013 !*** ./assets/src/js/_acf-screen.js ***!
9014 \**************************************/
9015 /***/ (() => {
9016
9017 (function ($, undefined) {
9018 acf.screen = new acf.Model({
9019 active: true,
9020 xhr: false,
9021 timeout: false,
9022 wait: 'load',
9023 events: {
9024 'change #page_template': 'onChange',
9025 'change #parent_id': 'onChange',
9026 'change #post-formats-select': 'onChange',
9027 'change .categorychecklist': 'onChange',
9028 'change .tagsdiv': 'onChange',
9029 'change .acf-taxonomy-field[data-save="1"]': 'onChange',
9030 'change #product-type': 'onChange'
9031 },
9032 isPost: function () {
9033 return acf.get('screen') === 'post';
9034 },
9035 isUser: function () {
9036 return acf.get('screen') === 'user';
9037 },
9038 isTaxonomy: function () {
9039 return acf.get('screen') === 'taxonomy';
9040 },
9041 isAttachment: function () {
9042 return acf.get('screen') === 'attachment';
9043 },
9044 isNavMenu: function () {
9045 return acf.get('screen') === 'nav_menu';
9046 },
9047 isWidget: function () {
9048 return acf.get('screen') === 'widget';
9049 },
9050 isComment: function () {
9051 return acf.get('screen') === 'comment';
9052 },
9053 getPageTemplate: function () {
9054 var $el = $('#page_template');
9055 return $el.length ? $el.val() : null;
9056 },
9057 getPageParent: function (e, $el) {
9058 var $el = $('#parent_id');
9059 return $el.length ? $el.val() : null;
9060 },
9061 getPageType: function (e, $el) {
9062 return this.getPageParent() ? 'child' : 'parent';
9063 },
9064 getPostType: function () {
9065 return $('#post_type').val();
9066 },
9067 getPostFormat: function (e, $el) {
9068 var $el = $('#post-formats-select input:checked');
9069 if ($el.length) {
9070 var val = $el.val();
9071 return val == '0' ? 'standard' : val;
9072 }
9073 return null;
9074 },
9075 getPostCoreTerms: function () {
9076 // vars
9077 var terms = {};
9078
9079 // serialize WP taxonomy postboxes
9080 var data = acf.serialize($('.categorydiv, .tagsdiv'));
9081
9082 // use tax_input (tag, custom-taxonomy) when possible.
9083 // this data is already formatted in taxonomy => [terms].
9084 if (data.tax_input) {
9085 terms = data.tax_input;
9086 }
9087
9088 // append "category" which uses a different name
9089 if (data.post_category) {
9090 terms.category = data.post_category;
9091 }
9092
9093 // convert any string values (tags) into array format
9094 for (var tax in terms) {
9095 if (!acf.isArray(terms[tax])) {
9096 terms[tax] = terms[tax].split(/,[\s]?/);
9097 }
9098 }
9099
9100 // return
9101 return terms;
9102 },
9103 getPostTerms: function () {
9104 // Get core terms.
9105 var terms = this.getPostCoreTerms();
9106
9107 // loop over taxonomy fields and add their values
9108 acf.getFields({
9109 type: 'taxonomy'
9110 }).map(function (field) {
9111 // ignore fields that don't save
9112 if (!field.get('save')) {
9113 return;
9114 }
9115
9116 // vars
9117 var val = field.val();
9118 var tax = field.get('taxonomy');
9119
9120 // check val
9121 if (val) {
9122 // ensure terms exists
9123 terms[tax] = terms[tax] || [];
9124
9125 // ensure val is an array
9126 val = acf.isArray(val) ? val : [val];
9127
9128 // append
9129 terms[tax] = terms[tax].concat(val);
9130 }
9131 });
9132
9133 // add WC product type
9134 if ((productType = this.getProductType()) !== null) {
9135 terms.product_type = [productType];
9136 }
9137
9138 // remove duplicate values
9139 for (var tax in terms) {
9140 terms[tax] = acf.uniqueArray(terms[tax]);
9141 }
9142
9143 // return
9144 return terms;
9145 },
9146 getProductType: function () {
9147 var $el = $('#product-type');
9148 return $el.length ? $el.val() : null;
9149 },
9150 check: function () {
9151 // bail early if not for post
9152 if (acf.get('screen') !== 'post') {
9153 return;
9154 }
9155
9156 // abort XHR if is already loading AJAX data
9157 if (this.xhr) {
9158 this.xhr.abort();
9159 }
9160
9161 // vars
9162 var ajaxData = acf.parseArgs(this.data, {
9163 action: 'acf/ajax/check_screen',
9164 screen: acf.get('screen'),
9165 exists: []
9166 });
9167
9168 // post id
9169 if (this.isPost()) {
9170 ajaxData.post_id = acf.get('post_id');
9171 }
9172
9173 // post type
9174 if ((postType = this.getPostType()) !== null) {
9175 ajaxData.post_type = postType;
9176 }
9177
9178 // page template
9179 if ((pageTemplate = this.getPageTemplate()) !== null) {
9180 ajaxData.page_template = pageTemplate;
9181 }
9182
9183 // page parent
9184 if ((pageParent = this.getPageParent()) !== null) {
9185 ajaxData.page_parent = pageParent;
9186 }
9187
9188 // page type
9189 if ((pageType = this.getPageType()) !== null) {
9190 ajaxData.page_type = pageType;
9191 }
9192
9193 // post format
9194 if ((postFormat = this.getPostFormat()) !== null) {
9195 ajaxData.post_format = postFormat;
9196 }
9197
9198 // post terms
9199 if ((postTerms = this.getPostTerms()) !== null) {
9200 ajaxData.post_terms = postTerms;
9201 }
9202
9203 // add array of existing postboxes to increase performance and reduce JSON HTML
9204 acf.getPostboxes().map(function (postbox) {
9205 ajaxData.exists.push(postbox.get('key'));
9206 });
9207
9208 // filter
9209 ajaxData = acf.applyFilters('check_screen_args', ajaxData);
9210
9211 // success
9212 var onSuccess = function (json) {
9213 // Render post screen.
9214 if (acf.get('screen') == 'post') {
9215 this.renderPostScreen(json);
9216
9217 // Render user screen.
9218 } else if (acf.get('screen') == 'user') {
9219 this.renderUserScreen(json);
9220 }
9221
9222 // action
9223 acf.doAction('check_screen_complete', json, ajaxData);
9224 };
9225
9226 // ajax
9227 this.xhr = $.ajax({
9228 url: acf.get('ajaxurl'),
9229 data: acf.prepareForAjax(ajaxData),
9230 type: 'post',
9231 dataType: 'json',
9232 context: this,
9233 success: onSuccess
9234 });
9235 },
9236 onChange: function (e, $el) {
9237 this.setTimeout(this.check, 1);
9238 },
9239 renderPostScreen: function (data) {
9240 // Helper function to copy events
9241 var copyEvents = function ($from, $to) {
9242 var events = $._data($from[0]).events;
9243 for (var type in events) {
9244 for (var i = 0; i < events[type].length; i++) {
9245 $to.on(type, events[type][i].handler);
9246 }
9247 }
9248 };
9249
9250 // Helper function to sort metabox.
9251 var sortMetabox = function (id, ids) {
9252 // Find position of id within ids.
9253 var index = ids.indexOf(id);
9254
9255 // Bail early if index not found.
9256 if (index == -1) {
9257 return false;
9258 }
9259
9260 // Loop over metaboxes behind (in reverse order).
9261 for (var i = index - 1; i >= 0; i--) {
9262 if ($('#' + ids[i]).length) {
9263 return $('#' + ids[i]).after($('#' + id));
9264 }
9265 }
9266
9267 // Loop over metaboxes infront.
9268 for (var i = index + 1; i < ids.length; i++) {
9269 if ($('#' + ids[i]).length) {
9270 return $('#' + ids[i]).before($('#' + id));
9271 }
9272 }
9273
9274 // Return false if not sorted.
9275 return false;
9276 };
9277
9278 // Keep track of visible and hidden postboxes.
9279 data.visible = [];
9280 data.hidden = [];
9281
9282 // Show these postboxes.
9283 data.results = data.results.map(function (result, i) {
9284 // vars
9285 var postbox = acf.getPostbox(result.id);
9286
9287 // Prevent "acf_after_title" position in Block Editor.
9288 if (acf.isGutenberg() && result.position == 'acf_after_title') {
9289 result.position = 'normal';
9290 }
9291
9292 // Create postbox if doesn't exist.
9293 if (!postbox) {
9294 var postboxHeader = ['<div class="postbox-header">', '<h2 class="hndle ui-sortable-handle">', '<span>' + result.title + '</span>', '</h2>', '<div class="handle-actions hide-if-no-js">', '<button type="button" class="handlediv" aria-expanded="true">', '<span class="screen-reader-text">' + acf.__('Toggle panel') + ': ' + result.title + '</span>', '<span class="toggle-indicator" aria-hidden="true"></span>', '</button>', '</div>', '</div>'].join('');
9295
9296 // Ensure result.classes is set.
9297 if (!result.classes) result.classes = '';
9298
9299 // Create it.
9300 var $postbox = $(['<div id="' + result.id + '" class="postbox ' + result.classes + '">', postboxHeader, '<div class="inside">', result.html, '</div>', '</div>'].join(''));
9301
9302 // Create new hide toggle.
9303 if ($('#adv-settings').length) {
9304 var $prefs = $('#adv-settings .metabox-prefs');
9305 var $label = $(['<label for="' + result.id + '-hide">', '<input class="hide-postbox-tog" name="' + result.id + '-hide" type="checkbox" id="' + result.id + '-hide" value="' + result.id + '" checked="checked">', ' ' + result.title, '</label>'].join(''));
9306
9307 // Copy default WP events onto checkbox.
9308 copyEvents($prefs.find('input').first(), $label.find('input'));
9309
9310 // Append hide label
9311 $prefs.append($label);
9312 }
9313
9314 // Copy default WP events onto metabox.
9315 if ($('.postbox').length) {
9316 copyEvents($('.postbox .handlediv').first(), $postbox.children('.handlediv'));
9317 copyEvents($('.postbox .hndle').first(), $postbox.children('.hndle'));
9318 }
9319
9320 // Append metabox to the bottom of "side-sortables".
9321 if (result.position === 'side') {
9322 $('#' + result.position + '-sortables').append($postbox);
9323
9324 // Prepend metabox to the top of "normal-sortbables".
9325 } else {
9326 $('#' + result.position + '-sortables').prepend($postbox);
9327 }
9328
9329 // Position metabox amongst existing ACF metaboxes within the same location.
9330 var order = [];
9331 data.results.map(function (_result) {
9332 if (result.position === _result.position && $('#' + result.position + '-sortables #' + _result.id).length) {
9333 order.push(_result.id);
9334 }
9335 });
9336 sortMetabox(result.id, order);
9337
9338 // Check 'sorted' for user preference.
9339 if (data.sorted) {
9340 // Loop over each position (acf_after_title, side, normal).
9341 for (var position in data.sorted) {
9342 let order = data.sorted[position];
9343 if (typeof order !== 'string') {
9344 continue;
9345 }
9346
9347 // Explode string into array of ids.
9348 order = order.split(',');
9349
9350 // Position metabox relative to order.
9351 if (sortMetabox(result.id, order)) {
9352 break;
9353 }
9354 }
9355 }
9356
9357 // Initalize it (modifies HTML).
9358 postbox = acf.newPostbox(result);
9359
9360 // Trigger action.
9361 acf.doAction('append', $postbox);
9362 acf.doAction('append_postbox', postbox);
9363 }
9364
9365 // show postbox
9366 postbox.showEnable();
9367
9368 // append
9369 data.visible.push(result.id);
9370
9371 // Return result (may have changed).
9372 return result;
9373 });
9374
9375 // Hide these postboxes.
9376 acf.getPostboxes().map(function (postbox) {
9377 if (data.visible.indexOf(postbox.get('id')) === -1) {
9378 // Hide postbox.
9379 postbox.hideDisable();
9380
9381 // Append to data.
9382 data.hidden.push(postbox.get('id'));
9383 }
9384 });
9385
9386 // Update style.
9387 $('#acf-style').html(data.style);
9388
9389 // Do action.
9390 acf.doAction('refresh_post_screen', data);
9391 },
9392 renderUserScreen: function (json) {}
9393 });
9394
9395 /**
9396 * gutenScreen
9397 *
9398 * Adds compatibility with the Gutenberg edit screen.
9399 *
9400 * @date 11/12/18
9401 * @since ACF 5.8.0
9402 *
9403 * @param void
9404 * @return void
9405 */
9406 var gutenScreen = new acf.Model({
9407 // Keep a reference to the most recent post attributes.
9408 postEdits: {},
9409 // Wait until assets have been loaded.
9410 wait: 'prepare',
9411 initialize: function () {
9412 // Bail early if not Gutenberg.
9413 if (!acf.isGutenbergPostEditor()) {
9414 return;
9415 }
9416
9417 // Listen for changes (use debounced version as this can fires often).
9418 wp.data.subscribe(acf.debounce(this.onChange).bind(this));
9419
9420 // Customize "acf.screen.get" functions.
9421 acf.screen.getPageTemplate = this.getPageTemplate;
9422 acf.screen.getPageParent = this.getPageParent;
9423 acf.screen.getPostType = this.getPostType;
9424 acf.screen.getPostFormat = this.getPostFormat;
9425 acf.screen.getPostCoreTerms = this.getPostCoreTerms;
9426
9427 // Disable unload
9428 acf.unload.disable();
9429
9430 // Refresh metaboxes since WP 5.3.
9431 this.addAction('refresh_post_screen', this.onRefreshPostScreen);
9432
9433 // Trigger "refresh" after WP has moved metaboxes into place.
9434 wp.domReady(acf.refresh);
9435 },
9436 onChange: function () {
9437 // Determine attributes that can trigger a refresh.
9438 var attributes = ['template', 'parent', 'format'];
9439
9440 // Append taxonomy attribute names to this list.
9441 (wp.data.select('core').getTaxonomies() || []).map(function (taxonomy) {
9442 attributes.push(taxonomy.rest_base);
9443 });
9444
9445 // Get relevant current post edits.
9446 var _postEdits = wp.data.select('core/editor').getPostEdits();
9447 var postEdits = {};
9448 attributes.map(function (k) {
9449 if (_postEdits[k] !== undefined) {
9450 postEdits[k] = _postEdits[k];
9451 }
9452 });
9453
9454 // Detect change.
9455 if (JSON.stringify(postEdits) !== JSON.stringify(this.postEdits)) {
9456 this.postEdits = postEdits;
9457
9458 // Check screen.
9459 acf.screen.check();
9460 }
9461 },
9462 getPageTemplate: function () {
9463 return wp.data.select('core/editor').getEditedPostAttribute('template');
9464 },
9465 getPageParent: function (e, $el) {
9466 return wp.data.select('core/editor').getEditedPostAttribute('parent');
9467 },
9468 getPostType: function () {
9469 return wp.data.select('core/editor').getEditedPostAttribute('type');
9470 },
9471 getPostFormat: function (e, $el) {
9472 return wp.data.select('core/editor').getEditedPostAttribute('format');
9473 },
9474 getPostCoreTerms: function () {
9475 // vars
9476 var terms = {};
9477
9478 // Loop over taxonomies.
9479 var taxonomies = wp.data.select('core').getTaxonomies() || [];
9480 taxonomies.map(function (taxonomy) {
9481 // Append selected taxonomies to terms object.
9482 var postTerms = wp.data.select('core/editor').getEditedPostAttribute(taxonomy.rest_base);
9483 if (postTerms) {
9484 terms[taxonomy.slug] = postTerms;
9485 }
9486 });
9487
9488 // return
9489 return terms;
9490 },
9491 /**
9492 * onRefreshPostScreen
9493 *
9494 * Fires after the Post edit screen metaboxs are refreshed to update the Block Editor API state.
9495 *
9496 * @date 11/11/19
9497 * @since ACF 5.8.7
9498 *
9499 * @param object data The "check_screen" JSON response data.
9500 * @return void
9501 */
9502 onRefreshPostScreen: function (data) {
9503 // Extract vars.
9504 var select = wp.data.select('core/edit-post');
9505 var dispatch = wp.data.dispatch('core/edit-post');
9506
9507 // Load current metabox locations and data.
9508 var locations = {};
9509 select.getActiveMetaBoxLocations().map(function (location) {
9510 locations[location] = select.getMetaBoxesPerLocation(location);
9511 });
9512
9513 // Generate flat array of existing ids.
9514 var ids = [];
9515 for (var k in locations) {
9516 locations[k].map(function (m) {
9517 ids.push(m.id);
9518 });
9519 }
9520
9521 // Append new ACF metaboxes (ignore those which already exist).
9522 data.results.filter(function (r) {
9523 return ids.indexOf(r.id) === -1;
9524 }).map(function (result, i) {
9525 // Ensure location exists.
9526 var location = result.position;
9527 locations[location] = locations[location] || [];
9528
9529 // Append.
9530 locations[location].push({
9531 id: result.id,
9532 title: result.title
9533 });
9534 });
9535
9536 // Remove hidden ACF metaboxes.
9537 for (var k in locations) {
9538 locations[k] = locations[k].filter(function (m) {
9539 return data.hidden.indexOf(m.id) === -1;
9540 });
9541 }
9542
9543 // Update state.
9544 dispatch.setAvailableMetaBoxesPerLocation(locations);
9545 }
9546 });
9547 })(jQuery);
9548
9549 /***/ }),
9550
9551 /***/ "./assets/src/js/_acf-select2.js":
9552 /*!***************************************!*\
9553 !*** ./assets/src/js/_acf-select2.js ***!
9554 \***************************************/
9555 /***/ (() => {
9556
9557 (function ($, undefined) {
9558 /**
9559 * acf.newSelect2
9560 *
9561 * description
9562 *
9563 * @date 13/1/18
9564 * @since ACF 5.6.5
9565 *
9566 * @param type $var Description. Default.
9567 * @return type Description.
9568 */
9569
9570 acf.newSelect2 = function ($select, props) {
9571 // defaults
9572 props = acf.parseArgs(props, {
9573 allowNull: false,
9574 placeholder: '',
9575 multiple: false,
9576 field: false,
9577 ajax: false,
9578 tags: false,
9579 ajaxAction: '',
9580 ajaxData: function (data) {
9581 return data;
9582 },
9583 ajaxResults: function (json) {
9584 return json;
9585 },
9586 escapeMarkup: false,
9587 templateSelection: false,
9588 templateResult: false,
9589 dropdownCssClass: '',
9590 suppressFilters: false
9591 });
9592
9593 // initialize
9594 if (getVersion() == 4) {
9595 var select2 = new Select2_4($select, props);
9596 } else {
9597 var select2 = new Select2_3($select, props);
9598 }
9599
9600 // actions
9601 acf.doAction('new_select2', select2);
9602
9603 // return
9604 return select2;
9605 };
9606
9607 /**
9608 * getVersion
9609 *
9610 * description
9611 *
9612 * @date 13/1/18
9613 * @since ACF 5.6.5
9614 *
9615 * @param type $var Description. Default.
9616 * @return type Description.
9617 */
9618
9619 function getVersion() {
9620 // v4
9621 if (acf.isset(window, 'jQuery', 'fn', 'select2', 'amd')) {
9622 return 4;
9623 }
9624
9625 // v3
9626 if (acf.isset(window, 'Select2')) {
9627 return 3;
9628 }
9629
9630 // return
9631 return false;
9632 }
9633
9634 /**
9635 * Select2
9636 *
9637 * description
9638 *
9639 * @date 13/1/18
9640 * @since ACF 5.6.5
9641 *
9642 * @param type $var Description. Default.
9643 * @return type Description.
9644 */
9645
9646 var Select2 = acf.Model.extend({
9647 setup: function ($select, props) {
9648 $.extend(this.data, props);
9649 this.$el = $select;
9650 },
9651 initialize: function () {},
9652 selectOption: function (value) {
9653 var $option = this.getOption(value);
9654 if (!$option.prop('selected')) {
9655 $option.prop('selected', true).trigger('change');
9656 }
9657 },
9658 unselectOption: function (value) {
9659 var $option = this.getOption(value);
9660 if ($option.prop('selected')) {
9661 $option.prop('selected', false).trigger('change');
9662 }
9663 },
9664 getOption: function (value) {
9665 return this.$('option[value="' + value + '"]');
9666 },
9667 addOption: function (option) {
9668 // defaults
9669 option = acf.parseArgs(option, {
9670 id: '',
9671 text: '',
9672 selected: false
9673 });
9674
9675 // vars
9676 var $option = this.getOption(option.id);
9677
9678 // append
9679 if (!$option.length) {
9680 $option = $('<option></option>');
9681 $option.html(option.text);
9682 $option.attr('value', option.id);
9683 $option.prop('selected', option.selected);
9684 this.$el.append($option);
9685 }
9686
9687 // chain
9688 return $option;
9689 },
9690 getValue: function () {
9691 // vars
9692 var val = [];
9693 var $options = this.$el.find('option:selected');
9694
9695 // bail early if no selected
9696 if (!$options.exists()) {
9697 return val;
9698 }
9699
9700 // sort by attribute
9701 $options = $options.sort(function (a, b) {
9702 return +a.getAttribute('data-i') - +b.getAttribute('data-i');
9703 });
9704
9705 // loop
9706 $options.each(function () {
9707 var $el = $(this);
9708 val.push({
9709 $el: $el,
9710 id: $el.attr('value'),
9711 text: $el.text()
9712 });
9713 });
9714
9715 // return
9716 return val;
9717 },
9718 mergeOptions: function () {},
9719 getChoices: function () {
9720 // callback
9721 var crawl = function ($parent) {
9722 // vars
9723 var choices = [];
9724
9725 // loop
9726 $parent.children().each(function () {
9727 // vars
9728 var $child = $(this);
9729
9730 // optgroup
9731 if ($child.is('optgroup')) {
9732 choices.push({
9733 text: $child.attr('label'),
9734 children: crawl($child)
9735 });
9736
9737 // option
9738 } else {
9739 choices.push({
9740 id: $child.attr('value'),
9741 text: $child.text()
9742 });
9743 }
9744 });
9745
9746 // return
9747 return choices;
9748 };
9749
9750 // crawl
9751 return crawl(this.$el);
9752 },
9753 getAjaxData: function (params) {
9754 // vars
9755 var ajaxData = {
9756 action: this.get('ajaxAction'),
9757 s: params.term || '',
9758 paged: params.page || 1
9759 };
9760
9761 // field helper
9762 var field = this.get('field');
9763 if (field) {
9764 ajaxData.field_key = field.get('key');
9765 if (field.get('nonce')) {
9766 ajaxData.nonce = field.get('nonce');
9767 }
9768 }
9769
9770 // callback
9771 var callback = this.get('ajaxData');
9772 if (callback) {
9773 ajaxData = callback.apply(this, [ajaxData, params]);
9774 }
9775
9776 // filter
9777 ajaxData = acf.applyFilters('select2_ajax_data', ajaxData, this.data, this.$el, field || false, this);
9778
9779 // return
9780 return acf.prepareForAjax(ajaxData);
9781 },
9782 getAjaxResults: function (json, params) {
9783 // defaults
9784 json = acf.parseArgs(json, {
9785 results: false,
9786 more: false
9787 });
9788
9789 // callback
9790 var callback = this.get('ajaxResults');
9791 if (callback) {
9792 json = callback.apply(this, [json, params]);
9793 }
9794
9795 // filter
9796 json = acf.applyFilters('select2_ajax_results', json, params, this);
9797
9798 // return
9799 return json;
9800 },
9801 processAjaxResults: function (json, params) {
9802 // vars
9803 var json = this.getAjaxResults(json, params);
9804
9805 // change more to pagination
9806 if (json.more) {
9807 json.pagination = {
9808 more: true
9809 };
9810 }
9811
9812 // merge together groups
9813 setTimeout($.proxy(this.mergeOptions, this), 1);
9814
9815 // return
9816 return json;
9817 },
9818 destroy: function () {
9819 // destroy via api
9820 if (this.$el.data('select2')) {
9821 this.$el.select2('destroy');
9822 }
9823
9824 // destroy via HTML (duplicating HTML does not contain data)
9825 this.$el.siblings('.select2-container').remove();
9826 }
9827 });
9828
9829 /**
9830 * Select2_4
9831 *
9832 * description
9833 *
9834 * @date 13/1/18
9835 * @since ACF 5.6.5
9836 *
9837 * @param type $var Description. Default.
9838 * @return type Description.
9839 */
9840
9841 var Select2_4 = Select2.extend({
9842 initialize: function () {
9843 // vars
9844 var $select = this.$el;
9845 var options = {
9846 width: '100%',
9847 allowClear: this.get('allowNull'),
9848 placeholder: this.get('placeholder'),
9849 multiple: this.get('multiple'),
9850 escapeMarkup: this.get('escapeMarkup'),
9851 templateSelection: this.get('templateSelection'),
9852 templateResult: this.get('templateResult'),
9853 dropdownCssClass: this.get('dropdownCssClass'),
9854 suppressFilters: this.get('suppressFilters'),
9855 data: []
9856 };
9857 if (this.get('tags')) {
9858 options.tags = true;
9859 options.tokenSeparators = [','];
9860 }
9861
9862 // Clear empty templateSelections, templateResults, or dropdownCssClass.
9863 if (!options.templateSelection) {
9864 delete options.templateSelection;
9865 }
9866 if (!options.templateResult) {
9867 delete options.templateResult;
9868 }
9869 if (!options.dropdownCssClass) {
9870 delete options.dropdownCssClass;
9871 }
9872
9873 // Only use the template if SelectWoo is not loaded to work around https://github.com/woocommerce/woocommerce/pull/30473
9874 if (!acf.isset(window, 'jQuery', 'fn', 'selectWoo')) {
9875 if (!options.templateSelection) {
9876 options.templateSelection = function (selection) {
9877 var $selection = $('<span class="acf-selection"></span>');
9878 $selection.html(options.escapeMarkup(selection.text));
9879 $selection.data('element', selection.element);
9880 return $selection;
9881 };
9882 }
9883 } else {
9884 delete options.templateSelection;
9885 delete options.templateResult;
9886 }
9887
9888 // Use a default, filterable escapeMarkup if not provided.
9889 if (!options.escapeMarkup) {
9890 options.escapeMarkup = function (markup) {
9891 if (typeof markup !== 'string') {
9892 return markup;
9893 }
9894 if (this.suppressFilters) {
9895 return acf.strEscape(markup);
9896 }
9897 return acf.applyFilters('select2_escape_markup', acf.strEscape(markup), markup, $select, this.data, field || false, this);
9898 };
9899 }
9900
9901 // multiple
9902 if (options.multiple) {
9903 // reorder options
9904 this.getValue().map(function (item) {
9905 item.$el.detach().appendTo($select);
9906 });
9907 }
9908
9909 // Temporarily remove conflicting attribute.
9910 var attrAjax = $select.attr('data-ajax');
9911 if (attrAjax !== undefined) {
9912 $select.removeData('ajax');
9913 $select.removeAttr('data-ajax');
9914 }
9915
9916 // ajax
9917 if (this.get('ajax')) {
9918 options.ajax = {
9919 url: acf.get('ajaxurl'),
9920 delay: 250,
9921 dataType: 'json',
9922 type: 'post',
9923 cache: false,
9924 data: $.proxy(this.getAjaxData, this),
9925 processResults: $.proxy(this.processAjaxResults, this)
9926 };
9927 }
9928
9929 // filter for 3rd party customization
9930 if (!options.suppressFilters) {
9931 var field = this.get('field');
9932 options = acf.applyFilters('select2_args', options, $select, this.data, field || false, this);
9933 }
9934 // add select2
9935 $select.select2(options);
9936
9937 // get container (Select2 v4 does not return this from constructor)
9938 var $container = $select.next('.select2-container');
9939
9940 // multiple
9941 if (options.multiple) {
9942 // vars
9943 var $ul = $container.find('ul');
9944
9945 // sortable
9946 $ul.sortable({
9947 stop: function (e) {
9948 // loop
9949 $ul.find('.select2-selection__choice').each(function () {
9950 // Attempt to use .data if it exists (select2 version < 4.0.6) or use our template data instead.
9951 if ($(this).data('data')) {
9952 var $option = $($(this).data('data').element);
9953 } else {
9954 var $option = $($(this).find('span.acf-selection').data('element'));
9955 }
9956
9957 // detach and re-append to end
9958 $option.detach().appendTo($select);
9959 });
9960
9961 // trigger change on input (JS error if trigger on select)
9962 $select.trigger('change');
9963 }
9964 });
9965
9966 // on select, move to end
9967 $select.on('select2:select', this.proxy(function (e) {
9968 this.getOption(e.params.data.id).detach().appendTo(this.$el);
9969 }));
9970 }
9971
9972 // add handler to auto-focus searchbox (for jQuery 3.6)
9973 $select.on('select2:open', () => {
9974 $('.select2-container--open .select2-search__field').get(-1).focus();
9975 });
9976
9977 // add class
9978 $container.addClass('-acf');
9979
9980 // Add back temporarily removed attr.
9981 if (attrAjax !== undefined) {
9982 $select.attr('data-ajax', attrAjax);
9983 }
9984
9985 // action for 3rd party customization
9986 if (!options.suppressFilters) {
9987 acf.doAction('select2_init', $select, options, this.data, field || false, this);
9988 }
9989 },
9990 mergeOptions: function () {
9991 // vars
9992 var $prevOptions = false;
9993 var $prevGroup = false;
9994
9995 // loop
9996 $('.select2-results__option[role="group"]').each(function () {
9997 // vars
9998 var $options = $(this).children('ul');
9999 var $group = $(this).children('strong');
10000
10001 // compare to previous
10002 if ($prevGroup && $prevGroup.text() === $group.text()) {
10003 $prevOptions.append($options.children());
10004 $(this).remove();
10005 return;
10006 }
10007
10008 // update vars
10009 $prevOptions = $options;
10010 $prevGroup = $group;
10011 });
10012 }
10013 });
10014
10015 /**
10016 * Select2_3
10017 *
10018 * description
10019 *
10020 * @date 13/1/18
10021 * @since ACF 5.6.5
10022 *
10023 * @param type $var Description. Default.
10024 * @return type Description.
10025 */
10026
10027 var Select2_3 = Select2.extend({
10028 initialize: function () {
10029 // vars
10030 var $select = this.$el;
10031 var value = this.getValue();
10032 var multiple = this.get('multiple');
10033 var options = {
10034 width: '100%',
10035 allowClear: this.get('allowNull'),
10036 placeholder: this.get('placeholder'),
10037 separator: '||',
10038 multiple: this.get('multiple'),
10039 data: this.getChoices(),
10040 escapeMarkup: function (string) {
10041 return acf.escHtml(string);
10042 },
10043 dropdownCss: {
10044 'z-index': '999999999'
10045 },
10046 initSelection: function (element, callback) {
10047 if (multiple) {
10048 callback(value);
10049 } else {
10050 callback(value.shift());
10051 }
10052 }
10053 };
10054 // get hidden input
10055 var $input = $select.siblings('input');
10056 if (!$input.length) {
10057 $input = $('<input type="hidden" />');
10058 $select.before($input);
10059 }
10060
10061 // set input value
10062 inputValue = value.map(function (item) {
10063 return item.id;
10064 }).join('||');
10065 $input.val(inputValue);
10066
10067 // multiple
10068 if (options.multiple) {
10069 // reorder options
10070 value.map(function (item) {
10071 item.$el.detach().appendTo($select);
10072 });
10073 }
10074
10075 // remove blank option as we have a clear all button
10076 if (options.allowClear) {
10077 options.data = options.data.filter(function (item) {
10078 return item.id !== '';
10079 });
10080 }
10081
10082 // remove conflicting atts
10083 $select.removeData('ajax');
10084 $select.removeAttr('data-ajax');
10085
10086 // ajax
10087 if (this.get('ajax')) {
10088 options.ajax = {
10089 url: acf.get('ajaxurl'),
10090 quietMillis: 250,
10091 dataType: 'json',
10092 type: 'post',
10093 cache: false,
10094 data: $.proxy(this.getAjaxData, this),
10095 results: $.proxy(this.processAjaxResults, this)
10096 };
10097 }
10098
10099 // filter for 3rd party customization
10100 var field = this.get('field');
10101 options = acf.applyFilters('select2_args', options, $select, this.data, field || false, this);
10102
10103 // add select2
10104 $input.select2(options);
10105
10106 // get container
10107 var $container = $input.select2('container');
10108
10109 // helper to find this select's option
10110 var getOption = $.proxy(this.getOption, this);
10111
10112 // multiple
10113 if (options.multiple) {
10114 // vars
10115 var $ul = $container.find('ul');
10116
10117 // sortable
10118 $ul.sortable({
10119 stop: function () {
10120 // loop
10121 $ul.find('.select2-search-choice').each(function () {
10122 // vars
10123 var data = $(this).data('select2Data');
10124 var $option = getOption(data.id);
10125
10126 // detach and re-append to end
10127 $option.detach().appendTo($select);
10128 });
10129
10130 // trigger change on input (JS error if trigger on select)
10131 $select.trigger('change');
10132 }
10133 });
10134 }
10135
10136 // on select, create option and move to end
10137 $input.on('select2-selecting', function (e) {
10138 // vars
10139 var item = e.choice;
10140 var $option = getOption(item.id);
10141
10142 // create if doesn't exist
10143 if (!$option.length) {
10144 $option = $('<option value="' + item.id + '">' + item.text + '</option>');
10145 }
10146
10147 // detach and re-append to end
10148 $option.detach().appendTo($select);
10149 });
10150
10151 // add class
10152 $container.addClass('-acf');
10153
10154 // action for 3rd party customization
10155 acf.doAction('select2_init', $select, options, this.data, field || false, this);
10156
10157 // change
10158 $input.on('change', function () {
10159 var val = $input.val();
10160 if (val.indexOf('||')) {
10161 val = val.split('||');
10162 }
10163 $select.val(val).trigger('change');
10164 });
10165
10166 // hide select
10167 $select.hide();
10168 },
10169 mergeOptions: function () {
10170 // vars
10171 var $prevOptions = false;
10172 var $prevGroup = false;
10173
10174 // loop
10175 $('#select2-drop .select2-result-with-children').each(function () {
10176 // vars
10177 var $options = $(this).children('ul');
10178 var $group = $(this).children('.select2-result-label');
10179
10180 // compare to previous
10181 if ($prevGroup && $prevGroup.text() === $group.text()) {
10182 $prevGroup.append($options.children());
10183 $(this).remove();
10184 return;
10185 }
10186
10187 // update vars
10188 $prevOptions = $options;
10189 $prevGroup = $group;
10190 });
10191 },
10192 getAjaxData: function (term, page) {
10193 // create Select2 v4 params
10194 var params = {
10195 term: term,
10196 page: page
10197 };
10198
10199 // filter
10200 var field = this.get('field');
10201 params = acf.applyFilters('select2_ajax_data', params, this.data, this.$el, field || false, this);
10202 // return
10203 return Select2.prototype.getAjaxData.apply(this, [params]);
10204 }
10205 });
10206
10207 // manager
10208 var select2Manager = new acf.Model({
10209 priority: 5,
10210 wait: 'prepare',
10211 actions: {
10212 duplicate: 'onDuplicate'
10213 },
10214 initialize: function () {
10215 // vars
10216 var locale = acf.get('locale');
10217 var rtl = acf.get('rtl');
10218 var l10n = acf.get('select2L10n');
10219 var version = getVersion();
10220
10221 // bail early if no l10n
10222 if (!l10n) {
10223 return false;
10224 }
10225
10226 // bail early if 'en'
10227 if (locale.indexOf('en') === 0) {
10228 return false;
10229 }
10230
10231 // initialize
10232 if (version == 4) {
10233 this.addTranslations4();
10234 } else if (version == 3) {
10235 this.addTranslations3();
10236 }
10237 },
10238 addTranslations4: function () {
10239 // vars
10240 var l10n = acf.get('select2L10n');
10241 var locale = acf.get('locale');
10242
10243 // modify local to match html[lang] attribute (used by Select2)
10244 locale = locale.replace('_', '-');
10245
10246 // select2L10n
10247 var select2L10n = {
10248 errorLoading: function () {
10249 return l10n.load_fail;
10250 },
10251 inputTooLong: function (args) {
10252 var overChars = args.input.length - args.maximum;
10253 if (overChars > 1) {
10254 return l10n.input_too_long_n.replace('%d', overChars);
10255 }
10256 return l10n.input_too_long_1;
10257 },
10258 inputTooShort: function (args) {
10259 var remainingChars = args.minimum - args.input.length;
10260 if (remainingChars > 1) {
10261 return l10n.input_too_short_n.replace('%d', remainingChars);
10262 }
10263 return l10n.input_too_short_1;
10264 },
10265 loadingMore: function () {
10266 return l10n.load_more;
10267 },
10268 maximumSelected: function (args) {
10269 var maximum = args.maximum;
10270 if (maximum > 1) {
10271 return l10n.selection_too_long_n.replace('%d', maximum);
10272 }
10273 return l10n.selection_too_long_1;
10274 },
10275 noResults: function () {
10276 return l10n.matches_0;
10277 },
10278 searching: function () {
10279 return l10n.searching;
10280 }
10281 };
10282
10283 // append
10284 jQuery.fn.select2.amd.define('select2/i18n/' + locale, [], function () {
10285 return select2L10n;
10286 });
10287 },
10288 addTranslations3: function () {
10289 // vars
10290 var l10n = acf.get('select2L10n');
10291 var locale = acf.get('locale');
10292
10293 // modify local to match html[lang] attribute (used by Select2)
10294 locale = locale.replace('_', '-');
10295
10296 // select2L10n
10297 var select2L10n = {
10298 formatMatches: function (matches) {
10299 if (matches > 1) {
10300 return l10n.matches_n.replace('%d', matches);
10301 }
10302 return l10n.matches_1;
10303 },
10304 formatNoMatches: function () {
10305 return l10n.matches_0;
10306 },
10307 formatAjaxError: function () {
10308 return l10n.load_fail;
10309 },
10310 formatInputTooShort: function (input, min) {
10311 var remainingChars = min - input.length;
10312 if (remainingChars > 1) {
10313 return l10n.input_too_short_n.replace('%d', remainingChars);
10314 }
10315 return l10n.input_too_short_1;
10316 },
10317 formatInputTooLong: function (input, max) {
10318 var overChars = input.length - max;
10319 if (overChars > 1) {
10320 return l10n.input_too_long_n.replace('%d', overChars);
10321 }
10322 return l10n.input_too_long_1;
10323 },
10324 formatSelectionTooBig: function (maximum) {
10325 if (maximum > 1) {
10326 return l10n.selection_too_long_n.replace('%d', maximum);
10327 }
10328 return l10n.selection_too_long_1;
10329 },
10330 formatLoadMore: function () {
10331 return l10n.load_more;
10332 },
10333 formatSearching: function () {
10334 return l10n.searching;
10335 }
10336 };
10337
10338 // ensure locales exists
10339 $.fn.select2.locales = $.fn.select2.locales || {};
10340
10341 // append
10342 $.fn.select2.locales[locale] = select2L10n;
10343 $.extend($.fn.select2.defaults, select2L10n);
10344 },
10345 onDuplicate: function ($el, $el2) {
10346 $el2.find('.select2-container').remove();
10347 }
10348 });
10349 })(jQuery);
10350
10351 /***/ }),
10352
10353 /***/ "./assets/src/js/_acf-tinymce.js":
10354 /*!***************************************!*\
10355 !*** ./assets/src/js/_acf-tinymce.js ***!
10356 \***************************************/
10357 /***/ (() => {
10358
10359 (function ($, undefined) {
10360 acf.tinymce = {
10361 /*
10362 * defaults
10363 *
10364 * This function will return default mce and qt settings
10365 *
10366 * @type function
10367 * @date 18/8/17
10368 * @since ACF 5.6.0
10369 *
10370 * @param $post_id (int)
10371 * @return $post_id (int)
10372 */
10373
10374 defaults: function () {
10375 // bail early if no tinyMCEPreInit
10376 if (typeof tinyMCEPreInit === 'undefined') return false;
10377
10378 // vars
10379 var defaults = {
10380 tinymce: tinyMCEPreInit.mceInit.acf_content,
10381 quicktags: tinyMCEPreInit.qtInit.acf_content
10382 };
10383
10384 // return
10385 return defaults;
10386 },
10387 /*
10388 * initialize
10389 *
10390 * This function will initialize the tinymce and quicktags instances
10391 *
10392 * @type function
10393 * @date 18/8/17
10394 * @since ACF 5.6.0
10395 *
10396 * @param $post_id (int)
10397 * @return $post_id (int)
10398 */
10399
10400 initialize: function (id, args) {
10401 // defaults
10402 args = acf.parseArgs(args, {
10403 tinymce: true,
10404 quicktags: true,
10405 toolbar: 'full',
10406 mode: 'visual',
10407 // visual,text
10408 field: false
10409 });
10410
10411 // tinymce
10412 if (args.tinymce) {
10413 this.initializeTinymce(id, args);
10414 }
10415
10416 // quicktags
10417 if (args.quicktags) {
10418 this.initializeQuicktags(id, args);
10419 }
10420 },
10421 /*
10422 * initializeTinymce
10423 *
10424 * This function will initialize the tinymce instance
10425 *
10426 * @type function
10427 * @date 18/8/17
10428 * @since ACF 5.6.0
10429 *
10430 * @param $post_id (int)
10431 * @return $post_id (int)
10432 */
10433
10434 initializeTinymce: function (id, args) {
10435 // vars
10436 var $textarea = $('#' + id);
10437 var defaults = this.defaults();
10438 var toolbars = acf.get('toolbars');
10439 var field = args.field || false;
10440 var $field = field.$el || false;
10441
10442 // bail early
10443 if (typeof tinymce === 'undefined') return false;
10444 if (!defaults) return false;
10445
10446 // check if exists
10447 if (tinymce.get(id)) {
10448 return this.enable(id);
10449 }
10450
10451 // settings
10452 var init = $.extend({}, defaults.tinymce, args.tinymce);
10453 init.id = id;
10454 init.selector = '#' + id;
10455
10456 // toolbar
10457 var toolbar = args.toolbar;
10458 if (toolbar && toolbars && toolbars[toolbar]) {
10459 for (var i = 1; i <= 4; i++) {
10460 init['toolbar' + i] = toolbars[toolbar][i] || '';
10461 }
10462 }
10463
10464 // event
10465 init.setup = function (ed) {
10466 ed.on('change', function (e) {
10467 ed.save(); // save to textarea
10468 if (!$textarea.closest('.attachment-info').length) {
10469 $textarea.trigger('change');
10470 }
10471 });
10472 ed.on('blur', function (e) {
10473 if ($textarea.closest('.attachment-info').length) {
10474 ed.save();
10475 $textarea.trigger('change');
10476 }
10477 });
10478
10479 // Fix bug where Gutenberg does not hear "mouseup" event and tries to select multiple blocks.
10480 ed.on('mouseup', function (e) {
10481 const event = new MouseEvent('mouseup');
10482 window.dispatchEvent(event);
10483 });
10484
10485 // Temporarily comment out. May not be necessary due to wysiwyg field actions.
10486 //ed.on('unload', function(e) {
10487 // acf.tinymce.remove( id );
10488 //});
10489 };
10490
10491 // disable wp_autoresize_on (no solution yet for fixed toolbar)
10492 init.wp_autoresize_on = false;
10493
10494 // Enable wpautop allowing value to save without <p> tags.
10495 // Only if the "TinyMCE Advanced" plugin hasn't already set this functionality.
10496 if (!init.tadv_noautop) {
10497 init.wpautop = true;
10498 }
10499
10500 // hook for 3rd party customization
10501 init = acf.applyFilters('wysiwyg_tinymce_settings', init, id, field);
10502
10503 // z-index fix (caused too many conflicts)
10504 //if( acf.isset(tinymce,'ui','FloatPanel') ) {
10505 // tinymce.ui.FloatPanel.zIndex = 900000;
10506 //}
10507
10508 // store settings
10509 tinyMCEPreInit.mceInit[id] = init;
10510
10511 // visual tab is active
10512 if (args.mode == 'visual') {
10513 // init
10514 var result = tinymce.init(init);
10515
10516 // get editor
10517 var ed = tinymce.get(id);
10518
10519 // validate
10520 if (!ed) {
10521 return false;
10522 }
10523
10524 // add reference
10525 ed.acf = args.field;
10526
10527 // action
10528 acf.doAction('wysiwyg_tinymce_init', ed, ed.id, init, field);
10529 }
10530 },
10531 /*
10532 * initializeQuicktags
10533 *
10534 * This function will initialize the quicktags instance
10535 *
10536 * @type function
10537 * @date 18/8/17
10538 * @since ACF 5.6.0
10539 *
10540 * @param $post_id (int)
10541 * @return $post_id (int)
10542 */
10543
10544 initializeQuicktags: function (id, args) {
10545 // vars
10546 var defaults = this.defaults();
10547
10548 // bail early
10549 if (typeof quicktags === 'undefined') return false;
10550 if (!defaults) return false;
10551
10552 // settings
10553 var init = $.extend({}, defaults.quicktags, args.quicktags);
10554 init.id = id;
10555
10556 // filter
10557 var field = args.field || false;
10558 var $field = field.$el || false;
10559 init = acf.applyFilters('wysiwyg_quicktags_settings', init, init.id, field);
10560
10561 // store settings
10562 tinyMCEPreInit.qtInit[id] = init;
10563
10564 // init
10565 var ed = quicktags(init);
10566
10567 // validate
10568 if (!ed) {
10569 return false;
10570 }
10571
10572 // generate HTML
10573 this.buildQuicktags(ed);
10574
10575 // action for 3rd party customization
10576 acf.doAction('wysiwyg_quicktags_init', ed, ed.id, init, field);
10577 },
10578 /*
10579 * buildQuicktags
10580 *
10581 * This function will build the quicktags HTML
10582 *
10583 * @type function
10584 * @date 18/8/17
10585 * @since ACF 5.6.0
10586 *
10587 * @param $post_id (int)
10588 * @return $post_id (int)
10589 */
10590
10591 buildQuicktags: function (ed) {
10592 var canvas,
10593 name,
10594 settings,
10595 theButtons,
10596 html,
10597 ed,
10598 id,
10599 i,
10600 use,
10601 instanceId,
10602 defaults = ',strong,em,link,block,del,ins,img,ul,ol,li,code,more,close,';
10603 canvas = ed.canvas;
10604 name = ed.name;
10605 settings = ed.settings;
10606 html = '';
10607 theButtons = {};
10608 use = '';
10609 instanceId = ed.id;
10610
10611 // set buttons
10612 if (settings.buttons) {
10613 use = ',' + settings.buttons + ',';
10614 }
10615 for (i in edButtons) {
10616 if (!edButtons[i]) {
10617 continue;
10618 }
10619 id = edButtons[i].id;
10620 if (use && defaults.indexOf(',' + id + ',') !== -1 && use.indexOf(',' + id + ',') === -1) {
10621 continue;
10622 }
10623 if (!edButtons[i].instance || edButtons[i].instance === instanceId) {
10624 theButtons[id] = edButtons[i];
10625 if (edButtons[i].html) {
10626 html += edButtons[i].html(name + '_');
10627 }
10628 }
10629 }
10630 if (use && use.indexOf(',dfw,') !== -1) {
10631 theButtons.dfw = new QTags.DFWButton();
10632 html += theButtons.dfw.html(name + '_');
10633 }
10634 if ('rtl' === document.getElementsByTagName('html')[0].dir) {
10635 theButtons.textdirection = new QTags.TextDirectionButton();
10636 html += theButtons.textdirection.html(name + '_');
10637 }
10638 ed.toolbar.innerHTML = html;
10639 ed.theButtons = theButtons;
10640 if (typeof jQuery !== 'undefined') {
10641 jQuery(document).triggerHandler('quicktags-init', [ed]);
10642 }
10643 },
10644 disable: function (id) {
10645 this.destroyTinymce(id);
10646 },
10647 remove: function (id) {
10648 this.destroyTinymce(id);
10649 },
10650 destroy: function (id) {
10651 this.destroyTinymce(id);
10652 },
10653 destroyTinymce: function (id) {
10654 // bail early
10655 if (typeof tinymce === 'undefined') return false;
10656
10657 // get editor
10658 var ed = tinymce.get(id);
10659
10660 // bail early if no editor
10661 if (!ed) return false;
10662
10663 // save
10664 ed.save();
10665
10666 // destroy editor
10667 ed.destroy();
10668
10669 // return
10670 return true;
10671 },
10672 enable: function (id) {
10673 this.enableTinymce(id);
10674 },
10675 enableTinymce: function (id) {
10676 // bail early
10677 if (typeof switchEditors === 'undefined') return false;
10678
10679 // bail early if not initialized
10680 if (typeof tinyMCEPreInit.mceInit[id] === 'undefined') return false;
10681
10682 // Ensure textarea element is visible
10683 // - Fixes bug in block editor when switching between "Block" and "Document" tabs.
10684 if (!tinymce.get(id)) {
10685 $('#' + id).show();
10686 }
10687
10688 // toggle
10689 switchEditors.go(id, 'tmce');
10690
10691 // return
10692 return true;
10693 }
10694 };
10695 var editorManager = new acf.Model({
10696 // hook in before fieldsEventManager, conditions, etc
10697 priority: 5,
10698 actions: {
10699 prepare: 'onPrepare',
10700 ready: 'onReady'
10701 },
10702 onPrepare: function () {
10703 // find hidden editor which may exist within a field
10704 var $div = $('#acf-hidden-wp-editor');
10705
10706 // move to footer
10707 if ($div.exists()) {
10708 $div.appendTo('body');
10709 }
10710 },
10711 onReady: function () {
10712 // Restore wp.editor functions used by tinymce removed in WP5.
10713 if (acf.isset(window, 'wp', 'oldEditor')) {
10714 wp.editor.autop = wp.oldEditor.autop;
10715 wp.editor.removep = wp.oldEditor.removep;
10716 }
10717
10718 // bail early if no tinymce
10719 if (!acf.isset(window, 'tinymce', 'on')) return;
10720
10721 // restore default activeEditor
10722 tinymce.on('AddEditor', function (data) {
10723 // vars
10724 var editor = data.editor;
10725
10726 // bail early if not 'acf'
10727 if (editor.id.substr(0, 3) !== 'acf') return;
10728
10729 // override if 'content' exists
10730 editor = tinymce.editors.content || editor;
10731
10732 // update vars
10733 tinymce.activeEditor = editor;
10734 wpActiveEditor = editor.id;
10735 });
10736 }
10737 });
10738 })(jQuery);
10739
10740 /***/ }),
10741
10742 /***/ "./assets/src/js/_acf-unload.js":
10743 /*!**************************************!*\
10744 !*** ./assets/src/js/_acf-unload.js ***!
10745 \**************************************/
10746 /***/ (() => {
10747
10748 (function ($, undefined) {
10749 acf.unload = new acf.Model({
10750 wait: 'load',
10751 active: true,
10752 changed: false,
10753 actions: {
10754 validation_failure: 'startListening',
10755 validation_success: 'stopListening'
10756 },
10757 events: {
10758 'change form .acf-field': 'startListening',
10759 'submit form': 'stopListening'
10760 },
10761 enable: function () {
10762 this.active = true;
10763 },
10764 disable: function () {
10765 this.active = false;
10766 },
10767 reset: function () {
10768 this.stopListening();
10769 },
10770 startListening: function () {
10771 // bail early if already changed, not active
10772 if (this.changed || !this.active) {
10773 return;
10774 }
10775
10776 // update
10777 this.changed = true;
10778
10779 // add event
10780 $(window).on('beforeunload', this.onUnload);
10781 },
10782 stopListening: function () {
10783 // update
10784 this.changed = false;
10785
10786 // remove event
10787 $(window).off('beforeunload', this.onUnload);
10788 },
10789 onUnload: function () {
10790 return acf.__('The changes you made will be lost if you navigate away from this page');
10791 }
10792 });
10793 })(jQuery);
10794
10795 /***/ }),
10796
10797 /***/ "./assets/src/js/_acf-validation.js":
10798 /*!******************************************!*\
10799 !*** ./assets/src/js/_acf-validation.js ***!
10800 \******************************************/
10801 /***/ (() => {
10802
10803 (function ($, undefined) {
10804 /**
10805 * Validator
10806 *
10807 * The model for validating forms
10808 *
10809 * @date 4/9/18
10810 * @since ACF 5.7.5
10811 *
10812 * @param void
10813 * @return void
10814 */
10815 var Validator = acf.Model.extend({
10816 /** @var string The model identifier. */
10817 id: 'Validator',
10818 /** @var object The model data. */
10819 data: {
10820 /** @var array The form errors. */
10821 errors: [],
10822 /** @var object The form notice. */
10823 notice: null,
10824 /** @var string The form status. loading, invalid, valid */
10825 status: ''
10826 },
10827 /** @var object The model events. */
10828 events: {
10829 'changed:status': 'onChangeStatus'
10830 },
10831 /**
10832 * addErrors
10833 *
10834 * Adds errors to the form.
10835 *
10836 * @date 4/9/18
10837 * @since ACF 5.7.5
10838 *
10839 * @param array errors An array of errors.
10840 * @return void
10841 */
10842 addErrors: function (errors) {
10843 errors.map(this.addError, this);
10844 },
10845 /**
10846 * addError
10847 *
10848 * Adds and error to the form.
10849 *
10850 * @date 4/9/18
10851 * @since ACF 5.7.5
10852 *
10853 * @param object error An error object containing input and message.
10854 * @return void
10855 */
10856 addError: function (error) {
10857 this.data.errors.push(error);
10858 },
10859 /**
10860 * hasErrors
10861 *
10862 * Returns true if the form has errors.
10863 *
10864 * @date 4/9/18
10865 * @since ACF 5.7.5
10866 *
10867 * @param void
10868 * @return bool
10869 */
10870 hasErrors: function () {
10871 return this.data.errors.length;
10872 },
10873 /**
10874 * clearErrors
10875 *
10876 * Removes any errors.
10877 *
10878 * @date 4/9/18
10879 * @since ACF 5.7.5
10880 *
10881 * @param void
10882 * @return void
10883 */
10884 clearErrors: function () {
10885 return this.data.errors = [];
10886 },
10887 /**
10888 * getErrors
10889 *
10890 * Returns the forms errors.
10891 *
10892 * @date 4/9/18
10893 * @since ACF 5.7.5
10894 *
10895 * @param void
10896 * @return array
10897 */
10898 getErrors: function () {
10899 return this.data.errors;
10900 },
10901 /**
10902 * getFieldErrors
10903 *
10904 * Returns the forms field errors.
10905 *
10906 * @date 4/9/18
10907 * @since ACF 5.7.5
10908 *
10909 * @param void
10910 * @return array
10911 */
10912 getFieldErrors: function () {
10913 // vars
10914 var errors = [];
10915 var inputs = [];
10916
10917 // loop
10918 this.getErrors().map(function (error) {
10919 // bail early if global
10920 if (!error.input) return;
10921
10922 // update if exists
10923 var i = inputs.indexOf(error.input);
10924 if (i > -1) {
10925 errors[i] = error;
10926
10927 // update
10928 } else {
10929 errors.push(error);
10930 inputs.push(error.input);
10931 }
10932 });
10933
10934 // return
10935 return errors;
10936 },
10937 /**
10938 * getGlobalErrors
10939 *
10940 * Returns the forms global errors (errors without a specific input).
10941 *
10942 * @date 4/9/18
10943 * @since ACF 5.7.5
10944 *
10945 * @param void
10946 * @return array
10947 */
10948 getGlobalErrors: function () {
10949 // return array of errors that contain no input
10950 return this.getErrors().filter(function (error) {
10951 return !error.input;
10952 });
10953 },
10954 /**
10955 * showErrors
10956 *
10957 * Displays all errors for this form.
10958 *
10959 * @since ACF 5.7.5
10960 *
10961 * @param {string} [location=before] - The location to add the error, before or after the input. Default before. Since ACF 6.3.
10962 * @return void
10963 */
10964 showErrors: function (location = 'before') {
10965 // bail early if no errors
10966 if (!this.hasErrors()) {
10967 return;
10968 }
10969
10970 // vars
10971 var fieldErrors = this.getFieldErrors();
10972 var globalErrors = this.getGlobalErrors();
10973
10974 // vars
10975 var errorCount = 0;
10976 var $scrollTo = false;
10977
10978 // loop
10979 fieldErrors.map(function (error) {
10980 // get input
10981 var $input = this.$('[name="' + error.input + '"]').first();
10982
10983 // if $_POST value was an array, this $input may not exist
10984 if (!$input.length) {
10985 $input = this.$('[name^="' + error.input + '"]').first();
10986 }
10987
10988 // bail early if input doesn't exist
10989 if (!$input.length) {
10990 return;
10991 }
10992
10993 // increase
10994 errorCount++;
10995
10996 // get field
10997 var field = acf.getClosestField($input);
10998
10999 // make sure the postbox containing this field is not hidden by screen options
11000 ensureFieldPostBoxIsVisible(field.$el);
11001
11002 // show error
11003 field.showError(error.message, location);
11004
11005 // set $scrollTo
11006 if (!$scrollTo) {
11007 $scrollTo = field.$el;
11008 }
11009 }, this);
11010
11011 // errorMessage
11012 var errorMessage = acf.__('Validation failed');
11013 globalErrors.map(function (error) {
11014 errorMessage += '. ' + error.message;
11015 });
11016 if (errorCount == 1) {
11017 errorMessage += '. ' + acf.__('1 field requires attention');
11018 } else if (errorCount > 1) {
11019 errorMessage += '. ' + acf.__('%d fields require attention').replace('%d', errorCount);
11020 }
11021
11022 // notice
11023 if (this.has('notice')) {
11024 this.get('notice').update({
11025 type: 'error',
11026 text: errorMessage
11027 });
11028 } else {
11029 var notice = acf.newNotice({
11030 type: 'error',
11031 text: errorMessage,
11032 target: this.$el
11033 });
11034 this.set('notice', notice);
11035 }
11036
11037 // If in a modal, don't try to scroll.
11038 if (this.$el.parents('.acf-popup-box').length) {
11039 return;
11040 }
11041
11042 // if no $scrollTo, set to message
11043 if (!$scrollTo) {
11044 $scrollTo = this.get('notice').$el;
11045 }
11046
11047 // timeout
11048 setTimeout(function () {
11049 $('html, body').animate({
11050 scrollTop: $scrollTo.offset().top - $(window).height() / 2
11051 }, 500);
11052 }, 10);
11053 },
11054 /**
11055 * onChangeStatus
11056 *
11057 * Update the form class when changing the 'status' data
11058 *
11059 * @date 4/9/18
11060 * @since ACF 5.7.5
11061 *
11062 * @param object e The event object.
11063 * @param jQuery $el The form element.
11064 * @param string value The new status.
11065 * @param string prevValue The old status.
11066 * @return void
11067 */
11068 onChangeStatus: function (e, $el, value, prevValue) {
11069 this.$el.removeClass('is-' + prevValue).addClass('is-' + value);
11070 },
11071 /**
11072 * validate
11073 *
11074 * Validates the form via AJAX.
11075 *
11076 * @date 4/9/18
11077 * @since ACF 5.7.5
11078 *
11079 * @param object args A list of settings to customize the validation process.
11080 * @return bool True if the form is valid.
11081 */
11082 validate: function (args) {
11083 // default args
11084 args = acf.parseArgs(args, {
11085 // trigger event
11086 event: false,
11087 // reset the form after submit
11088 reset: false,
11089 // loading callback
11090 loading: function () {},
11091 // complete callback
11092 complete: function () {},
11093 // failure callback
11094 failure: function () {},
11095 // success callback
11096 success: function ($form) {
11097 $form.submit();
11098 }
11099 });
11100
11101 // return true if is valid - allows form submit
11102 if (this.get('status') == 'valid') {
11103 return true;
11104 }
11105
11106 // return false if is currently validating - prevents form submit
11107 if (this.get('status') == 'validating') {
11108 return false;
11109 }
11110
11111 // return true if no ACF fields exist (no need to validate)
11112 if (!this.$('.acf-field').length) {
11113 return true;
11114 }
11115
11116 // if event is provided, create a new success callback.
11117 if (args.event) {
11118 var event = $.Event(null, args.event);
11119 args.success = function () {
11120 acf.enableSubmit($(event.target)).trigger(event);
11121 };
11122 }
11123
11124 // action for 3rd party
11125 acf.doAction('validation_begin', this.$el);
11126
11127 // lock form
11128 acf.lockForm(this.$el);
11129
11130 // loading callback
11131 args.loading(this.$el, this);
11132
11133 // update status
11134 this.set('status', 'validating');
11135
11136 // success callback
11137 var onSuccess = function (json) {
11138 // validate
11139 if (!acf.isAjaxSuccess(json)) {
11140 return;
11141 }
11142
11143 // filter
11144 var data = acf.applyFilters('validation_complete', json.data, this.$el, this);
11145
11146 // add errors
11147 if (!data.valid) {
11148 this.addErrors(data.errors);
11149 }
11150 };
11151
11152 // complete
11153 var onComplete = function () {
11154 // unlock form
11155 acf.unlockForm(this.$el);
11156
11157 // failure
11158 if (this.hasErrors()) {
11159 // update status
11160 this.set('status', 'invalid');
11161
11162 // action
11163 acf.doAction('validation_failure', this.$el, this);
11164
11165 // display errors
11166 this.showErrors();
11167
11168 // failure callback
11169 args.failure(this.$el, this);
11170
11171 // success
11172 } else {
11173 // update status
11174 this.set('status', 'valid');
11175
11176 // remove previous error message
11177 if (this.has('notice')) {
11178 this.get('notice').update({
11179 type: 'success',
11180 text: acf.__('Validation successful'),
11181 timeout: 1000
11182 });
11183 }
11184
11185 // action
11186 acf.doAction('validation_success', this.$el, this);
11187 acf.doAction('submit', this.$el);
11188
11189 // success callback (submit form)
11190 args.success(this.$el, this);
11191
11192 // lock form
11193 acf.lockForm(this.$el);
11194
11195 // reset
11196 if (args.reset) {
11197 this.reset();
11198 }
11199 }
11200
11201 // complete callback
11202 args.complete(this.$el, this);
11203
11204 // clear errors
11205 this.clearErrors();
11206 };
11207
11208 // serialize form data
11209 var data = acf.serialize(this.$el);
11210 data.action = 'acf/validate_save_post';
11211
11212 // ajax
11213 $.ajax({
11214 url: acf.get('ajaxurl'),
11215 data: acf.prepareForAjax(data, true),
11216 type: 'post',
11217 dataType: 'json',
11218 context: this,
11219 success: onSuccess,
11220 complete: onComplete
11221 });
11222
11223 // return false to fail validation and allow AJAX
11224 return false;
11225 },
11226 /**
11227 * setup
11228 *
11229 * Called during the constructor function to setup this instance
11230 *
11231 * @date 4/9/18
11232 * @since ACF 5.7.5
11233 *
11234 * @param jQuery $form The form element.
11235 * @return void
11236 */
11237 setup: function ($form) {
11238 // set $el
11239 this.$el = $form;
11240 },
11241 /**
11242 * reset
11243 *
11244 * Rests the validation to be used again.
11245 *
11246 * @date 6/9/18
11247 * @since ACF 5.7.5
11248 *
11249 * @param void
11250 * @return void
11251 */
11252 reset: function () {
11253 // reset data
11254 this.set('errors', []);
11255 this.set('notice', null);
11256 this.set('status', '');
11257
11258 // unlock form
11259 acf.unlockForm(this.$el);
11260 }
11261 });
11262
11263 /**
11264 * getValidator
11265 *
11266 * Returns the instance for a given form element.
11267 *
11268 * @date 4/9/18
11269 * @since ACF 5.7.5
11270 *
11271 * @param jQuery $el The form element.
11272 * @return object
11273 */
11274 var getValidator = function ($el) {
11275 // instantiate
11276 var validator = $el.data('acf');
11277 if (!validator) {
11278 validator = new Validator($el);
11279 }
11280
11281 // return
11282 return validator;
11283 };
11284
11285 /**
11286 * A helper function to generate a Validator for a block form, so .addErrors can be run via block logic.
11287 *
11288 * @since ACF 6.3
11289 *
11290 * @param $el The jQuery block form wrapper element.
11291 * @return bool
11292 */
11293 acf.getBlockFormValidator = function ($el) {
11294 return getValidator($el);
11295 };
11296
11297 /**
11298 * A helper function for the Validator.validate() function.
11299 * Returns true if form is valid, or fetches a validation request and returns false.
11300 *
11301 * @since ACF 5.6.9
11302 *
11303 * @param object args A list of settings to customize the validation process.
11304 * @return bool
11305 */
11306 acf.validateForm = function (args) {
11307 return getValidator(args.form).validate(args);
11308 };
11309
11310 /**
11311 * acf.enableSubmit
11312 *
11313 * Enables a submit button and returns the element.
11314 *
11315 * @date 30/8/18
11316 * @since ACF 5.7.4
11317 *
11318 * @param jQuery $submit The submit button.
11319 * @return jQuery
11320 */
11321 acf.enableSubmit = function ($submit) {
11322 return $submit.removeClass('disabled').removeAttr('disabled');
11323 };
11324
11325 /**
11326 * acf.disableSubmit
11327 *
11328 * Disables a submit button and returns the element.
11329 *
11330 * @date 30/8/18
11331 * @since ACF 5.7.4
11332 *
11333 * @param jQuery $submit The submit button.
11334 * @return jQuery
11335 */
11336 acf.disableSubmit = function ($submit) {
11337 return $submit.addClass('disabled').attr('disabled', true);
11338 };
11339
11340 /**
11341 * acf.showSpinner
11342 *
11343 * Shows the spinner element.
11344 *
11345 * @date 4/9/18
11346 * @since ACF 5.7.5
11347 *
11348 * @param jQuery $spinner The spinner element.
11349 * @return jQuery
11350 */
11351 acf.showSpinner = function ($spinner) {
11352 $spinner.addClass('is-active'); // add class (WP > 4.2)
11353 $spinner.css('display', 'inline-block'); // css (WP < 4.2)
11354 return $spinner;
11355 };
11356
11357 /**
11358 * acf.hideSpinner
11359 *
11360 * Hides the spinner element.
11361 *
11362 * @date 4/9/18
11363 * @since ACF 5.7.5
11364 *
11365 * @param jQuery $spinner The spinner element.
11366 * @return jQuery
11367 */
11368 acf.hideSpinner = function ($spinner) {
11369 $spinner.removeClass('is-active'); // add class (WP > 4.2)
11370 $spinner.css('display', 'none'); // css (WP < 4.2)
11371 return $spinner;
11372 };
11373
11374 /**
11375 * acf.lockForm
11376 *
11377 * Locks a form by disabling its primary inputs and showing a spinner.
11378 *
11379 * @date 4/9/18
11380 * @since ACF 5.7.5
11381 *
11382 * @param jQuery $form The form element.
11383 * @return jQuery
11384 */
11385 acf.lockForm = function ($form) {
11386 // vars
11387 var $wrap = findSubmitWrap($form);
11388 var $submit = $wrap.find('.button, [type="submit"]').not('.acf-nav, .acf-repeater-add-row');
11389 var $spinner = $wrap.find('.spinner, .acf-spinner');
11390
11391 // hide all spinners (hides the preview spinner)
11392 acf.hideSpinner($spinner);
11393
11394 // lock
11395 acf.disableSubmit($submit);
11396 acf.showSpinner($spinner.last());
11397 return $form;
11398 };
11399
11400 /**
11401 * acf.unlockForm
11402 *
11403 * Unlocks a form by enabling its primary inputs and hiding all spinners.
11404 *
11405 * @date 4/9/18
11406 * @since ACF 5.7.5
11407 *
11408 * @param jQuery $form The form element.
11409 * @return jQuery
11410 */
11411 acf.unlockForm = function ($form) {
11412 // vars
11413 var $wrap = findSubmitWrap($form);
11414 var $submit = $wrap.find('.button, [type="submit"]').not('.acf-nav, .acf-repeater-add-row');
11415 var $spinner = $wrap.find('.spinner, .acf-spinner');
11416
11417 // unlock
11418 acf.enableSubmit($submit);
11419 acf.hideSpinner($spinner);
11420 return $form;
11421 };
11422
11423 /**
11424 * findSubmitWrap
11425 *
11426 * An internal function to find the 'primary' form submit wrapping element.
11427 *
11428 * @date 4/9/18
11429 * @since ACF 5.7.5
11430 *
11431 * @param jQuery $form The form element.
11432 * @return jQuery
11433 */
11434 var findSubmitWrap = function ($form) {
11435 // default post submit div
11436 var $wrap = $form.find('#submitdiv');
11437 if ($wrap.length) {
11438 return $wrap;
11439 }
11440
11441 // 3rd party publish box
11442 var $wrap = $form.find('#submitpost');
11443 if ($wrap.length) {
11444 return $wrap;
11445 }
11446
11447 // term, user
11448 var $wrap = $form.find('p.submit').last();
11449 if ($wrap.length) {
11450 return $wrap;
11451 }
11452
11453 // front end form
11454 var $wrap = $form.find('.acf-form-submit');
11455 if ($wrap.length) {
11456 return $wrap;
11457 }
11458
11459 // ACF 6.2 options page modal
11460 var $wrap = $('#acf-create-options-page-form .acf-actions');
11461 if ($wrap.length) {
11462 return $wrap;
11463 }
11464
11465 // ACF 6.0+ headerbar submit
11466 var $wrap = $('.acf-headerbar-actions');
11467 if ($wrap.length) {
11468 return $wrap;
11469 }
11470
11471 // default
11472 return $form;
11473 };
11474
11475 /**
11476 * A debounced function to trigger a form submission.
11477 *
11478 * @date 15/07/2020
11479 * @since ACF 5.9.0
11480 *
11481 * @param type Var Description.
11482 * @return type Description.
11483 */
11484 var submitFormDebounced = acf.debounce(function ($form) {
11485 $form.submit();
11486 });
11487
11488 /**
11489 * Ensure field is visible for validation errors
11490 *
11491 * @date 20/10/2021
11492 * @since ACF 5.11.0
11493 */
11494 var ensureFieldPostBoxIsVisible = function ($el) {
11495 // Find the postbox element containing this field.
11496 var $postbox = $el.parents('.acf-postbox');
11497 if ($postbox.length) {
11498 var acf_postbox = acf.getPostbox($postbox);
11499 if (acf_postbox && acf_postbox.isHiddenByScreenOptions()) {
11500 // Rather than using .show() here, we don't want the field to appear next reload.
11501 // So just temporarily show the field group so validation can complete.
11502 acf_postbox.$el.removeClass('hide-if-js');
11503 acf_postbox.$el.css('display', '');
11504 }
11505 }
11506 };
11507
11508 /**
11509 * Ensure metaboxes which contain browser validation failures are visible.
11510 *
11511 * @date 20/10/2021
11512 * @since ACF 5.11.0
11513 */
11514 var ensureInvalidFieldVisibility = function () {
11515 // Load each ACF input field and check it's browser validation state.
11516 var $inputs = $('.acf-field input');
11517 $inputs.each(function () {
11518 if (!this.checkValidity()) {
11519 // Field is invalid, so we need to make sure it's metabox is visible.
11520 ensureFieldPostBoxIsVisible($(this));
11521 }
11522 });
11523 };
11524
11525 /**
11526 * acf.validation
11527 *
11528 * Global validation logic
11529 *
11530 * @date 4/4/18
11531 * @since ACF 5.6.9
11532 *
11533 * @param void
11534 * @return void
11535 */
11536
11537 acf.validation = new acf.Model({
11538 /** @var string The model identifier. */
11539 id: 'validation',
11540 /** @var bool The active state. Set to false before 'prepare' to prevent validation. */
11541 active: true,
11542 /** @var string The model initialize time. */
11543 wait: 'prepare',
11544 /** @var object The model actions. */
11545 actions: {
11546 ready: 'addInputEvents',
11547 append: 'addInputEvents'
11548 },
11549 /** @var object The model events. */
11550 events: {
11551 'click input[type="submit"]': 'onClickSubmit',
11552 'click button[type="submit"]': 'onClickSubmit',
11553 'click #save-post': 'onClickSave',
11554 'submit form#post': 'onSubmitPost',
11555 'submit form': 'onSubmit'
11556 },
11557 /**
11558 * initialize
11559 *
11560 * Called when initializing the model.
11561 *
11562 * @date 4/9/18
11563 * @since ACF 5.7.5
11564 *
11565 * @param void
11566 * @return void
11567 */
11568 initialize: function () {
11569 // check 'validation' setting
11570 if (!acf.get('validation')) {
11571 this.active = false;
11572 this.actions = {};
11573 this.events = {};
11574 }
11575 },
11576 /**
11577 * enable
11578 *
11579 * Enables validation.
11580 *
11581 * @date 4/9/18
11582 * @since ACF 5.7.5
11583 *
11584 * @param void
11585 * @return void
11586 */
11587 enable: function () {
11588 this.active = true;
11589 },
11590 /**
11591 * disable
11592 *
11593 * Disables validation.
11594 *
11595 * @date 4/9/18
11596 * @since ACF 5.7.5
11597 *
11598 * @param void
11599 * @return void
11600 */
11601 disable: function () {
11602 this.active = false;
11603 },
11604 /**
11605 * reset
11606 *
11607 * Rests the form validation to be used again
11608 *
11609 * @date 6/9/18
11610 * @since ACF 5.7.5
11611 *
11612 * @param jQuery $form The form element.
11613 * @return void
11614 */
11615 reset: function ($form) {
11616 getValidator($form).reset();
11617 },
11618 /**
11619 * addInputEvents
11620 *
11621 * Adds 'invalid' event listeners to HTML inputs.
11622 *
11623 * @date 4/9/18
11624 * @since ACF 5.7.5
11625 *
11626 * @param jQuery $el The element being added / readied.
11627 * @return void
11628 */
11629 addInputEvents: function ($el) {
11630 // Bug exists in Safari where custom "invalid" handling prevents draft from saving.
11631 if (acf.get('browser') === 'safari') return;
11632
11633 // vars
11634 var $inputs = $('.acf-field [name]', $el);
11635
11636 // check
11637 if ($inputs.length) {
11638 this.on($inputs, 'invalid', 'onInvalid');
11639 }
11640 },
11641 /**
11642 * onInvalid
11643 *
11644 * Callback for the 'invalid' event.
11645 *
11646 * @date 4/9/18
11647 * @since ACF 5.7.5
11648 *
11649 * @param object e The event object.
11650 * @param jQuery $el The input element.
11651 * @return void
11652 */
11653 onInvalid: function (e, $el) {
11654 // prevent default
11655 // - prevents browser error message
11656 // - also fixes chrome bug where 'hidden-by-tab' field throws focus error
11657 e.preventDefault();
11658
11659 // vars
11660 var $form = $el.closest('form');
11661
11662 // check form exists
11663 if ($form.length) {
11664 // add error to validator
11665 getValidator($form).addError({
11666 input: $el.attr('name'),
11667 message: acf.strEscape(e.target.validationMessage)
11668 });
11669
11670 // trigger submit on $form
11671 // - allows for "save", "preview" and "publish" to work
11672 submitFormDebounced($form);
11673 }
11674 },
11675 /**
11676 * onClickSubmit
11677 *
11678 * Callback when clicking submit.
11679 *
11680 * @date 4/9/18
11681 * @since ACF 5.7.5
11682 *
11683 * @param object e The event object.
11684 * @param jQuery $el The input element.
11685 * @return void
11686 */
11687 onClickSubmit: function (e, $el) {
11688 // Some browsers (safari) force their browser validation before our AJAX validation,
11689 // so we need to make sure fields are visible earlier than showErrors()
11690 ensureInvalidFieldVisibility();
11691
11692 // store the "click event" for later use in this.onSubmit()
11693 this.set('originalEvent', e);
11694 },
11695 /**
11696 * onClickSave
11697 *
11698 * Set ignore to true when saving a draft.
11699 *
11700 * @date 4/9/18
11701 * @since ACF 5.7.5
11702 *
11703 * @param object e The event object.
11704 * @param jQuery $el The input element.
11705 * @return void
11706 */
11707 onClickSave: function (e, $el) {
11708 this.set('ignore', true);
11709 },
11710 /**
11711 * onSubmitPost
11712 *
11713 * Callback when the 'post' form is submit.
11714 *
11715 * @date 5/3/19
11716 * @since ACF 5.7.13
11717 *
11718 * @param object e The event object.
11719 * @param jQuery $el The input element.
11720 * @return void
11721 */
11722 onSubmitPost: function (e, $el) {
11723 // Check if is preview.
11724 if ($('input#wp-preview').val() === 'dopreview') {
11725 // Ignore validation.
11726 this.set('ignore', true);
11727
11728 // Unlock form to fix conflict with core "submit.edit-post" event causing all submit buttons to be disabled.
11729 acf.unlockForm($el);
11730 }
11731 },
11732 /**
11733 * onSubmit
11734 *
11735 * Callback when the form is submit.
11736 *
11737 * @date 4/9/18
11738 * @since ACF 5.7.5
11739 *
11740 * @param object e The event object.
11741 * @param jQuery $el The input element.
11742 * @return void
11743 */
11744 onSubmit: function (e, $el) {
11745 // Allow form to submit if...
11746 if (
11747 // Validation has been disabled.
11748 !this.active ||
11749 // Or this event is to be ignored.
11750 this.get('ignore') ||
11751 // Or this event has already been prevented.
11752 e.isDefaultPrevented()) {
11753 // Return early and call reset function.
11754 return this.allowSubmit();
11755 }
11756
11757 // Validate form.
11758 var valid = acf.validateForm({
11759 form: $el,
11760 event: this.get('originalEvent')
11761 });
11762
11763 // If not valid, stop event to prevent form submit.
11764 if (!valid) {
11765 e.preventDefault();
11766 }
11767 },
11768 /**
11769 * allowSubmit
11770 *
11771 * Resets data during onSubmit when the form is allowed to submit.
11772 *
11773 * @date 5/3/19
11774 * @since ACF 5.7.13
11775 *
11776 * @param void
11777 * @return void
11778 */
11779 allowSubmit: function () {
11780 // Reset "ignore" state.
11781 this.set('ignore', false);
11782
11783 // Reset "originalEvent" object.
11784 this.set('originalEvent', false);
11785
11786 // Return true
11787 return true;
11788 }
11789 });
11790 var gutenbergValidation = new acf.Model({
11791 wait: 'prepare',
11792 initialize: function () {
11793 // Bail early if not Gutenberg.
11794 if (!acf.isGutenberg()) {
11795 return;
11796 }
11797
11798 // Customize the editor.
11799 this.customizeEditor();
11800 },
11801 customizeEditor: function () {
11802 // Extract vars.
11803 var editor = wp.data.dispatch('core/editor');
11804 var editorSelect = wp.data.select('core/editor');
11805 var notices = wp.data.dispatch('core/notices');
11806
11807 // Backup original method.
11808 var savePost = editor.savePost;
11809
11810 // Listen for changes to post status and perform actions:
11811 // a) Enable validation for "publish" action.
11812 // b) Remember last non "publish" status used for restoring after validation fail.
11813 var useValidation = false;
11814 var lastPostStatus = '';
11815 wp.data.subscribe(function () {
11816 var postStatus = editorSelect.getEditedPostAttribute('status');
11817 useValidation = postStatus === 'publish' || postStatus === 'future';
11818 lastPostStatus = postStatus !== 'publish' ? postStatus : lastPostStatus;
11819 });
11820
11821 // Create validation version.
11822 editor.savePost = function (options) {
11823 options = options || {};
11824
11825 // Backup vars.
11826 var _this = this;
11827 var _args = arguments;
11828 // Perform validation within a Promise.
11829 return new Promise(function (resolve, reject) {
11830 if (typeof acf.gutenbergEditPost === 'function') {
11831 acf.gutenbergEditPost();
11832 }
11833
11834 // Bail early if is autosave or preview.
11835 if (options.isAutosave || options.isPreview) {
11836 return resolve('Validation ignored (autosave).');
11837 }
11838
11839 // Bail early if validation is not needed.
11840 if (!useValidation) {
11841 return resolve('Validation ignored (draft).');
11842 }
11843
11844 // Check if we've currently got an ACF block selected which is failing validation, but might not be presented yet.
11845 if ('undefined' !== typeof acf.blockInstances) {
11846 const selectedBlockId = wp.data.select('core/block-editor').getSelectedBlockClientId();
11847 if (selectedBlockId && selectedBlockId in acf.blockInstances) {
11848 const acfBlockState = acf.blockInstances[selectedBlockId];
11849 if (acfBlockState.validation_errors) {
11850 // Deselect the block to show the error and lock the save.
11851 acf.debug('Rejecting save because the block editor has a invalid ACF block selected.');
11852 notices.createErrorNotice(acf.__('An ACF Block on this page requires attention before you can save.'), {
11853 id: 'acf-validation',
11854 isDismissible: true
11855 });
11856 wp.data.dispatch('core/editor').lockPostSaving('acf/block/' + selectedBlockId);
11857 wp.data.dispatch('core/block-editor').selectBlock(false);
11858 return reject('ACF Validation failed for selected block.');
11859 }
11860 }
11861 }
11862
11863 // Recursive function to check all blocks (including nested innerBlocks) for ACF validation errors
11864 function checkBlocksForErrors(blocks) {
11865 const errors = [];
11866 return new Promise(function (resolve) {
11867 // Iterate through each block
11868 blocks.forEach(block => {
11869 // If this block has nested blocks, recursively check them
11870 if (block.innerBlocks.length > 0) {
11871 checkBlocksForErrors(block.innerBlocks).then(hasError => {
11872 if (hasError) {
11873 return resolve(true);
11874 }
11875 });
11876 }
11877
11878 // Check if this block has an ACF error attribute
11879 if (block.attributes.hasAcfError) {
11880 // Check if the publish panel is open and close it if so
11881 const publishPanel = document.getElementsByClassName('editor-post-publish-panel')[0];
11882 if (publishPanel) {
11883 // See https://github.com/WordPress/secure-custom-fields/pull/272
11884 // `togglePublishSidebar` was only introduced in WP 6.6, it should be optional
11885 wp.data.dispatch('core/editor').togglePublishSidebar?.();
11886 }
11887
11888 // Add block to errors array
11889 errors.push(block);
11890
11891 // Dispatch a custom event to notify about the block with validation error
11892 document.dispatchEvent(new CustomEvent('acf/block/has-error', {
11893 detail: {
11894 acfBlocksWithValidationErrors: block.clientId
11895 }
11896 }));
11897
11898 // Log debug message
11899 acf.debug('Rejecting save because the block editor has a invalid ACF block selected.');
11900
11901 // Resolve with true (error found)
11902 return resolve(true);
11903 }
11904 });
11905
11906 // If errors were found, select the first one
11907 if (errors.length > 0) {
11908 const blockClientId = errors[0].clientId;
11909 wp.data.dispatch('core/block-editor').selectBlock(blockClientId);
11910 }
11911
11912 // No errors found, resolve with false
11913 return resolve(false);
11914 });
11915 }
11916
11917 // Call the function with all blocks from the editor
11918 checkBlocksForErrors(wp.data.select('core/block-editor').getBlocks()).then(hasError => {
11919 // If errors were found
11920 if (hasError) {
11921 // Display an error notice
11922 notices.createErrorNotice(acf.__('An ACF Block on this page requires attention before you can save.'), {
11923 id: 'acf-blocks-validation',
11924 isDismissible: true
11925 });
11926
11927 // Reject the save operation
11928 return reject('ACF Block Validation failed');
11929 }
11930 });
11931
11932 // Validate the editor form.
11933 var valid = acf.validateForm({
11934 form: $('#wpbody-content > .block-editor'),
11935 reset: true,
11936 complete: function ($form, validator) {
11937 // Always unlock the form after AJAX.
11938 editor.unlockPostSaving('acf');
11939 },
11940 failure: function ($form, validator) {
11941 // Get validation error and append to Gutenberg notices.
11942 var notice = validator.get('notice');
11943 var action = validator.get('action');
11944 if (action && 'object' === typeof action && action.label && action.url) {
11945 notices.createErrorNotice(notice.get('text', {
11946 id: 'acf-validation',
11947 isDismissible: true,
11948 actions: [{
11949 label: action.label,
11950 url: action.url
11951 }]
11952 }));
11953 } else {
11954 notices.createErrorNotice(notice.get('text'), {
11955 id: 'acf-validation',
11956 isDismissible: true
11957 });
11958 }
11959 notice.remove();
11960 // Restore last non "publish" status.
11961 if (lastPostStatus) {
11962 editor.editPost({
11963 status: lastPostStatus
11964 });
11965 }
11966
11967 // Reject promise and prevent savePost().
11968 reject('Validation failed.');
11969 },
11970 success: function () {
11971 notices.removeNotice('acf-validation');
11972
11973 // Resolve promise and allow savePost().
11974 resolve('Validation success.');
11975 }
11976 });
11977
11978 // Resolve promise and allow savePost() if no validation is needed.
11979 if (valid) {
11980 resolve('Validation bypassed.');
11981
11982 // Otherwise, lock the form and wait for AJAX response.
11983 } else {
11984 editor.lockPostSaving('acf');
11985 }
11986 }).then(function () {
11987 return savePost.apply(_this, _args);
11988 }, err => {
11989 // Nothing to do here, user is alerted of validation issues.
11990 });
11991 };
11992 }
11993 });
11994 })(jQuery);
11995
11996 /***/ })
11997
11998 /******/ });
11999 /************************************************************************/
12000 /******/ // The module cache
12001 /******/ var __webpack_module_cache__ = {};
12002 /******/
12003 /******/ // The require function
12004 /******/ function __webpack_require__(moduleId) {
12005 /******/ // Check if module is in cache
12006 /******/ var cachedModule = __webpack_module_cache__[moduleId];
12007 /******/ if (cachedModule !== undefined) {
12008 /******/ return cachedModule.exports;
12009 /******/ }
12010 /******/ // Create a new module (and put it into the cache)
12011 /******/ var module = __webpack_module_cache__[moduleId] = {
12012 /******/ // no module.id needed
12013 /******/ // no module.loaded needed
12014 /******/ exports: {}
12015 /******/ };
12016 /******/
12017 /******/ // Execute the module function
12018 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
12019 /******/
12020 /******/ // Return the exports of the module
12021 /******/ return module.exports;
12022 /******/ }
12023 /******/
12024 /************************************************************************/
12025 /******/ /* webpack/runtime/compat get default export */
12026 /******/ (() => {
12027 /******/ // getDefaultExport function for compatibility with non-harmony modules
12028 /******/ __webpack_require__.n = (module) => {
12029 /******/ var getter = module && module.__esModule ?
12030 /******/ () => (module['default']) :
12031 /******/ () => (module);
12032 /******/ __webpack_require__.d(getter, { a: getter });
12033 /******/ return getter;
12034 /******/ };
12035 /******/ })();
12036 /******/
12037 /******/ /* webpack/runtime/define property getters */
12038 /******/ (() => {
12039 /******/ // define getter functions for harmony exports
12040 /******/ __webpack_require__.d = (exports, definition) => {
12041 /******/ for(var key in definition) {
12042 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
12043 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
12044 /******/ }
12045 /******/ }
12046 /******/ };
12047 /******/ })();
12048 /******/
12049 /******/ /* webpack/runtime/hasOwnProperty shorthand */
12050 /******/ (() => {
12051 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
12052 /******/ })();
12053 /******/
12054 /******/ /* webpack/runtime/make namespace object */
12055 /******/ (() => {
12056 /******/ // define __esModule on exports
12057 /******/ __webpack_require__.r = (exports) => {
12058 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
12059 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
12060 /******/ }
12061 /******/ Object.defineProperty(exports, '__esModule', { value: true });
12062 /******/ };
12063 /******/ })();
12064 /******/
12065 /************************************************************************/
12066 var __webpack_exports__ = {};
12067 // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
12068 (() => {
12069 "use strict";
12070 /*!************************************!*\
12071 !*** ./assets/src/js/acf-input.js ***!
12072 \************************************/
12073 __webpack_require__.r(__webpack_exports__);
12074 /* harmony import */ var _acf_field_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_acf-field.js */ "./assets/src/js/_acf-field.js");
12075 /* harmony import */ var _acf_field_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_acf_field_js__WEBPACK_IMPORTED_MODULE_0__);
12076 /* harmony import */ var _acf_fields_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./_acf-fields.js */ "./assets/src/js/_acf-fields.js");
12077 /* harmony import */ var _acf_fields_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_acf_fields_js__WEBPACK_IMPORTED_MODULE_1__);
12078 /* harmony import */ var _acf_field_accordion_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./_acf-field-accordion.js */ "./assets/src/js/_acf-field-accordion.js");
12079 /* harmony import */ var _acf_field_accordion_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_acf_field_accordion_js__WEBPACK_IMPORTED_MODULE_2__);
12080 /* harmony import */ var _acf_field_button_group_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./_acf-field-button-group.js */ "./assets/src/js/_acf-field-button-group.js");
12081 /* harmony import */ var _acf_field_checkbox_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./_acf-field-checkbox.js */ "./assets/src/js/_acf-field-checkbox.js");
12082 /* harmony import */ var _acf_field_checkbox_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_acf_field_checkbox_js__WEBPACK_IMPORTED_MODULE_4__);
12083 /* harmony import */ var _acf_field_color_picker_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./_acf-field-color-picker.js */ "./assets/src/js/_acf-field-color-picker.js");
12084 /* harmony import */ var _acf_field_color_picker_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_acf_field_color_picker_js__WEBPACK_IMPORTED_MODULE_5__);
12085 /* harmony import */ var _acf_field_date_picker_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./_acf-field-date-picker.js */ "./assets/src/js/_acf-field-date-picker.js");
12086 /* harmony import */ var _acf_field_date_picker_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_acf_field_date_picker_js__WEBPACK_IMPORTED_MODULE_6__);
12087 /* harmony import */ var _acf_field_date_time_picker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./_acf-field-date-time-picker.js */ "./assets/src/js/_acf-field-date-time-picker.js");
12088 /* harmony import */ var _acf_field_date_time_picker_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_acf_field_date_time_picker_js__WEBPACK_IMPORTED_MODULE_7__);
12089 /* harmony import */ var _acf_field_google_map_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./_acf-field-google-map.js */ "./assets/src/js/_acf-field-google-map.js");
12090 /* harmony import */ var _acf_field_google_map_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_acf_field_google_map_js__WEBPACK_IMPORTED_MODULE_8__);
12091 /* harmony import */ var _acf_field_icon_picker_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./_acf-field-icon-picker.js */ "./assets/src/js/_acf-field-icon-picker.js");
12092 /* harmony import */ var _acf_field_icon_picker_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_acf_field_icon_picker_js__WEBPACK_IMPORTED_MODULE_9__);
12093 /* harmony import */ var _acf_field_image_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./_acf-field-image.js */ "./assets/src/js/_acf-field-image.js");
12094 /* harmony import */ var _acf_field_image_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(_acf_field_image_js__WEBPACK_IMPORTED_MODULE_10__);
12095 /* harmony import */ var _acf_field_file_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./_acf-field-file.js */ "./assets/src/js/_acf-field-file.js");
12096 /* harmony import */ var _acf_field_file_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_acf_field_file_js__WEBPACK_IMPORTED_MODULE_11__);
12097 /* harmony import */ var _acf_field_link_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./_acf-field-link.js */ "./assets/src/js/_acf-field-link.js");
12098 /* harmony import */ var _acf_field_link_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_acf_field_link_js__WEBPACK_IMPORTED_MODULE_12__);
12099 /* harmony import */ var _acf_field_oembed_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./_acf-field-oembed.js */ "./assets/src/js/_acf-field-oembed.js");
12100 /* harmony import */ var _acf_field_oembed_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(_acf_field_oembed_js__WEBPACK_IMPORTED_MODULE_13__);
12101 /* harmony import */ var _acf_field_radio_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./_acf-field-radio.js */ "./assets/src/js/_acf-field-radio.js");
12102 /* harmony import */ var _acf_field_radio_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(_acf_field_radio_js__WEBPACK_IMPORTED_MODULE_14__);
12103 /* harmony import */ var _acf_field_range_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./_acf-field-range.js */ "./assets/src/js/_acf-field-range.js");
12104 /* harmony import */ var _acf_field_range_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(_acf_field_range_js__WEBPACK_IMPORTED_MODULE_15__);
12105 /* harmony import */ var _acf_field_relationship_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./_acf-field-relationship.js */ "./assets/src/js/_acf-field-relationship.js");
12106 /* harmony import */ var _acf_field_relationship_js__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(_acf_field_relationship_js__WEBPACK_IMPORTED_MODULE_16__);
12107 /* harmony import */ var _acf_field_select_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./_acf-field-select.js */ "./assets/src/js/_acf-field-select.js");
12108 /* harmony import */ var _acf_field_select_js__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_acf_field_select_js__WEBPACK_IMPORTED_MODULE_17__);
12109 /* harmony import */ var _acf_field_tab_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./_acf-field-tab.js */ "./assets/src/js/_acf-field-tab.js");
12110 /* harmony import */ var _acf_field_tab_js__WEBPACK_IMPORTED_MODULE_18___default = /*#__PURE__*/__webpack_require__.n(_acf_field_tab_js__WEBPACK_IMPORTED_MODULE_18__);
12111 /* harmony import */ var _acf_field_post_object_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./_acf-field-post-object.js */ "./assets/src/js/_acf-field-post-object.js");
12112 /* harmony import */ var _acf_field_post_object_js__WEBPACK_IMPORTED_MODULE_19___default = /*#__PURE__*/__webpack_require__.n(_acf_field_post_object_js__WEBPACK_IMPORTED_MODULE_19__);
12113 /* harmony import */ var _acf_field_page_link_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./_acf-field-page-link.js */ "./assets/src/js/_acf-field-page-link.js");
12114 /* harmony import */ var _acf_field_page_link_js__WEBPACK_IMPORTED_MODULE_20___default = /*#__PURE__*/__webpack_require__.n(_acf_field_page_link_js__WEBPACK_IMPORTED_MODULE_20__);
12115 /* harmony import */ var _acf_field_user_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./_acf-field-user.js */ "./assets/src/js/_acf-field-user.js");
12116 /* harmony import */ var _acf_field_user_js__WEBPACK_IMPORTED_MODULE_21___default = /*#__PURE__*/__webpack_require__.n(_acf_field_user_js__WEBPACK_IMPORTED_MODULE_21__);
12117 /* harmony import */ var _acf_field_taxonomy_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./_acf-field-taxonomy.js */ "./assets/src/js/_acf-field-taxonomy.js");
12118 /* harmony import */ var _acf_field_taxonomy_js__WEBPACK_IMPORTED_MODULE_22___default = /*#__PURE__*/__webpack_require__.n(_acf_field_taxonomy_js__WEBPACK_IMPORTED_MODULE_22__);
12119 /* harmony import */ var _acf_field_time_picker_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./_acf-field-time-picker.js */ "./assets/src/js/_acf-field-time-picker.js");
12120 /* harmony import */ var _acf_field_time_picker_js__WEBPACK_IMPORTED_MODULE_23___default = /*#__PURE__*/__webpack_require__.n(_acf_field_time_picker_js__WEBPACK_IMPORTED_MODULE_23__);
12121 /* harmony import */ var _acf_field_true_false_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./_acf-field-true-false.js */ "./assets/src/js/_acf-field-true-false.js");
12122 /* harmony import */ var _acf_field_true_false_js__WEBPACK_IMPORTED_MODULE_24___default = /*#__PURE__*/__webpack_require__.n(_acf_field_true_false_js__WEBPACK_IMPORTED_MODULE_24__);
12123 /* harmony import */ var _acf_field_url_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./_acf-field-url.js */ "./assets/src/js/_acf-field-url.js");
12124 /* harmony import */ var _acf_field_url_js__WEBPACK_IMPORTED_MODULE_25___default = /*#__PURE__*/__webpack_require__.n(_acf_field_url_js__WEBPACK_IMPORTED_MODULE_25__);
12125 /* harmony import */ var _acf_field_wysiwyg_js__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./_acf-field-wysiwyg.js */ "./assets/src/js/_acf-field-wysiwyg.js");
12126 /* harmony import */ var _acf_field_wysiwyg_js__WEBPACK_IMPORTED_MODULE_26___default = /*#__PURE__*/__webpack_require__.n(_acf_field_wysiwyg_js__WEBPACK_IMPORTED_MODULE_26__);
12127 /* harmony import */ var _acf_condition_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./_acf-condition.js */ "./assets/src/js/_acf-condition.js");
12128 /* harmony import */ var _acf_condition_js__WEBPACK_IMPORTED_MODULE_27___default = /*#__PURE__*/__webpack_require__.n(_acf_condition_js__WEBPACK_IMPORTED_MODULE_27__);
12129 /* harmony import */ var _acf_conditions_js__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./_acf-conditions.js */ "./assets/src/js/_acf-conditions.js");
12130 /* harmony import */ var _acf_conditions_js__WEBPACK_IMPORTED_MODULE_28___default = /*#__PURE__*/__webpack_require__.n(_acf_conditions_js__WEBPACK_IMPORTED_MODULE_28__);
12131 /* harmony import */ var _acf_condition_types_js__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./_acf-condition-types.js */ "./assets/src/js/_acf-condition-types.js");
12132 /* harmony import */ var _acf_condition_types_js__WEBPACK_IMPORTED_MODULE_29___default = /*#__PURE__*/__webpack_require__.n(_acf_condition_types_js__WEBPACK_IMPORTED_MODULE_29__);
12133 /* harmony import */ var _acf_unload_js__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./_acf-unload.js */ "./assets/src/js/_acf-unload.js");
12134 /* harmony import */ var _acf_unload_js__WEBPACK_IMPORTED_MODULE_30___default = /*#__PURE__*/__webpack_require__.n(_acf_unload_js__WEBPACK_IMPORTED_MODULE_30__);
12135 /* harmony import */ var _acf_postbox_js__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./_acf-postbox.js */ "./assets/src/js/_acf-postbox.js");
12136 /* harmony import */ var _acf_postbox_js__WEBPACK_IMPORTED_MODULE_31___default = /*#__PURE__*/__webpack_require__.n(_acf_postbox_js__WEBPACK_IMPORTED_MODULE_31__);
12137 /* harmony import */ var _acf_media_js__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./_acf-media.js */ "./assets/src/js/_acf-media.js");
12138 /* harmony import */ var _acf_media_js__WEBPACK_IMPORTED_MODULE_32___default = /*#__PURE__*/__webpack_require__.n(_acf_media_js__WEBPACK_IMPORTED_MODULE_32__);
12139 /* harmony import */ var _acf_screen_js__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./_acf-screen.js */ "./assets/src/js/_acf-screen.js");
12140 /* harmony import */ var _acf_screen_js__WEBPACK_IMPORTED_MODULE_33___default = /*#__PURE__*/__webpack_require__.n(_acf_screen_js__WEBPACK_IMPORTED_MODULE_33__);
12141 /* harmony import */ var _acf_select2_js__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./_acf-select2.js */ "./assets/src/js/_acf-select2.js");
12142 /* harmony import */ var _acf_select2_js__WEBPACK_IMPORTED_MODULE_34___default = /*#__PURE__*/__webpack_require__.n(_acf_select2_js__WEBPACK_IMPORTED_MODULE_34__);
12143 /* harmony import */ var _acf_tinymce_js__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./_acf-tinymce.js */ "./assets/src/js/_acf-tinymce.js");
12144 /* harmony import */ var _acf_tinymce_js__WEBPACK_IMPORTED_MODULE_35___default = /*#__PURE__*/__webpack_require__.n(_acf_tinymce_js__WEBPACK_IMPORTED_MODULE_35__);
12145 /* harmony import */ var _acf_validation_js__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./_acf-validation.js */ "./assets/src/js/_acf-validation.js");
12146 /* harmony import */ var _acf_validation_js__WEBPACK_IMPORTED_MODULE_36___default = /*#__PURE__*/__webpack_require__.n(_acf_validation_js__WEBPACK_IMPORTED_MODULE_36__);
12147 /* harmony import */ var _acf_helpers_js__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./_acf-helpers.js */ "./assets/src/js/_acf-helpers.js");
12148 /* harmony import */ var _acf_helpers_js__WEBPACK_IMPORTED_MODULE_37___default = /*#__PURE__*/__webpack_require__.n(_acf_helpers_js__WEBPACK_IMPORTED_MODULE_37__);
12149 /* harmony import */ var _acf_compatibility_js__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./_acf-compatibility.js */ "./assets/src/js/_acf-compatibility.js");
12150 /* harmony import */ var _acf_compatibility_js__WEBPACK_IMPORTED_MODULE_38___default = /*#__PURE__*/__webpack_require__.n(_acf_compatibility_js__WEBPACK_IMPORTED_MODULE_38__);
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190 })();
12191
12192 /******/ })()
12193 ;
12194 //# sourceMappingURL=acf-input.js.map