PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.7.0
Secure Custom Fields v6.7.0
6.9.5 6.9.4 6.9.3 6.9.2 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 / pro / acf-pro-input.js
secure-custom-fields / assets / build / js / pro Last commit date
acf-pro-blocks.asset.php 9 months ago acf-pro-blocks.js 9 months ago acf-pro-blocks.js.map 9 months ago acf-pro-blocks.min.asset.php 9 months ago acf-pro-blocks.min.js 9 months ago acf-pro-field-group.asset.php 1 year ago acf-pro-field-group.js 1 year ago acf-pro-field-group.js.map 9 months ago acf-pro-field-group.min.asset.php 9 months ago acf-pro-field-group.min.js 9 months ago acf-pro-input.asset.php 9 months ago acf-pro-input.js 9 months ago acf-pro-input.js.map 9 months ago acf-pro-input.min.asset.php 9 months ago acf-pro-input.min.js 9 months ago acf-pro-ui-options-page.asset.php 9 months ago acf-pro-ui-options-page.js 9 months ago acf-pro-ui-options-page.js.map 9 months ago acf-pro-ui-options-page.min.asset.php 9 months ago acf-pro-ui-options-page.min.js 9 months ago index.php 1 year ago
acf-pro-input.js
2493 lines
1 /******/ (() => { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ "./assets/src/js/pro/_acf-field-flexible-content.js":
5 /*!**********************************************************!*\
6 !*** ./assets/src/js/pro/_acf-field-flexible-content.js ***!
7 \**********************************************************/
8 /***/ (() => {
9
10 (function ($) {
11 var Field = acf.Field.extend({
12 type: 'flexible_content',
13 wait: '',
14 events: {
15 'click [data-name="add-layout"]': 'onClickAdd',
16 'click [data-name="duplicate-layout"]': 'onClickDuplicate',
17 'click [data-name="collapse-layout"]': 'onClickCollapse',
18 'click [data-name="remove-layout"]': 'onClickRemove',
19 'click [data-name="more-layout-actions"]': 'onClickMoreActions',
20 'click .acf-fc-expand-all': 'onClickExpandAll',
21 'click .acf-fc-collapse-all': 'onClickCollapseAll',
22 showField: 'onShow',
23 unloadField: 'onUnload',
24 mouseover: 'onHover'
25 },
26 $control: function () {
27 return this.$('.acf-flexible-content:first');
28 },
29 $layoutsWrap: function () {
30 return this.$('.acf-flexible-content:first > .values');
31 },
32 $layouts: function () {
33 return this.$('.acf-flexible-content:first > .values > .layout');
34 },
35 $layout: function (index) {
36 return this.$('.acf-flexible-content:first > .values > .layout:eq(' + index + ')');
37 },
38 $clonesWrap: function () {
39 return this.$('.acf-flexible-content:first > .clones');
40 },
41 $clones: function () {
42 return this.$('.acf-flexible-content:first > .clones > .layout');
43 },
44 $clone: function (name) {
45 return this.$('.acf-flexible-content:first > .clones > .layout[data-layout="' + name + '"]');
46 },
47 $actions: function () {
48 return this.$('.acf-actions:last');
49 },
50 $button: function () {
51 return this.$('.acf-fc-top-actions:first .button, .acf-actions:last .button');
52 },
53 $popup: function () {
54 return this.$('.tmpl-popup:last');
55 },
56 $moreLayoutActions: function () {
57 return this.$('.tmpl-more-layout-actions:last');
58 },
59 getPopupHTML: function () {
60 var html = this.$popup().html();
61 var $html = $(html);
62 var self = this;
63
64 // modify popup
65 $html.find('[data-layout]').each(function () {
66 var $a = $(this);
67 var min = $a.data('min') || 0;
68 var max = $a.data('max') || 0;
69 var name = $a.data('layout') || '';
70 var count = self.countLayouts(name);
71
72 // max
73 if (max && count >= max) {
74 $a.addClass('disabled');
75 return;
76 }
77
78 // min
79 if (min && count < min) {
80 var required = min - count;
81 var title = acf.__('{required} {label} {identifier} required (min {min})');
82 var identifier = acf._n('layout', 'layouts', required);
83
84 // translate
85 title = title.replace('{required}', required);
86 title = title.replace('{label}', name); // 5.5.0
87 title = title.replace('{identifier}', identifier);
88 title = title.replace('{min}', min);
89
90 // badge
91 $a.append('<span class="badge" title="' + title + '">' + required + '</span>');
92 }
93 });
94
95 // update
96 html = $html.outerHTML();
97 return html;
98 },
99 getMoreLayoutActionsHTML: function () {
100 return this.$moreLayoutActions().html();
101 },
102 getValue: function () {
103 return this.$layouts().length;
104 },
105 allowRemove: function () {
106 var min = parseInt(this.get('min'));
107 return !min || min < this.val();
108 },
109 allowAdd: function () {
110 return !this.isFull();
111 },
112 isFull: function () {
113 const max = parseInt(this.get('max'));
114 return max && this.countLayouts() >= max;
115 },
116 addSortable: function (self) {
117 // bail early if max 1 row
118 if (this.get('max') == 1) {
119 return;
120 }
121
122 // add sortable
123 this.$layoutsWrap().sortable({
124 items: '> .layout',
125 handle: '> .acf-fc-layout-actions-wrap .acf-fc-layout-handle',
126 forceHelperSize: true,
127 zIndex: 9999,
128 forcePlaceholderSize: true,
129 scroll: true,
130 stop: function (event, ui) {
131 self.render();
132 },
133 update: function (event, ui) {
134 self.$input().trigger('change');
135 }
136 });
137 },
138 addCollapsed: function () {
139 var indexes = preference.load(this.get('key'));
140
141 // bail early if no collapsed
142 if (!indexes) {
143 return false;
144 }
145
146 // loop
147 this.$layouts().each(function (i) {
148 if (indexes.indexOf(i) > -1) {
149 $(this).addClass('-collapsed');
150 }
151 });
152 },
153 addUnscopedEvents: function (self) {
154 // invalidField
155 this.on('invalidField', '.layout', function (e) {
156 self.onInvalidField(e, $(this));
157 });
158 $(document).on('click focusin', function (e) {
159 if (!$(e.target).closest('.acf-flexible-content .layout').length) {
160 self.setActiveLayout($([]));
161 }
162 });
163 },
164 initialize: function () {
165 // add unscoped events
166 this.addUnscopedEvents(this);
167
168 // add collapsed
169 this.addCollapsed();
170
171 // disable clone
172 acf.disable(this.$clonesWrap(), this.cid);
173
174 // render
175 this.render();
176 },
177 render: function () {
178 // update order number
179 this.$layouts().each(function (i) {
180 $(this).find('.acf-fc-layout-order:first').html(i + 1);
181 });
182
183 // Add event handlers for setting active layout
184 const self = this;
185 this.$control().on('click focus', '> .values > .layout', function (event) {
186 const layout = $(event.target).closest('.layout');
187 self.setActiveLayout(layout);
188 });
189
190 // empty
191 if (this.val() == 0) {
192 this.$control().addClass('-empty');
193 } else {
194 this.$control().removeClass('-empty');
195 }
196 this.maybeDisableAddLayout();
197
198 // max
199 if (this.isFull()) {
200 this.$button().addClass('disabled');
201 } else {
202 this.$button().removeClass('disabled');
203 }
204 },
205 maybeDisableAddLayout: function () {
206 const self = this;
207 const isFull = this.isFull();
208 const buttonLabel = this.$control().data('button-label');
209 const duplicateLabel = acf.__('Duplicate');
210 const maxRowsReached = acf.__('Maximum rows reached ({max})').replace('{max}', this.get('max'));
211
212 // Disable/enable main add buttons
213 if (isFull) {
214 this.$button().addClass('disabled');
215 } else {
216 this.$button().removeClass('disabled');
217 }
218
219 // Process each layout
220 this.$layouts().each(function () {
221 const $layout = $(this);
222 const $addButton = $layout.find('[data-name="add-layout"]:first');
223 const $duplicateButton = $layout.find('[data-name="duplicate-layout"]:first');
224 const layoutMax = $layout.data('max') || 0;
225 const $enableToggle = $('.acf-toggle-layout.enable');
226
227 // Handle field-level max
228 if (isFull) {
229 $addButton.addClass('disabled').attr('title', maxRowsReached);
230 $duplicateButton.addClass('disabled').attr('title', maxRowsReached);
231 $enableToggle.addClass('disabled');
232 } else {
233 $addButton.removeClass('disabled').attr('title', buttonLabel);
234 $duplicateButton.removeClass('disabled').attr('title', duplicateLabel);
235 $enableToggle.removeClass('disabled');
236 }
237
238 // Handle layout-specific max
239 if (layoutMax) {
240 const layoutName = $layout.data('layout') || '';
241 const layoutCount = self.countLayouts(layoutName);
242 if (layoutCount >= layoutMax) {
243 const maxLayoutReached = acf.__('Maximum {label} {identifier} reached ({max})').replace('{label}', layoutName).replace('{identifier}', acf._n('layout', 'layouts', layoutMax)).replace('{max}', layoutMax);
244 $duplicateButton.addClass('disabled').attr('title', maxLayoutReached);
245 $enableToggle.addClass('disabled');
246 }
247 }
248 });
249 },
250 setActiveLayout: function ($layout) {
251 // Remove active-layout class from all layouts
252 $('.layout').removeClass('active-layout');
253
254 // Add active-layout class to the provided layout if it exists
255 if ($layout.length) {
256 $layout.addClass('active-layout');
257 }
258 },
259 onShow: function (e, $el, context) {
260 // get sub fields
261 var fields = acf.getFields({
262 is: ':visible',
263 parent: this.$el
264 });
265
266 // trigger action
267 // - ignore context, no need to pass through 'conditional_logic'
268 // - this is just for fields like google_map to render itself
269 acf.doAction('show_fields', fields);
270 },
271 countLayouts: function (name) {
272 return this.$layouts().filter(function () {
273 const $layout = $(this);
274 return (!name || $layout.data('layout') === name) && '0' !== $layout.attr('data-enabled');
275 }).length;
276 },
277 countLayoutsByName: function (currentLayout) {
278 const layoutMax = currentLayout.data('max');
279 if (!layoutMax) {
280 return true;
281 }
282 const name = currentLayout.data('layout') || '';
283 const count = this.countLayouts(name);
284 if (count >= layoutMax) {
285 let text = acf.__('This field has a limit of {max} {label} {identifier}');
286 const identifier = acf._n('layout', 'layouts', layoutMax);
287 const layoutLabel = '"' + currentLayout.data('label') + '"';
288 text = text.replace('{max}', layoutMax);
289 text = text.replace('{label}', layoutLabel);
290 text = text.replace('{identifier}', identifier);
291 this.showNotice({
292 text: text,
293 type: 'warning'
294 });
295 return false;
296 }
297 return true;
298 },
299 validateAdd: function () {
300 // return true if allowed
301 if (this.allowAdd()) {
302 return true;
303 }
304 var max = this.get('max');
305 var text = acf.__('This field has a limit of {max} {label} {identifier}');
306 var identifier = acf._n('layout', 'layouts', max);
307 text = text.replace('{max}', max);
308 text = text.replace('{label}', '');
309 text = text.replace('{identifier}', identifier);
310 this.showNotice({
311 text: text,
312 type: 'warning'
313 });
314 return false;
315 },
316 onClickAdd: function (e, $el) {
317 // validate
318 if (!this.validateAdd()) {
319 return false;
320 }
321
322 // within layout
323 var $layout = null;
324 // Check the context data attribute to determine how to handle the add
325 if ($el.data('context') === 'layout') {
326 $layout = $el.closest('.layout');
327 $layout.addClass('-hover');
328 } else if ($el.data('context') === 'top-actions') {
329 $layout = $el.closest('.acf-flexible-content').find('.values .layout').first();
330 $layout.addClass('-hover');
331 }
332
333 // new popup
334 var popup = new Popup({
335 target: $el,
336 targetConfirm: false,
337 text: this.getPopupHTML(),
338 context: this,
339 confirm: function (e, $el) {
340 // check disabled
341 if ($el.hasClass('disabled')) {
342 return;
343 }
344
345 // add
346 this.add({
347 layout: $el.data('layout'),
348 before: $layout
349 });
350 },
351 cancel: function () {
352 if ($layout) {
353 $layout.removeClass('-hover');
354 }
355 }
356 });
357
358 // add extra event
359 popup.on('click', '[data-layout]', 'onConfirm');
360 },
361 add: function (args) {
362 // defaults
363 args = acf.parseArgs(args, {
364 layout: '',
365 before: false
366 });
367
368 // validate
369 if (!this.allowAdd()) {
370 return false;
371 }
372
373 // add row
374 var $el = acf.duplicate({
375 target: this.$clone(args.layout),
376 append: this.proxy(function ($el, $el2) {
377 // append
378 if (args.before) {
379 args.before.before($el2);
380 } else {
381 this.$layoutsWrap().append($el2);
382 }
383
384 // enable
385 acf.enable($el2, this.cid);
386
387 // render
388 this.render();
389 })
390 });
391
392 // trigger change for validation errors
393 this.$input().trigger('change');
394 this.setActiveLayout($el);
395 return $el;
396 },
397 onClickDuplicate: function (e, $el) {
398 var $layout = $el.closest('.layout');
399 // Validate each layout's max count.
400 if (!this.countLayoutsByName($layout.first())) {
401 return false;
402 }
403
404 // Validate with warning.
405 if (!this.validateAdd()) {
406 return false;
407 }
408
409 // get layout and duplicate it.
410 this.duplicateLayout($layout);
411 },
412 duplicateLayout: function ($layout) {
413 // Validate without warning.
414 if (!this.allowAdd()) {
415 return false;
416 }
417 var fieldKey = this.get('key');
418
419 // Duplicate layout.
420 var $el = acf.duplicate({
421 target: $layout,
422 // Provide a custom renaming callback to avoid renaming parent row attributes.
423 rename: function (name, value, search, replace) {
424 // Rename id attributes from "field_1-search" to "field_1-replace".
425 if (name === 'id' || name === 'for') {
426 return value.replace(fieldKey + '-' + search, fieldKey + '-' + replace);
427
428 // Rename name and for attributes from "[field_1][search]" to "[field_1][replace]".
429 } else {
430 return value.replace(fieldKey + '][' + search, fieldKey + '][' + replace);
431 }
432 },
433 before: function ($el) {
434 acf.doAction('unmount', $el);
435 },
436 after: function ($el, $el2) {
437 acf.doAction('remount', $el);
438 }
439 });
440
441 // trigger change for validation errors
442 this.$input().trigger('change');
443
444 // Update order numbers.
445 this.render();
446
447 // Draw focus to layout.
448 acf.focusAttention($el);
449 this.setActiveLayout($el);
450 // Return new layout.
451 return $el;
452 },
453 onClickToggleLayout: function (event, layout) {
454 const disabledInput = layout.find('.acf-fc-layout-disabled:first');
455 if (layout.attr('data-enabled') === '1') {
456 // Disable the layout
457 layout.attr('data-enabled', '0');
458 disabledInput.val('1');
459 } else if (layout.attr('data-enabled') === '0' && this.countLayoutsByName(layout.first()) && !this.isFull()) {
460 // Enable the layout only if validation passes
461 layout.attr('data-enabled', '1');
462 disabledInput.val('0');
463 }
464
465 // Trigger change event to save the state
466 this.$input().trigger('change');
467 this.maybeDisableAddLayout();
468 },
469 onClickRenameLayout: function (event, layout) {
470 const currentName = layout.find('.acf-fc-layout-custom-label:first').val();
471 const popupOptions = {
472 context: this,
473 title: acf.__('Rename Layout'),
474 textConfirm: acf.__('Rename'),
475 textCancel: acf.__('Cancel'),
476 currentName: currentName,
477 openedBy: layout.find('a[data-name="more-layout-actions"]').first(),
478 width: '500px',
479 confirm: function (event, element, newName) {
480 this.renameLayout(layout, newName);
481 },
482 cancel: function () {
483 layout.removeClass('-hover');
484 }
485 };
486
487 // Create new rename popup dialog
488 new RenameLayoutPopup(popupOptions);
489 },
490 renameLayout: function (layout, newName) {
491 // Set the escaped new name in the hidden input
492 layout.find('.acf-fc-layout-custom-label:first').val(acf.strEscape(newName));
493 const titleElement = layout.find('.acf-fc-layout-title:first');
494
495 // Update the visible title
496 titleElement.html(acf.escHtml(newName));
497 if (newName.length) {
498 // Mark as renamed with custom label
499 layout.attr('data-renamed', '1');
500 } else {
501 // Restore original title if name is empty
502 let originalTitle = layout.find('.acf-fc-layout-original-title:first').html().trim();
503
504 // Remove parentheses from original title
505 originalTitle = originalTitle.substring(1, originalTitle.length - 1);
506 titleElement.html(acf.escHtml(originalTitle));
507 layout.attr('data-renamed', '0');
508 }
509
510 // Trigger change event to save the state
511 this.$input().trigger('change');
512 },
513 validateRemove: function () {
514 // return true if allowed
515 if (this.allowRemove()) {
516 return true;
517 }
518 var min = this.get('min');
519 var text = acf.__('This field requires at least {min} {label} {identifier}');
520 var identifier = acf._n('layout', 'layouts', min);
521
522 // replace
523 text = text.replace('{min}', min);
524 text = text.replace('{label}', '');
525 text = text.replace('{identifier}', identifier);
526
527 // add notice
528 this.showNotice({
529 text: text,
530 type: 'warning'
531 });
532 return false;
533 },
534 onClickRemove: function (e, $el) {
535 const $layout = $el.closest('.layout');
536
537 // Bypass confirmation when holding down "shift" key.
538 if (e.shiftKey) {
539 return this.removeLayout($layout);
540 }
541
542 // add class
543 $layout.addClass('-hover');
544
545 // add tooltip
546 const tooltipOptions = {
547 confirmRemove: true,
548 context: this,
549 title: acf.__('Delete Layout'),
550 text: acf.__('Are you sure you want to delete the layout?'),
551 textConfirm: acf.__('Delete'),
552 textCancel: acf.__('Cancel'),
553 openedBy: $layout.find('a[data-name="more-layout-actions"]').first(),
554 width: '500px',
555 confirm: function (e, $el) {
556 this.removeLayout($layout);
557 },
558 cancel: function () {
559 $layout.removeClass('-hover');
560 }
561 };
562
563 // Check if layout has a custom label
564 const customLabel = $layout.data('label');
565 if (customLabel.length) {
566 // Customize the popup title and text with the layout label
567 tooltipOptions.title = acf.__('Delete %s').replace('%s', acf.escHtml(customLabel));
568 tooltipOptions.text = acf.__('Are you sure you want to delete %s?').replace('%s', customLabel);
569 }
570
571 // Create and show the confirmation popup
572 acf.newPopup(tooltipOptions);
573 },
574 removeLayout: function ($layout) {
575 // reference
576 var self = this;
577 var endHeight = this.getValue() == 1 ? 60 : 0;
578
579 // remove
580 acf.remove({
581 target: $layout,
582 endHeight: endHeight,
583 complete: function () {
584 // trigger change to allow attachment save
585 self.$input().trigger('change');
586
587 // render
588 self.render();
589 }
590 });
591 },
592 onClickCollapse: function (e, $el) {
593 var $layout = $el.closest('.layout');
594
595 // toggle
596 if (this.isLayoutClosed($layout)) {
597 this.openLayout($layout);
598 } else {
599 this.closeLayout($layout);
600 }
601 },
602 onClickExpandAll: function (e, $el) {
603 e.preventDefault();
604 const self = this;
605 this.$layouts().each(function () {
606 self.openLayout($(this));
607 });
608 },
609 onClickCollapseAll: function (e, $el) {
610 e.preventDefault();
611 const self = this;
612 this.$layouts().each(function () {
613 self.closeLayout($(this));
614 });
615 },
616 onClickMoreActions: function (e, $el) {
617 const $layout = $el.closest('.layout');
618 new MoreLayoutActionsPopup({
619 target: $el,
620 targetConfirm: false,
621 text: this.getMoreLayoutActionsHTML(),
622 context: this,
623 confirm: function (e, $el) {
624 // Check if the clicked element is a toggle action
625 const action = $el.data('action');
626 if (action === 'toggle-layout') {
627 this.onClickToggleLayout(e, $layout);
628 }
629 if (action === 'rename-layout') {
630 this.onClickRenameLayout(e, $layout);
631 }
632 },
633 cancel: function () {
634 $layout.find('a[data-name="more-layout-actions"]').first().trigger('focus');
635 }
636 });
637 },
638 isLayoutClosed: function ($layout) {
639 return $layout.hasClass('-collapsed');
640 },
641 openLayout: function ($layout) {
642 $layout.removeClass('-collapsed');
643 acf.doAction('show', $layout, 'collapse');
644 },
645 closeLayout: function ($layout) {
646 $layout.addClass('-collapsed');
647 acf.doAction('hide', $layout, 'collapse');
648
649 // render
650 // - no change could happen if layout was already closed. Only render when closing
651 this.renderLayout($layout);
652 },
653 renderLayout: function ($layout) {
654 const $input = $layout.children('input');
655 const prefix = $input.attr('name').replace('[acf_fc_layout]', '');
656
657 // ajax data
658 var ajaxData = {
659 action: 'acf/fields/flexible_content/layout_title',
660 field_key: this.get('key'),
661 i: $layout.index(),
662 layout: $layout.data('layout'),
663 value: acf.serialize($layout, prefix)
664 };
665
666 // ajax
667 $.ajax({
668 url: acf.get('ajaxurl'),
669 data: acf.prepareForAjax(ajaxData),
670 dataType: 'html',
671 type: 'post',
672 success: function (html) {
673 if (html) {
674 if ($layout.data('renamed') === 1) {
675 $layout.find('.acf-fc-layout-original-title').first().html(`(${html})`);
676 } else {
677 $layout.find('.acf-fc-layout-title').first().html(html);
678 }
679 }
680 }
681 });
682 },
683 onUnload: function () {
684 var indexes = [];
685
686 // loop
687 this.$layouts().each(function (i) {
688 if ($(this).hasClass('-collapsed')) {
689 indexes.push(i);
690 }
691 });
692
693 // allow null
694 indexes = indexes.length ? indexes : null;
695
696 // set
697 preference.save(this.get('key'), indexes);
698 },
699 onInvalidField: function (e, $layout) {
700 // open if is collapsed
701 if (this.isLayoutClosed($layout)) {
702 this.openLayout($layout);
703 }
704 },
705 onHover: function () {
706 // add sortable
707 this.addSortable(this);
708
709 // remove event
710 this.off('mouseover');
711 }
712 });
713 acf.registerFieldType(Field);
714
715 /**
716 * Popup
717 *
718 * description
719 *
720 * @date 7/4/18
721 * @since ACF 5.6.9
722 *
723 * @param type $var Description. Default.
724 * @return type Description.
725 */
726
727 var Popup = acf.models.TooltipConfirm.extend({
728 events: {
729 'click [data-layout]': 'onConfirm',
730 'click [data-event="cancel"]': 'onCancel'
731 },
732 render: function () {
733 // set HTML
734 this.html(this.get('text'));
735
736 // add class
737 this.$el.addClass('acf-fc-popup');
738 this.position();
739 },
740 show: function () {
741 $('body').append(this.$el);
742 },
743 position: function () {
744 const $popup = this.$el;
745 const $target = this.get('target');
746 const $container = $target.closest('.acf-flexible-content');
747 positionPopup($popup, $target, $container, 8);
748 }
749 }); /**
750 * MoreLayoutActionsPopup
751 *
752 * Popup for showing more layout actions (remove, toggle, rename)
753 */
754 const MoreLayoutActionsPopup = acf.models.TooltipConfirm.extend({
755 events: {
756 'click [data-action]': 'onConfirm',
757 'keydown [role="menu"]': 'onKeyDown'
758 },
759 render: function () {
760 const $layout = this.get('target').closest('.layout');
761 this.html(this.get('text'));
762 this.$el.addClass('acf-fc-popup acf-more-layout-actions');
763
764 // Add enable-layout class if layout is disabled
765 if ($layout.attr('data-enabled') === '0') {
766 this.$el.addClass('enable-layout');
767 } else {
768 this.$el.removeClass('enable-layout');
769 }
770 const context = this.get('context') || this;
771 const self = this;
772 setTimeout(function () {
773 self.$el.find('a').first().trigger('focus');
774 context.maybeDisableAddLayout();
775 }, 1);
776 },
777 show: function () {
778 $('body').append(this.$el);
779 },
780 position: function () {
781 const $popup = this.$el;
782 const $target = this.get('target');
783 const $container = $target.closest('.layout');
784 positionPopup($popup, $target, $container, 2);
785 },
786 onKeyDown: function (event, $el) {
787 if (['ArrowDown', 'ArrowUp', 'Escape', 'Tab'].indexOf(event.key) === -1) {
788 return;
789 }
790 event.preventDefault();
791 if (event.key === 'Escape') {
792 return void this.onCancel(event, $el);
793 }
794 const $menuItems = this.$el.find('[role="menu"]').find('[role="menuitem"]:visible');
795 const $activeElement = $(document.activeElement);
796 const menuItemsLength = $menuItems.length;
797 let currentIndex = $menuItems.index($activeElement);
798 let nextIndex;
799 if (event.key === 'ArrowDown' || event.key === 'Tab' && !event.shiftKey) {
800 nextIndex = (currentIndex + 1) % menuItemsLength;
801 } else {
802 nextIndex = (currentIndex - 1 + menuItemsLength) % menuItemsLength;
803 }
804 $menuItems.eq(nextIndex).trigger('focus');
805 }
806 });
807
808 /**
809 * RenameLayoutPopup
810 *
811 * Popup dialog for renaming layout labels
812 */
813 const RenameLayoutPopup = acf.models.PopupConfirm.extend({
814 events: {
815 'click [data-event="close"]': 'onCancel',
816 'click .acf-close-popup': 'onClickClose',
817 keydown: 'onPressEscapeClose',
818 'click [data-event="confirm"]': 'onConfirm',
819 'click .acf-reset-label': 'onReset',
820 'submit .acf-rename-layout-form': 'onConfirm'
821 },
822 tmpl: function () {
823 const resetButton = this.get('currentName') === '' ? '' : `<button type="button" data-event="reset-label" class="acf-btn acf-btn-secondary acf-reset-label">${acf.strEscape(acf.__('Remove Custom Label'))}</button>`;
824 return `
825 <div id="acf-popup" role="dialog" aria-labelledby="acf-rename-layout-title" tabindex="-1">
826 <div class="acf-popup-box acf-box acf-confirm-popup acf-rename-layout-popup">
827 <div class="title">
828 <h3 id="acf-rename-layout-title">${this.get('title')}</h3>
829 <a href="#" data-event="close" aria-label="${acf.strEscape(acf.__('Close modal'))}">
830 <i class="acf-icon -close"></i>
831 </a>
832 </div>
833 <form class="inner acf-rename-layout-form">
834 <div class="acf-field">
835 <div class="acf-label">
836 <label for="acf-new-layout-label">${acf.strEscape(acf.__('New Label'))}</label>
837 </div>
838 <div class="acf-input">
839 <input id="acf-new-layout-label" type="text" name="acf_new_layout_label" value="${this.get('currentName')}">
840 </div>
841 </div>
842 <div class="acf-actions">
843 ${resetButton}
844 <button type="button" data-event="close" class="acf-btn acf-btn-secondary acf-close-popup">${acf.strEscape(this.get('textCancel'))}</button>
845 <button type="submit" data-event="confirm" class="acf-btn acf-btn-primary acf-confirm">${acf.strEscape(this.get('textConfirm'))}</button>
846 </div>
847 </form>
848 </div>
849 <div class="bg" data-event="close"></div>
850 </div>`;
851 },
852 render: function () {
853 acf.models.PopupConfirm.prototype.render.apply(this, arguments);
854 setTimeout(() => {
855 const $input = this.$el.find('input#acf-new-layout-label');
856 const textLength = $input.val().length;
857 $input.trigger('focus');
858 $input[0].setSelectionRange(textLength, textLength);
859 }, 1);
860 },
861 onConfirm: function (event, $el) {
862 event.preventDefault();
863 event.stopPropagation();
864 const newName = this.$el.find('input#acf-new-layout-label').val();
865 this.close();
866 const confirmCallback = this.get('confirm');
867 const context = this.get('context') || this;
868 confirmCallback.apply(context, [event, $el, newName]);
869 },
870 onReset: function (event, $el) {
871 event.preventDefault();
872 event.stopPropagation();
873 this.$el.find('input#acf-new-layout-label').val('');
874 this.onConfirm(event, $el);
875 }
876 });
877
878 /**
879 * positionPopup
880 *
881 * Utility function to position popup relative to target within container
882 */
883 const positionPopup = function ($popup, $target, $container, offset) {
884 if (!$target.length || !$container.length) return;
885 const targetOffset = $target.offset();
886 const targetWidth = $target.outerWidth();
887 const targetHeight = $target.outerHeight();
888 const popupWidth = $popup.outerWidth();
889 const popupHeight = $popup.outerHeight();
890 const isRTL = $('body').hasClass('rtl');
891 const windowScrollTop = $(window).scrollTop();
892 const windowHeight = $(window).height();
893 let left, positionClass;
894 let top = targetOffset.top + targetHeight + offset;
895 let isAbove = false;
896
897 // Check if popup would be cut off at bottom of viewport
898 if (targetOffset.top + targetHeight + popupHeight + offset > windowScrollTop + windowHeight && targetOffset.top - popupHeight - offset > windowScrollTop) {
899 top = targetOffset.top - popupHeight - offset;
900 isAbove = true;
901 }
902 if (isRTL) {
903 left = targetOffset.left;
904 positionClass = isAbove ? 'bottom-left' : 'top-left';
905 } else {
906 left = targetOffset.left + targetWidth - popupWidth;
907 positionClass = isAbove ? 'bottom-right' : 'top-right';
908 }
909 $popup.removeClass('top-right bottom-right top-left bottom-left').css({
910 position: 'absolute',
911 top: top,
912 left: left
913 }).addClass(positionClass);
914 }; /**
915 * conditions
916 *
917 * description
918 *
919 * @date 9/4/18
920 * @since ACF 5.6.9
921 *
922 * @param type $var Description. Default.
923 * @return type Description.
924 */
925
926 // register existing conditions
927 acf.registerConditionForFieldType('hasValue', 'flexible_content');
928 acf.registerConditionForFieldType('hasNoValue', 'flexible_content');
929 acf.registerConditionForFieldType('lessThan', 'flexible_content');
930 acf.registerConditionForFieldType('greaterThan', 'flexible_content');
931
932 // state
933 var preference = new acf.Model({
934 name: 'this.collapsedLayouts',
935 key: function (key, context) {
936 var count = this.get(key + context) || 0;
937
938 // update
939 count++;
940 this.set(key + context, count, true);
941
942 // modify fieldKey
943 if (count > 1) {
944 key += '-' + count;
945 }
946 return key;
947 },
948 load: function (key) {
949 var key = this.key(key, 'load');
950 var data = acf.getPreference(this.name);
951 if (data && data[key]) {
952 return data[key];
953 } else {
954 return false;
955 }
956 },
957 save: function (key, value) {
958 var key = this.key(key, 'save');
959 var data = acf.getPreference(this.name) || {};
960
961 // delete
962 if (value === null) {
963 delete data[key];
964
965 // append
966 } else {
967 data[key] = value;
968 }
969
970 // allow null
971 if ($.isEmptyObject(data)) {
972 data = null;
973 }
974
975 // save
976 acf.setPreference(this.name, data);
977 }
978 });
979 })(jQuery);
980
981 /***/ }),
982
983 /***/ "./assets/src/js/pro/_acf-field-gallery.js":
984 /*!*************************************************!*\
985 !*** ./assets/src/js/pro/_acf-field-gallery.js ***!
986 \*************************************************/
987 /***/ (() => {
988
989 (function ($) {
990 var Field = acf.Field.extend({
991 type: 'gallery',
992 events: {
993 'click .acf-gallery-add': 'onClickAdd',
994 'click .acf-gallery-edit': 'onClickEdit',
995 'click .acf-gallery-remove': 'onClickRemove',
996 'click .acf-gallery-attachment': 'onClickSelect',
997 'click .acf-gallery-close': 'onClickClose',
998 'change .acf-gallery-sort': 'onChangeSort',
999 'click .acf-gallery-update': 'onUpdate',
1000 mouseover: 'onHover',
1001 showField: 'render'
1002 },
1003 actions: {
1004 validation_begin: 'onValidationBegin',
1005 validation_failure: 'onValidationFailure',
1006 resize: 'onResize'
1007 },
1008 onValidationBegin: function () {
1009 acf.disable(this.$sideData(), this.cid);
1010 },
1011 onValidationFailure: function () {
1012 acf.enable(this.$sideData(), this.cid);
1013 },
1014 $control: function () {
1015 return this.$('.acf-gallery');
1016 },
1017 $collection: function () {
1018 return this.$('.acf-gallery-attachments');
1019 },
1020 $attachments: function () {
1021 return this.$('.acf-gallery-attachment');
1022 },
1023 $attachment: function (id) {
1024 return this.$('.acf-gallery-attachment[data-id="' + id + '"]');
1025 },
1026 $active: function () {
1027 return this.$('.acf-gallery-attachment.active');
1028 },
1029 $main: function () {
1030 return this.$('.acf-gallery-main');
1031 },
1032 $side: function () {
1033 return this.$('.acf-gallery-side');
1034 },
1035 $sideData: function () {
1036 return this.$('.acf-gallery-side-data');
1037 },
1038 isFull: function () {
1039 var max = parseInt(this.get('max'));
1040 var count = this.$attachments().length;
1041 return max && count >= max;
1042 },
1043 getValue: function () {
1044 // vars
1045 var val = [];
1046
1047 // loop
1048 this.$attachments().each(function () {
1049 val.push($(this).data('id'));
1050 });
1051
1052 // return
1053 return val.length ? val : false;
1054 },
1055 addUnscopedEvents: function (self) {
1056 // invalidField
1057 this.on('change', '.acf-gallery-side', function (e) {
1058 self.onUpdate(e, $(this));
1059 });
1060 },
1061 addSortable: function (self) {
1062 // add sortable
1063 this.$collection().sortable({
1064 items: '.acf-gallery-attachment',
1065 forceHelperSize: true,
1066 zIndex: 9999,
1067 forcePlaceholderSize: true,
1068 scroll: true,
1069 start: function (event, ui) {
1070 ui.placeholder.html(ui.item.html());
1071 ui.placeholder.removeAttr('style');
1072 },
1073 update: function (event, ui) {
1074 self.$input().trigger('change');
1075 }
1076 });
1077
1078 // resizable
1079 this.$control().resizable({
1080 handles: 's',
1081 minHeight: 200,
1082 stop: function (event, ui) {
1083 acf.update_user_setting('gallery_height', ui.size.height);
1084 }
1085 });
1086 },
1087 initialize: function () {
1088 // add unscoped events
1089 this.addUnscopedEvents(this);
1090
1091 // render
1092 this.render();
1093 },
1094 render: function () {
1095 // vars
1096 var $sort = this.$('.acf-gallery-sort');
1097 var $add = this.$('.acf-gallery-add');
1098 var count = this.$attachments().length;
1099
1100 // disable add
1101 if (this.isFull()) {
1102 $add.addClass('disabled');
1103 } else {
1104 $add.removeClass('disabled');
1105 }
1106
1107 // disable select
1108 if (!count) {
1109 $sort.addClass('disabled');
1110 } else {
1111 $sort.removeClass('disabled');
1112 }
1113
1114 // resize
1115 this.resize();
1116 },
1117 resize: function () {
1118 // vars
1119 var width = this.$control().width();
1120 var target = 150;
1121 var columns = Math.round(width / target);
1122
1123 // max columns = 8
1124 columns = Math.min(columns, 8);
1125
1126 // update data
1127 this.$control().attr('data-columns', columns);
1128 },
1129 onResize: function () {
1130 this.resize();
1131 },
1132 openSidebar: function () {
1133 // add class
1134 this.$control().addClass('-open');
1135
1136 // hide bulk actions
1137 // should be done with CSS
1138 //this.$main().find('.acf-gallery-sort').hide();
1139
1140 // vars
1141 var width = this.$control().width() / 3;
1142 width = parseInt(width);
1143 width = Math.max(width, 350);
1144
1145 // animate
1146 this.$('.acf-gallery-side-inner').css({
1147 width: width - 1
1148 });
1149 this.$side().animate({
1150 width: width - 1
1151 }, 250);
1152 this.$main().animate({
1153 right: width
1154 }, 250);
1155 },
1156 closeSidebar: function () {
1157 // remove class
1158 this.$control().removeClass('-open');
1159
1160 // clear selection
1161 this.$active().removeClass('active');
1162
1163 // disable sidebar
1164 acf.disable(this.$side());
1165
1166 // animate
1167 var $sideData = this.$('.acf-gallery-side-data');
1168 this.$main().animate({
1169 right: 0
1170 }, 250);
1171 this.$side().animate({
1172 width: 0
1173 }, 250, function () {
1174 $sideData.html('');
1175 });
1176 },
1177 onClickAdd: function (e, $el) {
1178 // validate
1179 if (this.isFull()) {
1180 this.showNotice({
1181 text: acf.__('Maximum selection reached'),
1182 type: 'warning'
1183 });
1184 return;
1185 }
1186
1187 // new frame
1188 var frame = acf.newMediaPopup({
1189 mode: 'select',
1190 title: acf.__('Add Image to Gallery'),
1191 field: this.get('key'),
1192 multiple: 'add',
1193 library: this.get('library'),
1194 allowedTypes: this.get('mime_types'),
1195 selected: this.val(),
1196 select: $.proxy(function (attachment, i) {
1197 this.appendAttachment(attachment, i);
1198 }, this)
1199 });
1200 },
1201 appendAttachment: function (attachment, i) {
1202 // vars
1203 attachment = this.validateAttachment(attachment);
1204
1205 // bail early if is full
1206 if (this.isFull()) {
1207 return;
1208 }
1209
1210 // bail early if already exists
1211 if (this.$attachment(attachment.id).length) {
1212 return;
1213 }
1214
1215 // html
1216 var html = ['<div class="acf-gallery-attachment" data-id="' + attachment.id + '">', '<input type="hidden" value="' + attachment.id + '" name="' + this.getInputName() + '[]">', '<div class="margin" title="">', '<div class="thumbnail">', '<img src="" alt="">', '</div>', '<div class="filename"></div>', '</div>', '<div class="actions">', '<a href="#" class="acf-icon -cancel dark acf-gallery-remove" data-id="' + attachment.id + '"></a>', '</div>', '</div>'].join('');
1217 var $html = $(html);
1218
1219 // append
1220 this.$collection().append($html);
1221
1222 // move to beginning
1223 if (this.get('insert') === 'prepend') {
1224 var $before = this.$attachments().eq(i);
1225 if ($before.length) {
1226 $before.before($html);
1227 }
1228 }
1229
1230 // render attachment
1231 this.renderAttachment(attachment);
1232
1233 // render
1234 this.render();
1235
1236 // trigger change
1237 this.$input().trigger('change');
1238 },
1239 validateAttachment: function (attachment) {
1240 // defaults
1241 attachment = acf.parseArgs(attachment, {
1242 id: '',
1243 url: '',
1244 alt: '',
1245 title: '',
1246 filename: '',
1247 type: 'image'
1248 });
1249
1250 // WP attachment
1251 if (attachment.attributes) {
1252 attachment = attachment.attributes;
1253
1254 // preview size
1255 var url = acf.isget(attachment, 'sizes', this.get('preview_size'), 'url');
1256 if (url !== null) {
1257 attachment.url = url;
1258 }
1259 }
1260
1261 // return
1262 return attachment;
1263 },
1264 renderAttachment: function (attachment) {
1265 // vars
1266 attachment = this.validateAttachment(attachment);
1267
1268 // vars
1269 var $el = this.$attachment(attachment.id);
1270
1271 // Image type.
1272 if (attachment.type == 'image') {
1273 // Remove filename.
1274 $el.find('.filename').remove();
1275
1276 // Other file type.
1277 } else {
1278 // Check for attachment featured image.
1279 var image = acf.isget(attachment, 'image', 'src');
1280 if (image !== null) {
1281 attachment.url = image;
1282 }
1283
1284 // Update filename text.
1285 $el.find('.filename').text(attachment.filename);
1286 }
1287
1288 // Default to mimetype icon.
1289 if (!attachment.url) {
1290 attachment.url = acf.get('mimeTypeIcon');
1291 $el.addClass('-icon');
1292 }
1293
1294 // update els
1295 $el.find('img').attr({
1296 src: attachment.url,
1297 alt: attachment.alt,
1298 title: attachment.title
1299 });
1300
1301 // update val
1302 acf.val($el.find('input'), attachment.id);
1303 },
1304 editAttachment: function (id) {
1305 // new frame
1306 var frame = acf.newMediaPopup({
1307 mode: 'edit',
1308 title: acf.__('Edit Image'),
1309 button: acf.__('Update Image'),
1310 attachment: id,
1311 field: this.get('key'),
1312 select: $.proxy(function (attachment, i) {
1313 this.renderAttachment(attachment);
1314 // todo - render sidebar
1315 }, this)
1316 });
1317 },
1318 onClickEdit: function (e, $el) {
1319 var id = $el.data('id');
1320 if (id) {
1321 this.editAttachment(id);
1322 }
1323 },
1324 removeAttachment: function (id) {
1325 // close sidebar (if open)
1326 this.closeSidebar();
1327
1328 // remove attachment
1329 this.$attachment(id).remove();
1330
1331 // render
1332 this.render();
1333
1334 // trigger change
1335 this.$input().trigger('change');
1336 },
1337 onClickRemove: function (e, $el) {
1338 // prevent event from triggering click on attachment
1339 e.preventDefault();
1340 e.stopPropagation();
1341
1342 //remove
1343 var id = $el.data('id');
1344 if (id) {
1345 this.removeAttachment(id);
1346 }
1347 },
1348 selectAttachment: function (id) {
1349 // vars
1350 var $el = this.$attachment(id);
1351
1352 // bail early if already active
1353 if ($el.hasClass('active')) {
1354 return;
1355 }
1356
1357 // step 1
1358 var step1 = this.proxy(function () {
1359 // save any changes in sidebar
1360 this.$side().find(':focus').trigger('blur');
1361
1362 // clear selection
1363 this.$active().removeClass('active');
1364
1365 // add selection
1366 $el.addClass('active');
1367
1368 // open sidebar
1369 this.openSidebar();
1370
1371 // call step 2
1372 step2();
1373 });
1374
1375 // step 2
1376 var step2 = this.proxy(function () {
1377 const ajaxData = {
1378 action: 'acf/fields/gallery/get_attachment',
1379 nonce: this.get('nonce'),
1380 field_key: this.get('key'),
1381 id: id
1382 };
1383
1384 // abort prev ajax call
1385 if (this.has('xhr')) {
1386 this.get('xhr').abort();
1387 }
1388
1389 // loading
1390 acf.showLoading(this.$sideData());
1391
1392 // get HTML
1393 var xhr = $.ajax({
1394 url: acf.get('ajaxurl'),
1395 data: acf.prepareForAjax(ajaxData),
1396 type: 'post',
1397 dataType: 'html',
1398 cache: false,
1399 success: step3
1400 });
1401
1402 // update
1403 this.set('xhr', xhr);
1404 });
1405
1406 // step 3
1407 var step3 = this.proxy(function (html) {
1408 // bail early if no html
1409 if (!html) {
1410 return;
1411 }
1412
1413 // vars
1414 var $side = this.$sideData();
1415
1416 // render
1417 $side.html(html);
1418
1419 // remove acf form data
1420 $side.find('.compat-field-acf-form-data').remove();
1421
1422 // merge tables
1423 $side.find('> table.form-table > tbody').append($side.find('> .compat-attachment-fields > tbody > tr'));
1424
1425 // setup fields
1426 acf.doAction('append', $side);
1427 });
1428
1429 // run step 1
1430 step1();
1431 },
1432 onClickSelect: function (e, $el) {
1433 var id = $el.data('id');
1434 if (id) {
1435 this.selectAttachment(id);
1436 }
1437 },
1438 onClickClose: function (e, $el) {
1439 this.closeSidebar();
1440 },
1441 onChangeSort: function (e, $el) {
1442 // Bail early if is disabled.
1443 if ($el.hasClass('disabled')) {
1444 return;
1445 }
1446
1447 // Get sort val.
1448 var val = $el.val();
1449 if (!val) {
1450 return;
1451 }
1452
1453 // find ids
1454 var ids = [];
1455 this.$attachments().each(function () {
1456 ids.push($(this).data('id'));
1457 });
1458
1459 // step 1
1460 var step1 = this.proxy(function () {
1461 const ajaxData = {
1462 action: 'acf/fields/gallery/get_sort_order',
1463 nonce: this.get('nonce'),
1464 field_key: this.get('key'),
1465 ids: ids,
1466 sort: val
1467 };
1468
1469 // get results
1470 var xhr = $.ajax({
1471 url: acf.get('ajaxurl'),
1472 dataType: 'json',
1473 type: 'post',
1474 cache: false,
1475 data: acf.prepareForAjax(ajaxData),
1476 success: step2
1477 });
1478 });
1479
1480 // step 2
1481 var step2 = this.proxy(function (json) {
1482 // validate
1483 if (!acf.isAjaxSuccess(json)) {
1484 return;
1485 }
1486
1487 // reverse order
1488 json.data.reverse();
1489
1490 // loop
1491 json.data.map(function (id) {
1492 this.$collection().prepend(this.$attachment(id));
1493 }, this);
1494 });
1495
1496 // call step 1
1497 step1();
1498 },
1499 onUpdate: function (e, $el) {
1500 // vars
1501 var $submit = this.$('.acf-gallery-update');
1502
1503 // validate
1504 if ($submit.hasClass('disabled')) {
1505 return;
1506 }
1507
1508 // serialize data
1509 const ajaxData = acf.serialize(this.$sideData());
1510
1511 // loading
1512 $submit.addClass('disabled');
1513 $submit.before('<i class="acf-loading"></i> ');
1514
1515 // Append AJAX action and nonce.
1516 ajaxData.action = 'acf/fields/gallery/update_attachment';
1517 ajaxData.nonce = this.get('nonce');
1518 ajaxData.field_key = this.get('key');
1519
1520 // ajax
1521 $.ajax({
1522 url: acf.get('ajaxurl'),
1523 data: acf.prepareForAjax(ajaxData),
1524 type: 'post',
1525 dataType: 'json',
1526 complete: function () {
1527 $submit.removeClass('disabled');
1528 $submit.prev('.acf-loading').remove();
1529 }
1530 });
1531 },
1532 onHover: function () {
1533 // add sortable
1534 this.addSortable(this);
1535
1536 // remove event
1537 this.off('mouseover');
1538 }
1539 });
1540 acf.registerFieldType(Field);
1541
1542 // register existing conditions
1543 acf.registerConditionForFieldType('hasValue', 'gallery');
1544 acf.registerConditionForFieldType('hasNoValue', 'gallery');
1545 acf.registerConditionForFieldType('selectionLessThan', 'gallery');
1546 acf.registerConditionForFieldType('selectionGreaterThan', 'gallery');
1547 })(jQuery);
1548
1549 /***/ }),
1550
1551 /***/ "./assets/src/js/pro/_acf-field-repeater.js":
1552 /*!**************************************************!*\
1553 !*** ./assets/src/js/pro/_acf-field-repeater.js ***!
1554 \**************************************************/
1555 /***/ (() => {
1556
1557 (function ($) {
1558 var Field = acf.Field.extend({
1559 type: 'repeater',
1560 wait: '',
1561 page: 1,
1562 nextRowNum: 0,
1563 events: {
1564 'click a[data-event="add-row"]': 'onClickAdd',
1565 'click a[data-event="duplicate-row"]': 'onClickDuplicate',
1566 'click a[data-event="remove-row"]': 'onClickRemove',
1567 'click a[data-event="collapse-row"]': 'onClickCollapse',
1568 'click a[data-event="first-page"]:not(.disabled)': 'onClickFirstPage',
1569 'click a[data-event="last-page"]:not(.disabled)': 'onClickLastPage',
1570 'click a[data-event="prev-page"]:not(.disabled)': 'onClickPrevPage',
1571 'click a[data-event="next-page"]:not(.disabled)': 'onClickNextPage',
1572 'change .current-page': 'onChangeCurrentPage',
1573 'click .acf-order-input-wrap': 'onClickRowOrder',
1574 'blur .acf-order-input': 'onBlurRowOrder',
1575 'change .acf-order-input': 'onChangeRowOrder',
1576 'changed:total_rows': 'onChangeTotalRows',
1577 showField: 'onShow',
1578 unloadField: 'onUnload',
1579 mouseover: 'onHover',
1580 change: 'onChangeField'
1581 },
1582 $control: function () {
1583 return this.$('.acf-repeater:first');
1584 },
1585 $table: function () {
1586 return this.$('table:first');
1587 },
1588 $tbody: function () {
1589 return this.$('tbody:first');
1590 },
1591 $rows: function () {
1592 return this.$('tbody:first > tr').not('.acf-clone, .acf-deleted');
1593 },
1594 $row: function (index) {
1595 return this.$('tbody:first > tr:eq(' + index + ')');
1596 },
1597 $clone: function () {
1598 return this.$('tbody:first > tr.acf-clone');
1599 },
1600 $actions: function () {
1601 return this.$('.acf-actions:last');
1602 },
1603 $button: function () {
1604 return this.$('.acf-actions:last .button');
1605 },
1606 $firstPageButton: function () {
1607 return this.$('.acf-tablenav:last .first-page');
1608 },
1609 $prevPageButton: function () {
1610 return this.$('.acf-tablenav:last .prev-page');
1611 },
1612 $nextPageButton: function () {
1613 return this.$('.acf-tablenav:last .next-page');
1614 },
1615 $lastPageButton: function () {
1616 return this.$('.acf-tablenav:last .last-page');
1617 },
1618 $pageInput: function () {
1619 return this.$('.current-page:last');
1620 },
1621 totalPages: function () {
1622 const totalPages = this.$('.acf-total-pages:last').text();
1623 return parseInt(totalPages);
1624 },
1625 getValue: function () {
1626 return this.$rows().length;
1627 },
1628 allowRemove: function () {
1629 let numRows = this.val();
1630 let minRows = parseInt(this.get('min'));
1631 if (this.get('pagination')) {
1632 numRows = this.get('total_rows');
1633 }
1634 return !minRows || minRows < numRows;
1635 },
1636 allowAdd: function () {
1637 let numRows = this.val();
1638 let maxRows = parseInt(this.get('max'));
1639 if (this.get('pagination')) {
1640 numRows = this.get('total_rows');
1641 }
1642 return !maxRows || maxRows > numRows;
1643 },
1644 addSortable: function (self) {
1645 // bail early if max 1 row
1646 if (this.get('max') == 1) {
1647 return;
1648 }
1649
1650 // Bail early if using pagination.
1651 if (this.get('pagination')) {
1652 return;
1653 }
1654
1655 // add sortable
1656 this.$tbody().sortable({
1657 items: '> tr',
1658 handle: '> td.order',
1659 zIndex: 9999,
1660 forceHelperSize: true,
1661 forcePlaceholderSize: true,
1662 scroll: true,
1663 stop: function (event, ui) {
1664 self.render();
1665 },
1666 update: function (event, ui) {
1667 self.$input().trigger('change');
1668 }
1669 });
1670 },
1671 addCollapsed: function () {
1672 // vars
1673 var indexes = preference.load(this.get('key'));
1674
1675 // bail early if no collapsed
1676 if (!indexes) {
1677 return false;
1678 }
1679
1680 // loop
1681 this.$rows().each(function (i) {
1682 if (indexes.indexOf(i) > -1) {
1683 if ($(this).find('.-collapsed-target').length) {
1684 $(this).addClass('-collapsed');
1685 }
1686 }
1687 });
1688 },
1689 addUnscopedEvents: function (self) {
1690 // invalidField
1691 this.on('invalidField', '.acf-row', function (e) {
1692 var $row = $(this);
1693 if (self.isCollapsed($row)) {
1694 self.expand($row);
1695 }
1696 });
1697
1698 // Listen for changes to fields, so we can persist them in the DOM.
1699 if (this.get('pagination')) {
1700 this.on('change', 'input, select, textarea', function (e) {
1701 const $changed = $(e.currentTarget);
1702 if (!$changed.hasClass('acf-order-input') && !$changed.hasClass('acf-row-status')) {
1703 self.onChangeField(e, $(this));
1704 }
1705 });
1706 }
1707 this.listenForSavedMetaBoxes();
1708 },
1709 initialize: function () {
1710 // add unscoped events
1711 this.addUnscopedEvents(this);
1712
1713 // add collapsed
1714 this.addCollapsed();
1715
1716 // disable clone
1717 acf.disable(this.$clone(), this.cid);
1718
1719 // Set up the next row number.
1720 if (this.get('pagination')) {
1721 this.nextRowNum = this.get('total_rows');
1722 }
1723
1724 // render
1725 this.render();
1726 },
1727 render: function (update_order_numbers = true) {
1728 // Update order number.
1729 if (update_order_numbers) {
1730 this.$rows().each(function (i) {
1731 $(this).find('> .order > span').html(i + 1);
1732 });
1733 }
1734
1735 // Extract vars.
1736 var $control = this.$control();
1737 var $button = this.$button();
1738
1739 // empty
1740 if (this.val() == 0) {
1741 $control.addClass('-empty');
1742 } else {
1743 $control.removeClass('-empty');
1744 }
1745
1746 // Reached max rows.
1747 if (!this.allowAdd()) {
1748 $control.addClass('-max');
1749 $button.addClass('disabled');
1750 } else {
1751 $control.removeClass('-max');
1752 $button.removeClass('disabled');
1753 }
1754 if (this.get('pagination')) {
1755 this.maybeDisablePagination();
1756 }
1757
1758 // Reached min rows (not used).
1759 //if( !this.allowRemove() ) {
1760 // $control.addClass('-min');
1761 //} else {
1762 // $control.removeClass('-min');
1763 //}
1764 },
1765 listenForSavedMetaBoxes: function () {
1766 if (!acf.isGutenbergPostEditor() || !this.get('pagination')) {
1767 return;
1768 }
1769 let checkedMetaBoxes = true;
1770 wp.data.subscribe(() => {
1771 if (wp.data.select('core/edit-post').isSavingMetaBoxes()) {
1772 checkedMetaBoxes = false;
1773 } else {
1774 if (!checkedMetaBoxes) {
1775 checkedMetaBoxes = true;
1776 this.set('total_rows', 0, true);
1777 this.ajaxLoadPage(true);
1778 }
1779 }
1780 });
1781 },
1782 incrementTotalRows: function () {
1783 let totalRows = this.get('total_rows');
1784 this.set('total_rows', ++totalRows, true);
1785 },
1786 decrementTotalRows: function () {
1787 let totalRows = this.get('total_rows');
1788 this.set('total_rows', --totalRows, true);
1789 },
1790 validateAdd: function () {
1791 // return true if allowed
1792 if (this.allowAdd()) {
1793 return true;
1794 }
1795
1796 // vars
1797 var max = this.get('max');
1798 var text = acf.__('Maximum rows reached ({max} rows)');
1799
1800 // replace
1801 text = text.replace('{max}', max);
1802
1803 // add notice
1804 this.showNotice({
1805 text: text,
1806 type: 'warning'
1807 });
1808
1809 // return
1810 return false;
1811 },
1812 onClickAdd: function (e, $el) {
1813 // validate
1814 if (!this.validateAdd()) {
1815 return false;
1816 }
1817
1818 // add above row
1819 if ($el.hasClass('acf-icon')) {
1820 this.add({
1821 before: $el.closest('.acf-row')
1822 });
1823
1824 // default
1825 } else {
1826 this.add();
1827 }
1828 },
1829 add: function (args) {
1830 // validate
1831 if (!this.allowAdd()) {
1832 return false;
1833 }
1834
1835 // defaults
1836 args = acf.parseArgs(args, {
1837 before: false
1838 });
1839
1840 // add row
1841 var $el = acf.duplicate({
1842 target: this.$clone(),
1843 append: this.proxy(function ($el, $el2) {
1844 // append
1845 if (args.before) {
1846 args.before.before($el2);
1847 } else {
1848 $el.before($el2);
1849 }
1850
1851 // remove clone class
1852 $el2.removeClass('acf-clone');
1853
1854 // enable
1855 acf.enable($el2, this.cid);
1856 })
1857 });
1858 if (this.get('pagination')) {
1859 this.incrementTotalRows();
1860 if (false !== args.before) {
1861 // If the row was inserted above an existing row, try to keep that order.
1862 const prevRowNum = parseInt(args.before.find('.acf-row-number').first().text()) || 0;
1863 let newRowNum = prevRowNum;
1864 if (newRowNum && !args.before.hasClass('acf-inserted') && !args.before.hasClass('acf-added')) {
1865 --newRowNum;
1866 }
1867 if (args.before.hasClass('acf-divider')) {
1868 args.before.removeClass('acf-divider');
1869 $el.addClass('acf-divider');
1870 }
1871 this.updateRowStatus($el, 'inserted');
1872 this.updateRowStatus($el, 'reordered', newRowNum);
1873
1874 // Hide the row numbers to avoid confusion with existing rows.
1875 $el.find('.acf-row-number').first().hide().text(newRowNum);
1876 if (!$el.find('.acf-order-input-wrap').hasClass('disabled')) {
1877 let message = acf.__('Order will be assigned upon save');
1878 $el.find('.acf-order-input-wrap').addClass('disabled');
1879 $el.find('.acf-row-number').first().after('<span title="' + message + '">-</span>');
1880 }
1881 $el.find('.acf-order-input').first().hide();
1882 $el.attr('data-inserted', newRowNum);
1883 } else {
1884 this.nextRowNum++;
1885 $el.find('.acf-order-input').first().val(this.nextRowNum);
1886 $el.find('.acf-row-number').first().text(this.nextRowNum);
1887 this.updateRowStatus($el, 'added');
1888 if (!this.$tbody().find('.acf-divider').length) {
1889 $el.addClass('acf-divider');
1890 }
1891 }
1892 $el.find('.acf-input:first').find('input:not([type=hidden]), select, textarea').first().trigger('focus');
1893 }
1894
1895 // Render and trigger change for validation errors.
1896 this.render();
1897 this.$input().trigger('change');
1898 return $el;
1899 },
1900 onClickDuplicate: function (e, $el) {
1901 // Validate with warning.
1902 if (!this.validateAdd()) {
1903 return false;
1904 }
1905
1906 // get layout and duplicate it.
1907 var $row = $el.closest('.acf-row');
1908 this.duplicateRow($row);
1909 },
1910 duplicateRow: function ($row) {
1911 // Validate without warning.
1912 if (!this.allowAdd()) {
1913 return false;
1914 }
1915
1916 // Vars.
1917 var fieldKey = this.get('key');
1918
1919 // Duplicate row.
1920 var $el = acf.duplicate({
1921 target: $row,
1922 // Provide a custom renaming callback to avoid renaming parent row attributes.
1923 rename: function (name, value, search, replace) {
1924 // Rename id attributes from "field_1-search" to "field_1-replace".
1925 if (name === 'id' || name === 'for') {
1926 return value.replace(fieldKey + '-' + search, fieldKey + '-' + replace);
1927
1928 // Rename name and for attributes from "[field_1][search]" to "[field_1][replace]".
1929 } else {
1930 return value.replace(fieldKey + '][' + search, fieldKey + '][' + replace);
1931 }
1932 },
1933 before: function ($el) {
1934 acf.doAction('unmount', $el);
1935 },
1936 after: function ($el, $el2) {
1937 acf.doAction('remount', $el);
1938 }
1939 });
1940 if (this.get('pagination')) {
1941 this.incrementTotalRows();
1942
1943 // If the row was inserted above an existing row, try to keep that order.
1944 const prevRowNum = parseInt($row.find('.acf-row-number').first().text()) || 0;
1945 this.updateRowStatus($el, 'inserted');
1946 this.updateRowStatus($el, 'reordered', prevRowNum);
1947
1948 // Hide the row numbers to avoid confusion with existing rows.
1949 $el.find('.acf-row-number').first().hide();
1950 if (!$el.find('.acf-order-input-wrap').hasClass('disabled')) {
1951 let message = acf.__('Order will be assigned upon save');
1952 $el.find('.acf-order-input-wrap').addClass('disabled');
1953 $el.find('.acf-row-number').first().after('<span title="' + message + '">-</span>');
1954 }
1955 $el.find('.acf-order-input').first().hide();
1956 $el.attr('data-inserted', prevRowNum);
1957 $el.removeClass('acf-divider');
1958 }
1959
1960 // trigger change for validation errors
1961 this.$input().trigger('change');
1962
1963 // Update order numbers.
1964 this.render();
1965
1966 // Focus on new row.
1967 acf.focusAttention($el);
1968
1969 // Return new layout.
1970 return $el;
1971 },
1972 validateRemove: function () {
1973 // return true if allowed
1974 if (this.allowRemove()) {
1975 return true;
1976 }
1977
1978 // vars
1979 var min = this.get('min');
1980 var text = acf.__('Minimum rows not reached ({min} rows)');
1981
1982 // replace
1983 text = text.replace('{min}', min);
1984
1985 // add notice
1986 this.showNotice({
1987 text: text,
1988 type: 'warning'
1989 });
1990
1991 // return
1992 return false;
1993 },
1994 onClickRemove: function (e, $el) {
1995 var $row = $el.closest('.acf-row');
1996
1997 // Bypass confirmation when holding down "shift" key.
1998 if (e.shiftKey) {
1999 return this.remove($row);
2000 }
2001
2002 // add class
2003 $row.addClass('-hover');
2004
2005 // add tooltip
2006 var tooltip = acf.newTooltip({
2007 confirmRemove: true,
2008 target: $el,
2009 context: this,
2010 confirm: function () {
2011 this.remove($row);
2012 },
2013 cancel: function () {
2014 $row.removeClass('-hover');
2015 }
2016 });
2017 },
2018 onClickRowOrder: function (e, $el) {
2019 if (!this.get('pagination')) {
2020 return;
2021 }
2022 if ($el.hasClass('disabled')) {
2023 return;
2024 }
2025 $el.find('.acf-row-number').hide();
2026 $el.find('.acf-order-input').show().trigger('select');
2027 },
2028 onBlurRowOrder: function (e, $el) {
2029 this.onChangeRowOrder(e, $el, false);
2030 },
2031 onChangeRowOrder: function (e, $el, update = true) {
2032 if (!this.get('pagination')) {
2033 return;
2034 }
2035 const $row = $el.closest('.acf-row');
2036 const $orderSpan = $row.find('.acf-row-number').first();
2037 let hrOrder = $el.val();
2038 $row.find('.acf-order-input').first().hide();
2039 if (!acf.isNumeric(hrOrder) || parseFloat(hrOrder) < 0) {
2040 $orderSpan.show();
2041 return;
2042 }
2043 hrOrder = Math.round(hrOrder);
2044 const newOrder = hrOrder - 1;
2045 $el.val(hrOrder);
2046 $orderSpan.text(hrOrder).show();
2047 if (update) {
2048 this.updateRowStatus($row, 'reordered', newOrder);
2049 }
2050 },
2051 onChangeTotalRows: function () {
2052 const perPage = parseInt(this.get('per_page')) || 20;
2053 const totalRows = parseInt(this.get('total_rows')) || 0;
2054 const totalPages = Math.ceil(totalRows / perPage);
2055
2056 // Update the total pages in pagination.
2057 this.$('.acf-total-pages:last').text(totalPages);
2058 this.nextRowNum = totalRows;
2059
2060 // If the current page no longer exists, load the last page.
2061 if (this.page > totalPages) {
2062 this.page = totalPages;
2063 this.ajaxLoadPage();
2064 }
2065 },
2066 remove: function ($row) {
2067 const self = this;
2068 if (this.get('pagination')) {
2069 this.decrementTotalRows();
2070
2071 // If using pagination and the row had already been saved, just hide the row instead of deleting it.
2072 if ($row.data('id').includes('row-')) {
2073 this.updateRowStatus($row, 'deleted');
2074 $row.hide();
2075 self.$input().trigger('change');
2076 self.render(false);
2077 return;
2078 } else if ($row.hasClass('acf-divider')) {
2079 $row.next('.acf-added').addClass('acf-divider');
2080 }
2081 }
2082
2083 // If not using pagination, delete the actual row.
2084 acf.remove({
2085 target: $row,
2086 endHeight: 0,
2087 complete: function () {
2088 // trigger change to allow attachment save
2089 self.$input().trigger('change');
2090
2091 // render
2092 self.render();
2093
2094 // sync collapsed order
2095 //self.sync();
2096 }
2097 });
2098 },
2099 isCollapsed: function ($row) {
2100 return $row.hasClass('-collapsed');
2101 },
2102 collapse: function ($row) {
2103 $row.addClass('-collapsed');
2104 acf.doAction('hide', $row, 'collapse');
2105 },
2106 expand: function ($row) {
2107 $row.removeClass('-collapsed');
2108 acf.doAction('show', $row, 'collapse');
2109 },
2110 onClickCollapse: function (e, $el) {
2111 // vars
2112 var $row = $el.closest('.acf-row');
2113 var isCollpased = this.isCollapsed($row);
2114
2115 // shift
2116 if (e.shiftKey) {
2117 $row = this.$rows();
2118 }
2119
2120 // toggle
2121 if (isCollpased) {
2122 this.expand($row);
2123 } else {
2124 this.collapse($row);
2125 }
2126 },
2127 onShow: function (e, $el, context) {
2128 // get sub fields
2129 var fields = acf.getFields({
2130 is: ':visible',
2131 parent: this.$el
2132 });
2133
2134 // trigger action
2135 // - ignore context, no need to pass through 'conditional_logic'
2136 // - this is just for fields like google_map to render itself
2137 acf.doAction('show_fields', fields);
2138 },
2139 onUnload: function () {
2140 // vars
2141 var indexes = [];
2142
2143 // loop
2144 this.$rows().each(function (i) {
2145 if ($(this).hasClass('-collapsed')) {
2146 indexes.push(i);
2147 }
2148 });
2149
2150 // allow null
2151 indexes = indexes.length ? indexes : null;
2152
2153 // set
2154 preference.save(this.get('key'), indexes);
2155 },
2156 onHover: function () {
2157 // add sortable
2158 this.addSortable(this);
2159
2160 // remove event
2161 this.off('mouseover');
2162 },
2163 onChangeField: function (e, $el) {
2164 const $target = $(e.delegateTarget);
2165 let $row = $el.closest('.acf-row');
2166 if ($row.closest('.acf-field-repeater').data('key') !== $target.data('key')) {
2167 $row = $row.parent().closest('.acf-row');
2168 }
2169 this.updateRowStatus($row, 'changed');
2170 },
2171 updateRowStatus: function ($row, status, data = true) {
2172 if (!this.get('pagination')) {
2173 return;
2174 }
2175 const parent_key = $row.parents('.acf-field-repeater').data('key');
2176 if (this.parent() && parent_key !== this.get('key')) {
2177 return;
2178 }
2179 const row_id = $row.data('id');
2180 const input_name = this.$el.find('.acf-repeater-hidden-input:first').attr('name');
2181 const status_name = `${input_name}[${row_id}][acf_${status}]`;
2182 const status_input = `<input type="hidden" class="acf-row-status" name="${status_name}" value="${data}" />`;
2183 if (!$row.hasClass('acf-' + status)) {
2184 $row.addClass('acf-' + status);
2185 }
2186
2187 // TODO: Update so that this doesn't get messed up with repeater subfields.
2188 const $existing_status = $row.find(`input[name='${status_name}']`);
2189 if (!$existing_status.length) {
2190 $row.find('td').first().append(status_input);
2191 } else {
2192 $existing_status.val(data);
2193 }
2194 },
2195 onClickFirstPage: function () {
2196 this.validatePage(1);
2197 },
2198 onClickPrevPage: function () {
2199 this.validatePage(this.page - 1);
2200 },
2201 onClickNextPage: function (e) {
2202 this.validatePage(this.page + 1);
2203 },
2204 onClickLastPage: function () {
2205 this.validatePage(this.totalPages());
2206 },
2207 onChangeCurrentPage: function () {
2208 this.validatePage(this.$pageInput().val());
2209 },
2210 maybeDisablePagination: function () {
2211 this.$actions().find('.acf-nav').removeClass('disabled');
2212 if (this.page <= 1) {
2213 this.$firstPageButton().addClass('disabled');
2214 this.$prevPageButton().addClass('disabled');
2215 }
2216 if (this.page >= this.totalPages()) {
2217 this.$nextPageButton().addClass('disabled');
2218 this.$lastPageButton().addClass('disabled');
2219 }
2220 },
2221 validatePage: function (nextPage) {
2222 const self = this;
2223
2224 // Validate the current page.
2225 acf.validateForm({
2226 form: this.$control(),
2227 event: '',
2228 reset: true,
2229 success: function ($form) {
2230 self.page = nextPage;
2231
2232 // Set up some sane defaults.
2233 if (self.page <= 1) {
2234 self.page = 1;
2235 }
2236 if (self.page >= self.totalPages()) {
2237 self.page = self.totalPages();
2238 }
2239 self.ajaxLoadPage();
2240 },
2241 failure: function ($form) {
2242 self.$pageInput().val(self.page);
2243 return false;
2244 }
2245 });
2246 },
2247 ajaxLoadPage: function (clearChanged = false) {
2248 const ajaxData = acf.prepareForAjax({
2249 action: 'acf/ajax/query_repeater',
2250 paged: this.page,
2251 field_key: this.get('key'),
2252 field_name: this.get('orig_name'),
2253 rows_per_page: parseInt(this.get('per_page')),
2254 refresh: clearChanged,
2255 nonce: this.get('nonce')
2256 });
2257 $.ajax({
2258 url: ajaxurl,
2259 method: 'POST',
2260 dataType: 'json',
2261 data: ajaxData,
2262 context: this
2263 }).done(function (response) {
2264 const {
2265 rows
2266 } = response.data;
2267 const $existingRows = this.$tbody().find('> tr');
2268 $existingRows.not('.acf-clone').hide();
2269 if (clearChanged) {
2270 // Remove any existing rows since we are refreshing from the server.
2271 $existingRows.not('.acf-clone').remove();
2272
2273 // Trigger a change in total rows, so we can update pagination.
2274 this.set('total_rows', response.data.total_rows, false);
2275 } else {
2276 $existingRows.not('.acf-changed, .acf-deleted, .acf-reordered, .acf-added, .acf-inserted, .acf-clone').remove();
2277 }
2278 Object.keys(rows).forEach(index => {
2279 let $row = false;
2280 let $unsavedRow = this.$tbody().find('> *[data-id=row-' + index + ']');
2281 let $insertedRow = this.$tbody().find('> *[data-inserted=' + index + ']');
2282
2283 // Unsaved new rows that are inserted into this specific position.
2284 if ($insertedRow.length) {
2285 $insertedRow.appendTo(this.$tbody()).show();
2286 acf.doAction('remount', $insertedRow);
2287 }
2288
2289 // Skip unsaved deleted rows; we don't want to show them again.
2290 if ($unsavedRow.hasClass('acf-deleted')) {
2291 return;
2292 }
2293
2294 // Unsaved edited rows should be moved to correct position.
2295 if ($unsavedRow.length) {
2296 acf.doAction('unmount', $unsavedRow);
2297 $unsavedRow.appendTo(this.$tbody()).show();
2298 acf.doAction('remount', $unsavedRow);
2299 return;
2300 }
2301
2302 // Rows from the server (that haven't been changed or deleted) should be appended and shown.
2303 $row = $(rows[index]);
2304 this.$tbody().append($row).show();
2305 acf.doAction('remount', $row);
2306
2307 // Move clone field back to the right spot.
2308 this.$clone().appendTo(this.$tbody());
2309 });
2310 const $addedRows = this.$tbody().find('.acf-added:hidden');
2311
2312 // If there are any new rows that are still hidden, append them to the bottom.
2313 if ($addedRows.length) {
2314 const self = this;
2315 $addedRows.each(function () {
2316 const $addedRow = $(this);
2317 $addedRow.insertBefore(self.$clone()).show();
2318 acf.doAction('remount', $addedRow);
2319 });
2320 }
2321
2322 // Update the page input.
2323 this.$pageInput().val(this.page);
2324 this.maybeDisablePagination();
2325 }).fail(function (jqXHR, textStatus, errorThrown) {
2326 const error = acf.getXhrError(jqXHR);
2327 let message = acf.__('Error loading page');
2328 if ('' !== error) {
2329 message = `${message}: ${error}`;
2330 }
2331 this.showNotice({
2332 text: message,
2333 type: 'warning'
2334 });
2335 });
2336 }
2337 });
2338 acf.registerFieldType(Field);
2339
2340 // register existing conditions
2341 acf.registerConditionForFieldType('hasValue', 'repeater');
2342 acf.registerConditionForFieldType('hasNoValue', 'repeater');
2343 acf.registerConditionForFieldType('lessThan', 'repeater');
2344 acf.registerConditionForFieldType('greaterThan', 'repeater');
2345
2346 // state
2347 var preference = new acf.Model({
2348 name: 'this.collapsedRows',
2349 key: function (key, context) {
2350 // vars
2351 var count = this.get(key + context) || 0;
2352
2353 // update
2354 count++;
2355 this.set(key + context, count, true);
2356
2357 // modify fieldKey
2358 if (count > 1) {
2359 key += '-' + count;
2360 }
2361
2362 // return
2363 return key;
2364 },
2365 load: function (key) {
2366 // vars
2367 var key = this.key(key, 'load');
2368 var data = acf.getPreference(this.name);
2369
2370 // return
2371 if (data && data[key]) {
2372 return data[key];
2373 } else {
2374 return false;
2375 }
2376 },
2377 save: function (key, value) {
2378 // vars
2379 var key = this.key(key, 'save');
2380 var data = acf.getPreference(this.name) || {};
2381
2382 // delete
2383 if (value === null) {
2384 delete data[key];
2385
2386 // append
2387 } else {
2388 data[key] = value;
2389 }
2390
2391 // allow null
2392 if ($.isEmptyObject(data)) {
2393 data = null;
2394 }
2395
2396 // save
2397 acf.setPreference(this.name, data);
2398 }
2399 });
2400 })(jQuery);
2401
2402 /***/ })
2403
2404 /******/ });
2405 /************************************************************************/
2406 /******/ // The module cache
2407 /******/ var __webpack_module_cache__ = {};
2408 /******/
2409 /******/ // The require function
2410 /******/ function __webpack_require__(moduleId) {
2411 /******/ // Check if module is in cache
2412 /******/ var cachedModule = __webpack_module_cache__[moduleId];
2413 /******/ if (cachedModule !== undefined) {
2414 /******/ return cachedModule.exports;
2415 /******/ }
2416 /******/ // Create a new module (and put it into the cache)
2417 /******/ var module = __webpack_module_cache__[moduleId] = {
2418 /******/ // no module.id needed
2419 /******/ // no module.loaded needed
2420 /******/ exports: {}
2421 /******/ };
2422 /******/
2423 /******/ // Execute the module function
2424 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
2425 /******/
2426 /******/ // Return the exports of the module
2427 /******/ return module.exports;
2428 /******/ }
2429 /******/
2430 /************************************************************************/
2431 /******/ /* webpack/runtime/compat get default export */
2432 /******/ (() => {
2433 /******/ // getDefaultExport function for compatibility with non-harmony modules
2434 /******/ __webpack_require__.n = (module) => {
2435 /******/ var getter = module && module.__esModule ?
2436 /******/ () => (module['default']) :
2437 /******/ () => (module);
2438 /******/ __webpack_require__.d(getter, { a: getter });
2439 /******/ return getter;
2440 /******/ };
2441 /******/ })();
2442 /******/
2443 /******/ /* webpack/runtime/define property getters */
2444 /******/ (() => {
2445 /******/ // define getter functions for harmony exports
2446 /******/ __webpack_require__.d = (exports, definition) => {
2447 /******/ for(var key in definition) {
2448 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
2449 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
2450 /******/ }
2451 /******/ }
2452 /******/ };
2453 /******/ })();
2454 /******/
2455 /******/ /* webpack/runtime/hasOwnProperty shorthand */
2456 /******/ (() => {
2457 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
2458 /******/ })();
2459 /******/
2460 /******/ /* webpack/runtime/make namespace object */
2461 /******/ (() => {
2462 /******/ // define __esModule on exports
2463 /******/ __webpack_require__.r = (exports) => {
2464 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
2465 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2466 /******/ }
2467 /******/ Object.defineProperty(exports, '__esModule', { value: true });
2468 /******/ };
2469 /******/ })();
2470 /******/
2471 /************************************************************************/
2472 var __webpack_exports__ = {};
2473 // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
2474 (() => {
2475 "use strict";
2476 /*!********************************************!*\
2477 !*** ./assets/src/js/pro/acf-pro-input.js ***!
2478 \********************************************/
2479 __webpack_require__.r(__webpack_exports__);
2480 /* harmony import */ var _acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_acf-field-repeater.js */ "./assets/src/js/pro/_acf-field-repeater.js");
2481 /* harmony import */ var _acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0__);
2482 /* harmony import */ var _acf_field_flexible_content_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./_acf-field-flexible-content.js */ "./assets/src/js/pro/_acf-field-flexible-content.js");
2483 /* harmony import */ var _acf_field_flexible_content_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_acf_field_flexible_content_js__WEBPACK_IMPORTED_MODULE_1__);
2484 /* harmony import */ var _acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./_acf-field-gallery.js */ "./assets/src/js/pro/_acf-field-gallery.js");
2485 /* harmony import */ var _acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2__);
2486
2487
2488
2489 })();
2490
2491 /******/ })()
2492 ;
2493 //# sourceMappingURL=acf-pro-input.js.map