PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.9.3
Secure Custom Fields v6.9.3
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-datastore.asset.php 2 months ago acf-datastore.js 2 months ago acf-datastore.js.map 2 months ago acf-datastore.min.asset.php 2 months ago acf-datastore.min.js 2 months ago acf-field-bindings.asset.php 2 months ago acf-field-bindings.js 2 months ago acf-field-bindings.js.map 2 months ago acf-field-bindings.min.asset.php 2 months ago acf-field-bindings.min.js 2 months ago acf-pro-blocks.asset.php 3 weeks ago acf-pro-blocks.js 3 weeks ago acf-pro-blocks.js.map 3 weeks ago acf-pro-blocks.min.asset.php 3 weeks ago acf-pro-blocks.min.js 3 weeks ago acf-pro-field-group.asset.php 11 months ago acf-pro-field-group.js 11 months 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 1 month ago acf-pro-input.js 1 month ago acf-pro-input.js.map 1 month ago acf-pro-input.min.asset.php 1 month ago acf-pro-input.min.js 1 month 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
2512 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 nonce: this.get('nonce')
665 };
666
667 // ajax
668 $.ajax({
669 url: acf.get('ajaxurl'),
670 data: acf.prepareForAjax(ajaxData),
671 dataType: 'html',
672 type: 'post',
673 success: function (html) {
674 if (html) {
675 if ($layout.data('renamed') === 1) {
676 $layout.find('.acf-fc-layout-original-title').first().html(`(${html})`);
677 } else {
678 $layout.find('.acf-fc-layout-title').first().html(html);
679 }
680 }
681 }
682 });
683 },
684 onUnload: function () {
685 var indexes = [];
686
687 // loop
688 this.$layouts().each(function (i) {
689 if ($(this).hasClass('-collapsed')) {
690 indexes.push(i);
691 }
692 });
693
694 // allow null
695 indexes = indexes.length ? indexes : null;
696
697 // set
698 preference.save(this.get('key'), indexes);
699 },
700 onInvalidField: function (e, $layout) {
701 // open if is collapsed
702 if (this.isLayoutClosed($layout)) {
703 this.openLayout($layout);
704 }
705 },
706 onHover: function () {
707 // add sortable
708 this.addSortable(this);
709
710 // remove event
711 this.off('mouseover');
712 }
713 });
714 acf.registerFieldType(Field);
715
716 /**
717 * Popup
718 *
719 * description
720 *
721 * @date 7/4/18
722 * @since ACF 5.6.9
723 *
724 * @param type $var Description. Default.
725 * @return type Description.
726 */
727
728 var Popup = acf.models.TooltipConfirm.extend({
729 events: {
730 'click [data-layout]': 'onConfirm',
731 'click [data-event="cancel"]': 'onCancel'
732 },
733 render: function () {
734 // set HTML
735 this.html(this.get('text'));
736
737 // add class
738 this.$el.addClass('acf-fc-popup');
739 this.position();
740 },
741 show: function () {
742 $('body').append(this.$el);
743 },
744 position: function () {
745 const $popup = this.$el;
746 const $target = this.get('target');
747 const $container = $target.closest('.acf-flexible-content');
748 positionPopup($popup, $target, $container, 8);
749 }
750 }); /**
751 * MoreLayoutActionsPopup
752 *
753 * Popup for showing more layout actions (remove, toggle, rename)
754 */
755 const MoreLayoutActionsPopup = acf.models.TooltipConfirm.extend({
756 events: {
757 'click [data-action]': 'onConfirm',
758 'keydown [role="menu"]': 'onKeyDown'
759 },
760 render: function () {
761 const $layout = this.get('target').closest('.layout');
762 this.html(this.get('text'));
763 this.$el.addClass('acf-fc-popup acf-more-layout-actions');
764
765 // Add enable-layout class if layout is disabled
766 if ($layout.attr('data-enabled') === '0') {
767 this.$el.addClass('enable-layout');
768 } else {
769 this.$el.removeClass('enable-layout');
770 }
771 const context = this.get('context') || this;
772 const self = this;
773 setTimeout(function () {
774 self.$el.find('a').first().trigger('focus');
775 context.maybeDisableAddLayout();
776 }, 1);
777 },
778 show: function () {
779 $('body').append(this.$el);
780 },
781 position: function () {
782 const $popup = this.$el;
783 const $target = this.get('target');
784 const $container = $target.closest('.layout');
785 positionPopup($popup, $target, $container, 2);
786 },
787 onKeyDown: function (event, $el) {
788 if (['ArrowDown', 'ArrowUp', 'Escape', 'Tab'].indexOf(event.key) === -1) {
789 return;
790 }
791 event.preventDefault();
792 if (event.key === 'Escape') {
793 return void this.onCancel(event, $el);
794 }
795 const $menuItems = this.$el.find('[role="menu"]').find('[role="menuitem"]:visible');
796 const $activeElement = $(document.activeElement);
797 const menuItemsLength = $menuItems.length;
798 let currentIndex = $menuItems.index($activeElement);
799 let nextIndex;
800 if (event.key === 'ArrowDown' || event.key === 'Tab' && !event.shiftKey) {
801 nextIndex = (currentIndex + 1) % menuItemsLength;
802 } else {
803 nextIndex = (currentIndex - 1 + menuItemsLength) % menuItemsLength;
804 }
805 $menuItems.eq(nextIndex).trigger('focus');
806 }
807 });
808
809 /**
810 * RenameLayoutPopup
811 *
812 * Popup dialog for renaming layout labels
813 */
814 const RenameLayoutPopup = acf.models.PopupConfirm.extend({
815 events: {
816 'click [data-event="close"]': 'onCancel',
817 'click .acf-close-popup': 'onClickClose',
818 keydown: 'onPressEscapeClose',
819 'click [data-event="confirm"]': 'onConfirm',
820 'click .acf-reset-label': 'onReset',
821 'submit .acf-rename-layout-form': 'onConfirm'
822 },
823 tmpl: function () {
824 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>`;
825 return `
826 <div id="acf-popup" role="dialog" aria-labelledby="acf-rename-layout-title" tabindex="-1">
827 <div class="acf-popup-box acf-box acf-confirm-popup acf-rename-layout-popup">
828 <div class="title">
829 <h3 id="acf-rename-layout-title">${this.get('title')}</h3>
830 <a href="#" data-event="close" aria-label="${acf.strEscape(acf.__('Close modal'))}">
831 <i class="acf-icon -close"></i>
832 </a>
833 </div>
834 <form class="inner acf-rename-layout-form">
835 <div class="acf-field">
836 <div class="acf-label">
837 <label for="acf-new-layout-label">${acf.strEscape(acf.__('New Label'))}</label>
838 </div>
839 <div class="acf-input">
840 <input id="acf-new-layout-label" type="text" name="acf_new_layout_label" value="">
841 </div>
842 </div>
843 <div class="acf-actions">
844 ${resetButton}
845 <button type="button" data-event="close" class="acf-btn acf-btn-secondary acf-close-popup">${acf.strEscape(this.get('textCancel'))}</button>
846 <button type="submit" data-event="confirm" class="acf-btn acf-btn-primary acf-confirm">${acf.strEscape(this.get('textConfirm'))}</button>
847 </div>
848 </form>
849 </div>
850 <div class="bg" data-event="close"></div>
851 </div>`;
852 },
853 render: function () {
854 acf.models.PopupConfirm.prototype.render.apply(this, arguments);
855 setTimeout(() => {
856 const $input = this.$el.find('input#acf-new-layout-label');
857 $input.val(this.get('currentName'));
858 const textLength = $input.val().length;
859 $input.trigger('focus');
860 $input[0].setSelectionRange(textLength, textLength);
861 }, 1);
862 },
863 onConfirm: function (event, $el) {
864 event.preventDefault();
865 event.stopPropagation();
866 const newName = this.$el.find('input#acf-new-layout-label').val();
867 this.close();
868 const confirmCallback = this.get('confirm');
869 const context = this.get('context') || this;
870 confirmCallback.apply(context, [event, $el, newName]);
871 },
872 onReset: function (event, $el) {
873 event.preventDefault();
874 event.stopPropagation();
875 this.$el.find('input#acf-new-layout-label').val('');
876 this.onConfirm(event, $el);
877 }
878 });
879
880 /**
881 * positionPopup
882 *
883 * Utility function to position popup relative to target within container
884 */
885 const positionPopup = function ($popup, $target, $container, offset) {
886 if (!$target.length || !$container.length) return;
887 const targetOffset = $target.offset();
888 const targetWidth = $target.outerWidth();
889 const targetHeight = $target.outerHeight();
890 const popupWidth = $popup.outerWidth();
891 const popupHeight = $popup.outerHeight();
892 const isRTL = $('body').hasClass('rtl');
893 const windowScrollTop = $(window).scrollTop();
894 const windowHeight = $(window).height();
895 let left, positionClass;
896 let top = targetOffset.top + targetHeight + offset;
897 let isAbove = false;
898
899 // Check if popup would be cut off at bottom of viewport
900 if (targetOffset.top + targetHeight + popupHeight + offset > windowScrollTop + windowHeight && targetOffset.top - popupHeight - offset > windowScrollTop) {
901 top = targetOffset.top - popupHeight - offset;
902 isAbove = true;
903 }
904 if (isRTL) {
905 left = targetOffset.left;
906 positionClass = isAbove ? 'bottom-left' : 'top-left';
907 } else {
908 left = targetOffset.left + targetWidth - popupWidth;
909 positionClass = isAbove ? 'bottom-right' : 'top-right';
910 }
911 $popup.removeClass('top-right bottom-right top-left bottom-left').css({
912 position: 'absolute',
913 top: top,
914 left: left
915 }).addClass(positionClass);
916 }; /**
917 * conditions
918 *
919 * description
920 *
921 * @date 9/4/18
922 * @since ACF 5.6.9
923 *
924 * @param type $var Description. Default.
925 * @return type Description.
926 */
927
928 // register existing conditions
929 acf.registerConditionForFieldType('hasValue', 'flexible_content');
930 acf.registerConditionForFieldType('hasNoValue', 'flexible_content');
931 acf.registerConditionForFieldType('lessThan', 'flexible_content');
932 acf.registerConditionForFieldType('greaterThan', 'flexible_content');
933
934 // state
935 var preference = new acf.Model({
936 name: 'this.collapsedLayouts',
937 key: function (key, context) {
938 var count = this.get(key + context) || 0;
939
940 // update
941 count++;
942 this.set(key + context, count, true);
943
944 // modify fieldKey
945 if (count > 1) {
946 key += '-' + count;
947 }
948 return key;
949 },
950 load: function (key) {
951 var key = this.key(key, 'load');
952 var data = acf.getPreference(this.name);
953 if (data && data[key]) {
954 return data[key];
955 } else {
956 return false;
957 }
958 },
959 save: function (key, value) {
960 var key = this.key(key, 'save');
961 var data = acf.getPreference(this.name) || {};
962
963 // delete
964 if (value === null) {
965 delete data[key];
966
967 // append
968 } else {
969 data[key] = value;
970 }
971
972 // allow null
973 if ($.isEmptyObject(data)) {
974 data = null;
975 }
976
977 // save
978 acf.setPreference(this.name, data);
979 }
980 });
981 })(jQuery);
982
983 /***/ }),
984
985 /***/ "./assets/src/js/pro/_acf-field-gallery.js":
986 /*!*************************************************!*\
987 !*** ./assets/src/js/pro/_acf-field-gallery.js ***!
988 \*************************************************/
989 /***/ (() => {
990
991 (function ($) {
992 var Field = acf.Field.extend({
993 type: 'gallery',
994 events: {
995 'click .acf-gallery-add': 'onClickAdd',
996 'click .acf-gallery-edit': 'onClickEdit',
997 'click .acf-gallery-remove': 'onClickRemove',
998 'click .acf-gallery-attachment': 'onClickSelect',
999 'click .acf-gallery-close': 'onClickClose',
1000 'change .acf-gallery-sort': 'onChangeSort',
1001 'click .acf-gallery-update': 'onUpdate',
1002 mouseover: 'onHover',
1003 showField: 'render'
1004 },
1005 actions: {
1006 validation_begin: 'onValidationBegin',
1007 validation_failure: 'onValidationFailure',
1008 resize: 'onResize'
1009 },
1010 onValidationBegin: function () {
1011 acf.disable(this.$sideData(), this.cid);
1012 },
1013 onValidationFailure: function () {
1014 acf.enable(this.$sideData(), this.cid);
1015 },
1016 $control: function () {
1017 return this.$('.acf-gallery');
1018 },
1019 $collection: function () {
1020 return this.$('.acf-gallery-attachments');
1021 },
1022 $attachments: function () {
1023 return this.$('.acf-gallery-attachment');
1024 },
1025 $attachment: function (id) {
1026 return this.$attachments().filter(function () {
1027 return String($(this).data('id')) === String(id);
1028 });
1029 },
1030 $active: function () {
1031 return this.$('.acf-gallery-attachment.active');
1032 },
1033 $main: function () {
1034 return this.$('.acf-gallery-main');
1035 },
1036 $side: function () {
1037 return this.$('.acf-gallery-side');
1038 },
1039 $sideData: function () {
1040 return this.$('.acf-gallery-side-data');
1041 },
1042 isFull: function () {
1043 var max = parseInt(this.get('max'));
1044 var count = this.$attachments().length;
1045 return max && count >= max;
1046 },
1047 getValue: function () {
1048 // vars
1049 var val = [];
1050
1051 // loop
1052 this.$attachments().each(function () {
1053 val.push($(this).data('id'));
1054 });
1055
1056 // return
1057 return val.length ? val : false;
1058 },
1059 setValue: function (value) {
1060 if (!Array.isArray(value)) {
1061 value = value ? [value] : [];
1062 }
1063 this.closeSidebar();
1064 this.$attachments().remove();
1065 value.forEach(id => {
1066 this.appendAttachment({
1067 id
1068 });
1069 });
1070 this.render();
1071 },
1072 addUnscopedEvents: function (self) {
1073 // invalidField
1074 this.on('change', '.acf-gallery-side', function (e) {
1075 self.onUpdate(e, $(this));
1076 });
1077 },
1078 addSortable: function (self) {
1079 // add sortable
1080 this.$collection().sortable({
1081 items: '.acf-gallery-attachment',
1082 forceHelperSize: true,
1083 zIndex: 9999,
1084 forcePlaceholderSize: true,
1085 scroll: true,
1086 start: function (event, ui) {
1087 ui.placeholder.html(ui.item.html());
1088 ui.placeholder.removeAttr('style');
1089 },
1090 update: function (event, ui) {
1091 self.$input().trigger('change');
1092 }
1093 });
1094
1095 // resizable
1096 this.$control().resizable({
1097 handles: 's',
1098 minHeight: 200,
1099 stop: function (event, ui) {
1100 acf.update_user_setting('gallery_height', ui.size.height);
1101 }
1102 });
1103 },
1104 initialize: function () {
1105 // add unscoped events
1106 this.addUnscopedEvents(this);
1107
1108 // render
1109 this.render();
1110 },
1111 render: function () {
1112 // vars
1113 var $sort = this.$('.acf-gallery-sort');
1114 var $add = this.$('.acf-gallery-add');
1115 var count = this.$attachments().length;
1116
1117 // disable add
1118 if (this.isFull()) {
1119 $add.addClass('disabled');
1120 } else {
1121 $add.removeClass('disabled');
1122 }
1123
1124 // disable select
1125 if (!count) {
1126 $sort.addClass('disabled');
1127 } else {
1128 $sort.removeClass('disabled');
1129 }
1130
1131 // resize
1132 this.resize();
1133 },
1134 resize: function () {
1135 // vars
1136 var width = this.$control().width();
1137 var target = 150;
1138 var columns = Math.round(width / target);
1139
1140 // max columns = 8
1141 columns = Math.min(columns, 8);
1142
1143 // update data
1144 this.$control().attr('data-columns', columns);
1145 },
1146 onResize: function () {
1147 this.resize();
1148 },
1149 openSidebar: function () {
1150 // add class
1151 this.$control().addClass('-open');
1152
1153 // hide bulk actions
1154 // should be done with CSS
1155 //this.$main().find('.acf-gallery-sort').hide();
1156
1157 // vars
1158 var width = this.$control().width() / 3;
1159 width = parseInt(width);
1160 width = Math.max(width, 350);
1161
1162 // animate
1163 this.$('.acf-gallery-side-inner').css({
1164 width: width - 1
1165 });
1166 this.$side().animate({
1167 width: width - 1
1168 }, 250);
1169 this.$main().animate({
1170 right: width
1171 }, 250);
1172 },
1173 closeSidebar: function () {
1174 // remove class
1175 this.$control().removeClass('-open');
1176
1177 // clear selection
1178 this.$active().removeClass('active');
1179
1180 // disable sidebar
1181 acf.disable(this.$side());
1182
1183 // animate
1184 var $sideData = this.$('.acf-gallery-side-data');
1185 this.$main().animate({
1186 right: 0
1187 }, 250);
1188 this.$side().animate({
1189 width: 0
1190 }, 250, function () {
1191 $sideData.html('');
1192 });
1193 },
1194 onClickAdd: function (e, $el) {
1195 // validate
1196 if (this.isFull()) {
1197 this.showNotice({
1198 text: acf.__('Maximum selection reached'),
1199 type: 'warning'
1200 });
1201 return;
1202 }
1203
1204 // new frame
1205 var frame = acf.newMediaPopup({
1206 mode: 'select',
1207 title: acf.__('Add Image to Gallery'),
1208 field: this.get('key'),
1209 multiple: 'add',
1210 library: this.get('library'),
1211 allowedTypes: this.get('mime_types'),
1212 selected: this.val(),
1213 select: $.proxy(function (attachment, i) {
1214 this.appendAttachment(attachment, i);
1215 }, this)
1216 });
1217 },
1218 appendAttachment: function (attachment, i) {
1219 // vars
1220 attachment = this.validateAttachment(attachment);
1221
1222 // bail early if is full
1223 if (this.isFull()) {
1224 return;
1225 }
1226
1227 // bail early if already exists
1228 if (this.$attachment(attachment.id).length) {
1229 return;
1230 }
1231
1232 // html
1233 const escapedId = acf.strEscape(String(attachment.id));
1234 var html = ['<div class="acf-gallery-attachment" data-id="' + escapedId + '">', '<input type="hidden" value="' + escapedId + '" 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="' + escapedId + '"></a>', '</div>', '</div>'].join('');
1235 var $html = $(html);
1236
1237 // append
1238 this.$collection().append($html);
1239
1240 // move to beginning
1241 if (this.get('insert') === 'prepend') {
1242 var $before = this.$attachments().eq(i);
1243 if ($before.length) {
1244 $before.before($html);
1245 }
1246 }
1247
1248 // render attachment
1249 this.renderAttachment(attachment);
1250
1251 // render
1252 this.render();
1253
1254 // trigger change
1255 this.$input().trigger('change');
1256 },
1257 validateAttachment: function (attachment) {
1258 // defaults
1259 attachment = acf.parseArgs(attachment, {
1260 id: '',
1261 url: '',
1262 alt: '',
1263 title: '',
1264 filename: '',
1265 type: 'image'
1266 });
1267
1268 // WP attachment
1269 if (attachment.attributes) {
1270 attachment = attachment.attributes;
1271
1272 // preview size
1273 var url = acf.isget(attachment, 'sizes', this.get('preview_size'), 'url');
1274 if (url !== null) {
1275 attachment.url = url;
1276 }
1277 }
1278
1279 // return
1280 return attachment;
1281 },
1282 renderAttachment: function (attachment) {
1283 // vars
1284 attachment = this.validateAttachment(attachment);
1285
1286 // vars
1287 var $el = this.$attachment(attachment.id);
1288
1289 // Image type.
1290 if (attachment.type == 'image') {
1291 // Remove filename.
1292 $el.find('.filename').remove();
1293
1294 // Other file type.
1295 } else {
1296 // Check for attachment featured image.
1297 var image = acf.isget(attachment, 'image', 'src');
1298 if (image !== null) {
1299 attachment.url = image;
1300 }
1301
1302 // Update filename text.
1303 $el.find('.filename').text(attachment.filename);
1304 }
1305
1306 // Default to mimetype icon.
1307 if (!attachment.url) {
1308 attachment.url = acf.get('mimeTypeIcon');
1309 $el.addClass('-icon');
1310 }
1311
1312 // update els
1313 $el.find('img').attr({
1314 src: attachment.url,
1315 alt: attachment.alt,
1316 title: attachment.title
1317 });
1318
1319 // update val
1320 acf.val($el.find('input'), attachment.id);
1321 },
1322 editAttachment: function (id) {
1323 // new frame
1324 var frame = acf.newMediaPopup({
1325 mode: 'edit',
1326 title: acf.__('Edit Image'),
1327 button: acf.__('Update Image'),
1328 attachment: id,
1329 field: this.get('key'),
1330 select: $.proxy(function (attachment, i) {
1331 this.renderAttachment(attachment);
1332 // todo - render sidebar
1333 }, this)
1334 });
1335 },
1336 onClickEdit: function (e, $el) {
1337 var id = $el.data('id');
1338 if (id) {
1339 this.editAttachment(id);
1340 }
1341 },
1342 removeAttachment: function (id) {
1343 // close sidebar (if open)
1344 this.closeSidebar();
1345
1346 // remove attachment
1347 this.$attachment(id).remove();
1348
1349 // render
1350 this.render();
1351
1352 // trigger change
1353 this.$input().trigger('change');
1354 },
1355 onClickRemove: function (e, $el) {
1356 // prevent event from triggering click on attachment
1357 e.preventDefault();
1358 e.stopPropagation();
1359
1360 //remove
1361 var id = $el.data('id');
1362 if (id) {
1363 this.removeAttachment(id);
1364 }
1365 },
1366 selectAttachment: function (id) {
1367 // vars
1368 var $el = this.$attachment(id);
1369
1370 // bail early if already active
1371 if ($el.hasClass('active')) {
1372 return;
1373 }
1374
1375 // step 1
1376 var step1 = this.proxy(function () {
1377 // save any changes in sidebar
1378 this.$side().find(':focus').trigger('blur');
1379
1380 // clear selection
1381 this.$active().removeClass('active');
1382
1383 // add selection
1384 $el.addClass('active');
1385
1386 // open sidebar
1387 this.openSidebar();
1388
1389 // call step 2
1390 step2();
1391 });
1392
1393 // step 2
1394 var step2 = this.proxy(function () {
1395 const ajaxData = {
1396 action: 'acf/fields/gallery/get_attachment',
1397 nonce: this.get('nonce'),
1398 field_key: this.get('key'),
1399 id: id
1400 };
1401
1402 // abort prev ajax call
1403 if (this.has('xhr')) {
1404 this.get('xhr').abort();
1405 }
1406
1407 // loading
1408 acf.showLoading(this.$sideData());
1409
1410 // get HTML
1411 var xhr = $.ajax({
1412 url: acf.get('ajaxurl'),
1413 data: acf.prepareForAjax(ajaxData),
1414 type: 'post',
1415 dataType: 'html',
1416 cache: false,
1417 success: step3
1418 });
1419
1420 // update
1421 this.set('xhr', xhr);
1422 });
1423
1424 // step 3
1425 var step3 = this.proxy(function (html) {
1426 // bail early if no html
1427 if (!html) {
1428 return;
1429 }
1430
1431 // vars
1432 var $side = this.$sideData();
1433
1434 // render
1435 $side.html(html);
1436
1437 // remove acf form data
1438 $side.find('.compat-field-acf-form-data').remove();
1439
1440 // merge tables
1441 $side.find('> table.form-table > tbody').append($side.find('> .compat-attachment-fields > tbody > tr'));
1442
1443 // setup fields
1444 acf.doAction('append', $side);
1445 });
1446
1447 // run step 1
1448 step1();
1449 },
1450 onClickSelect: function (e, $el) {
1451 var id = $el.data('id');
1452 if (id) {
1453 this.selectAttachment(id);
1454 }
1455 },
1456 onClickClose: function (e, $el) {
1457 this.closeSidebar();
1458 },
1459 onChangeSort: function (e, $el) {
1460 // Bail early if is disabled.
1461 if ($el.hasClass('disabled')) {
1462 return;
1463 }
1464
1465 // Get sort val.
1466 var val = $el.val();
1467 if (!val) {
1468 return;
1469 }
1470
1471 // find ids
1472 var ids = [];
1473 this.$attachments().each(function () {
1474 ids.push($(this).data('id'));
1475 });
1476
1477 // step 1
1478 var step1 = this.proxy(function () {
1479 const ajaxData = {
1480 action: 'acf/fields/gallery/get_sort_order',
1481 nonce: this.get('nonce'),
1482 field_key: this.get('key'),
1483 ids: ids,
1484 sort: val
1485 };
1486
1487 // get results
1488 var xhr = $.ajax({
1489 url: acf.get('ajaxurl'),
1490 dataType: 'json',
1491 type: 'post',
1492 cache: false,
1493 data: acf.prepareForAjax(ajaxData),
1494 success: step2
1495 });
1496 });
1497
1498 // step 2
1499 var step2 = this.proxy(function (json) {
1500 // validate
1501 if (!acf.isAjaxSuccess(json)) {
1502 return;
1503 }
1504
1505 // reverse order
1506 json.data.reverse();
1507
1508 // loop
1509 json.data.map(function (id) {
1510 this.$collection().prepend(this.$attachment(id));
1511 }, this);
1512 });
1513
1514 // call step 1
1515 step1();
1516 },
1517 onUpdate: function (e, $el) {
1518 // vars
1519 var $submit = this.$('.acf-gallery-update');
1520
1521 // validate
1522 if ($submit.hasClass('disabled')) {
1523 return;
1524 }
1525
1526 // serialize data
1527 const ajaxData = acf.serialize(this.$sideData());
1528
1529 // loading
1530 $submit.addClass('disabled');
1531 $submit.before('<i class="acf-loading"></i> ');
1532
1533 // Append AJAX action and nonce.
1534 ajaxData.action = 'acf/fields/gallery/update_attachment';
1535 ajaxData.nonce = this.get('nonce');
1536 ajaxData.field_key = this.get('key');
1537
1538 // ajax
1539 $.ajax({
1540 url: acf.get('ajaxurl'),
1541 data: acf.prepareForAjax(ajaxData),
1542 type: 'post',
1543 dataType: 'json',
1544 complete: function () {
1545 $submit.removeClass('disabled');
1546 $submit.prev('.acf-loading').remove();
1547 }
1548 });
1549 },
1550 onHover: function () {
1551 // add sortable
1552 this.addSortable(this);
1553
1554 // remove event
1555 this.off('mouseover');
1556 }
1557 });
1558 acf.registerFieldType(Field);
1559
1560 // register existing conditions
1561 acf.registerConditionForFieldType('hasValue', 'gallery');
1562 acf.registerConditionForFieldType('hasNoValue', 'gallery');
1563 acf.registerConditionForFieldType('selectionLessThan', 'gallery');
1564 acf.registerConditionForFieldType('selectionGreaterThan', 'gallery');
1565 })(jQuery);
1566
1567 /***/ }),
1568
1569 /***/ "./assets/src/js/pro/_acf-field-repeater.js":
1570 /*!**************************************************!*\
1571 !*** ./assets/src/js/pro/_acf-field-repeater.js ***!
1572 \**************************************************/
1573 /***/ (() => {
1574
1575 (function ($) {
1576 var Field = acf.Field.extend({
1577 type: 'repeater',
1578 wait: '',
1579 page: 1,
1580 nextRowNum: 0,
1581 events: {
1582 'click a[data-event="add-row"]': 'onClickAdd',
1583 'click a[data-event="duplicate-row"]': 'onClickDuplicate',
1584 'click a[data-event="remove-row"]': 'onClickRemove',
1585 'click a[data-event="collapse-row"]': 'onClickCollapse',
1586 'click a[data-event="first-page"]:not(.disabled)': 'onClickFirstPage',
1587 'click a[data-event="last-page"]:not(.disabled)': 'onClickLastPage',
1588 'click a[data-event="prev-page"]:not(.disabled)': 'onClickPrevPage',
1589 'click a[data-event="next-page"]:not(.disabled)': 'onClickNextPage',
1590 'change .current-page': 'onChangeCurrentPage',
1591 'click .acf-order-input-wrap': 'onClickRowOrder',
1592 'blur .acf-order-input': 'onBlurRowOrder',
1593 'change .acf-order-input': 'onChangeRowOrder',
1594 'changed:total_rows': 'onChangeTotalRows',
1595 showField: 'onShow',
1596 unloadField: 'onUnload',
1597 mouseover: 'onHover',
1598 change: 'onChangeField'
1599 },
1600 $control: function () {
1601 return this.$('.acf-repeater:first');
1602 },
1603 $table: function () {
1604 return this.$('table:first');
1605 },
1606 $tbody: function () {
1607 return this.$('tbody:first');
1608 },
1609 $rows: function () {
1610 return this.$('tbody:first > tr').not('.acf-clone, .acf-deleted');
1611 },
1612 $row: function (index) {
1613 return this.$('tbody:first > tr:eq(' + index + ')');
1614 },
1615 $clone: function () {
1616 return this.$('tbody:first > tr.acf-clone');
1617 },
1618 $actions: function () {
1619 return this.$('.acf-actions:last');
1620 },
1621 $button: function () {
1622 return this.$('.acf-actions:last .button');
1623 },
1624 $firstPageButton: function () {
1625 return this.$('.acf-tablenav:last .first-page');
1626 },
1627 $prevPageButton: function () {
1628 return this.$('.acf-tablenav:last .prev-page');
1629 },
1630 $nextPageButton: function () {
1631 return this.$('.acf-tablenav:last .next-page');
1632 },
1633 $lastPageButton: function () {
1634 return this.$('.acf-tablenav:last .last-page');
1635 },
1636 $pageInput: function () {
1637 return this.$('.current-page:last');
1638 },
1639 totalPages: function () {
1640 const totalPages = this.$('.acf-total-pages:last').text();
1641 return parseInt(totalPages);
1642 },
1643 getValue: function () {
1644 return this.$rows().length;
1645 },
1646 allowRemove: function () {
1647 let numRows = this.val();
1648 let minRows = parseInt(this.get('min'));
1649 if (this.get('pagination')) {
1650 numRows = this.get('total_rows');
1651 }
1652 return !minRows || minRows < numRows;
1653 },
1654 allowAdd: function () {
1655 let numRows = this.val();
1656 let maxRows = parseInt(this.get('max'));
1657 if (this.get('pagination')) {
1658 numRows = this.get('total_rows');
1659 }
1660 return !maxRows || maxRows > numRows;
1661 },
1662 addSortable: function (self) {
1663 // bail early if max 1 row
1664 if (this.get('max') == 1) {
1665 return;
1666 }
1667
1668 // Bail early if using pagination.
1669 if (this.get('pagination')) {
1670 return;
1671 }
1672
1673 // add sortable
1674 this.$tbody().sortable({
1675 items: '> tr',
1676 handle: '> td.order',
1677 zIndex: 9999,
1678 forceHelperSize: true,
1679 forcePlaceholderSize: true,
1680 scroll: true,
1681 stop: function (event, ui) {
1682 self.render();
1683 },
1684 update: function (event, ui) {
1685 self.$input().trigger('change');
1686 }
1687 });
1688 },
1689 addCollapsed: function () {
1690 // vars
1691 var indexes = preference.load(this.get('key'));
1692
1693 // bail early if no collapsed
1694 if (!indexes) {
1695 return false;
1696 }
1697
1698 // loop
1699 this.$rows().each(function (i) {
1700 if (indexes.indexOf(i) > -1) {
1701 if ($(this).find('.-collapsed-target').length) {
1702 $(this).addClass('-collapsed');
1703 }
1704 }
1705 });
1706 },
1707 addUnscopedEvents: function (self) {
1708 // invalidField
1709 this.on('invalidField', '.acf-row', function (e) {
1710 var $row = $(this);
1711 if (self.isCollapsed($row)) {
1712 self.expand($row);
1713 }
1714 });
1715
1716 // Listen for changes to fields, so we can persist them in the DOM.
1717 if (this.get('pagination')) {
1718 this.on('change', 'input, select, textarea', function (e) {
1719 const $changed = $(e.currentTarget);
1720 if (!$changed.hasClass('acf-order-input') && !$changed.hasClass('acf-row-status')) {
1721 self.onChangeField(e, $(this));
1722 }
1723 });
1724 }
1725 this.listenForSavedMetaBoxes();
1726 },
1727 initialize: function () {
1728 // add unscoped events
1729 this.addUnscopedEvents(this);
1730
1731 // add collapsed
1732 this.addCollapsed();
1733
1734 // disable clone
1735 acf.disable(this.$clone(), this.cid);
1736
1737 // Set up the next row number.
1738 if (this.get('pagination')) {
1739 this.nextRowNum = this.get('total_rows');
1740 }
1741
1742 // render
1743 this.render();
1744 },
1745 render: function (update_order_numbers = true) {
1746 // Update order number.
1747 if (update_order_numbers) {
1748 this.$rows().each(function (i) {
1749 $(this).find('> .order > span').html(i + 1);
1750 });
1751 }
1752
1753 // Extract vars.
1754 var $control = this.$control();
1755 var $button = this.$button();
1756
1757 // empty
1758 if (this.val() == 0) {
1759 $control.addClass('-empty');
1760 } else {
1761 $control.removeClass('-empty');
1762 }
1763
1764 // Reached max rows.
1765 if (!this.allowAdd()) {
1766 $control.addClass('-max');
1767 $button.addClass('disabled');
1768 } else {
1769 $control.removeClass('-max');
1770 $button.removeClass('disabled');
1771 }
1772 if (this.get('pagination')) {
1773 this.maybeDisablePagination();
1774 }
1775
1776 // Reached min rows (not used).
1777 //if( !this.allowRemove() ) {
1778 // $control.addClass('-min');
1779 //} else {
1780 // $control.removeClass('-min');
1781 //}
1782 },
1783 listenForSavedMetaBoxes: function () {
1784 if (!acf.isGutenbergPostEditor() || !this.get('pagination')) {
1785 return;
1786 }
1787 let checkedMetaBoxes = true;
1788 wp.data.subscribe(() => {
1789 if (wp.data.select('core/edit-post').isSavingMetaBoxes()) {
1790 checkedMetaBoxes = false;
1791 } else {
1792 if (!checkedMetaBoxes) {
1793 checkedMetaBoxes = true;
1794 this.set('total_rows', 0, true);
1795 this.ajaxLoadPage(true);
1796 }
1797 }
1798 });
1799 },
1800 incrementTotalRows: function () {
1801 let totalRows = this.get('total_rows');
1802 this.set('total_rows', ++totalRows, true);
1803 },
1804 decrementTotalRows: function () {
1805 let totalRows = this.get('total_rows');
1806 this.set('total_rows', --totalRows, true);
1807 },
1808 validateAdd: function () {
1809 // return true if allowed
1810 if (this.allowAdd()) {
1811 return true;
1812 }
1813
1814 // vars
1815 var max = this.get('max');
1816 var text = acf.__('Maximum rows reached ({max} rows)');
1817
1818 // replace
1819 text = text.replace('{max}', max);
1820
1821 // add notice
1822 this.showNotice({
1823 text: text,
1824 type: 'warning'
1825 });
1826
1827 // return
1828 return false;
1829 },
1830 onClickAdd: function (e, $el) {
1831 // validate
1832 if (!this.validateAdd()) {
1833 return false;
1834 }
1835
1836 // add above row
1837 if ($el.hasClass('acf-icon')) {
1838 this.add({
1839 before: $el.closest('.acf-row')
1840 });
1841
1842 // default
1843 } else {
1844 this.add();
1845 }
1846 },
1847 add: function (args) {
1848 // validate
1849 if (!this.allowAdd()) {
1850 return false;
1851 }
1852
1853 // defaults
1854 args = acf.parseArgs(args, {
1855 before: false
1856 });
1857
1858 // add row
1859 var $el = acf.duplicate({
1860 target: this.$clone(),
1861 append: this.proxy(function ($el, $el2) {
1862 // append
1863 if (args.before) {
1864 args.before.before($el2);
1865 } else {
1866 $el.before($el2);
1867 }
1868
1869 // remove clone class
1870 $el2.removeClass('acf-clone');
1871
1872 // enable
1873 acf.enable($el2, this.cid);
1874 })
1875 });
1876 if (this.get('pagination')) {
1877 this.incrementTotalRows();
1878 if (false !== args.before) {
1879 // If the row was inserted above an existing row, try to keep that order.
1880 const prevRowNum = parseInt(args.before.find('.acf-row-number').first().text()) || 0;
1881 let newRowNum = prevRowNum;
1882 if (newRowNum && !args.before.hasClass('acf-inserted') && !args.before.hasClass('acf-added')) {
1883 --newRowNum;
1884 }
1885 if (args.before.hasClass('acf-divider')) {
1886 args.before.removeClass('acf-divider');
1887 $el.addClass('acf-divider');
1888 }
1889 this.updateRowStatus($el, 'inserted');
1890 this.updateRowStatus($el, 'reordered', newRowNum);
1891
1892 // Hide the row numbers to avoid confusion with existing rows.
1893 $el.find('.acf-row-number').first().hide().text(newRowNum);
1894 if (!$el.find('.acf-order-input-wrap').hasClass('disabled')) {
1895 let message = acf.__('Order will be assigned upon save');
1896 $el.find('.acf-order-input-wrap').addClass('disabled');
1897 $el.find('.acf-row-number').first().after('<span title="' + message + '">-</span>');
1898 }
1899 $el.find('.acf-order-input').first().hide();
1900 $el.attr('data-inserted', newRowNum);
1901 } else {
1902 this.nextRowNum++;
1903 $el.find('.acf-order-input').first().val(this.nextRowNum);
1904 $el.find('.acf-row-number').first().text(this.nextRowNum);
1905 this.updateRowStatus($el, 'added');
1906 if (!this.$tbody().find('.acf-divider').length) {
1907 $el.addClass('acf-divider');
1908 }
1909 }
1910 $el.find('.acf-input:first').find('input:not([type=hidden]), select, textarea').first().trigger('focus');
1911 }
1912
1913 // Render and trigger change for validation errors.
1914 this.render();
1915 this.$input().trigger('change');
1916 return $el;
1917 },
1918 onClickDuplicate: function (e, $el) {
1919 // Validate with warning.
1920 if (!this.validateAdd()) {
1921 return false;
1922 }
1923
1924 // get layout and duplicate it.
1925 var $row = $el.closest('.acf-row');
1926 this.duplicateRow($row);
1927 },
1928 duplicateRow: function ($row) {
1929 // Validate without warning.
1930 if (!this.allowAdd()) {
1931 return false;
1932 }
1933
1934 // Vars.
1935 var fieldKey = this.get('key');
1936
1937 // Duplicate row.
1938 var $el = acf.duplicate({
1939 target: $row,
1940 // Provide a custom renaming callback to avoid renaming parent row attributes.
1941 rename: function (name, value, search, replace) {
1942 // Rename id attributes from "field_1-search" to "field_1-replace".
1943 if (name === 'id' || name === 'for') {
1944 return value.replace(fieldKey + '-' + search, fieldKey + '-' + replace);
1945
1946 // Rename name and for attributes from "[field_1][search]" to "[field_1][replace]".
1947 } else {
1948 return value.replace(fieldKey + '][' + search, fieldKey + '][' + replace);
1949 }
1950 },
1951 before: function ($el) {
1952 acf.doAction('unmount', $el);
1953 },
1954 after: function ($el, $el2) {
1955 acf.doAction('remount', $el);
1956 }
1957 });
1958 if (this.get('pagination')) {
1959 this.incrementTotalRows();
1960
1961 // If the row was inserted above an existing row, try to keep that order.
1962 const prevRowNum = parseInt($row.find('.acf-row-number').first().text()) || 0;
1963 this.updateRowStatus($el, 'inserted');
1964 this.updateRowStatus($el, 'reordered', prevRowNum);
1965
1966 // Hide the row numbers to avoid confusion with existing rows.
1967 $el.find('.acf-row-number').first().hide();
1968 if (!$el.find('.acf-order-input-wrap').hasClass('disabled')) {
1969 let message = acf.__('Order will be assigned upon save');
1970 $el.find('.acf-order-input-wrap').addClass('disabled');
1971 $el.find('.acf-row-number').first().after('<span title="' + message + '">-</span>');
1972 }
1973 $el.find('.acf-order-input').first().hide();
1974 $el.attr('data-inserted', prevRowNum);
1975 $el.removeClass('acf-divider');
1976 }
1977
1978 // trigger change for validation errors
1979 this.$input().trigger('change');
1980
1981 // Update order numbers.
1982 this.render();
1983
1984 // Focus on new row.
1985 acf.focusAttention($el);
1986
1987 // Return new layout.
1988 return $el;
1989 },
1990 validateRemove: function () {
1991 // return true if allowed
1992 if (this.allowRemove()) {
1993 return true;
1994 }
1995
1996 // vars
1997 var min = this.get('min');
1998 var text = acf.__('Minimum rows not reached ({min} rows)');
1999
2000 // replace
2001 text = text.replace('{min}', min);
2002
2003 // add notice
2004 this.showNotice({
2005 text: text,
2006 type: 'warning'
2007 });
2008
2009 // return
2010 return false;
2011 },
2012 onClickRemove: function (e, $el) {
2013 var $row = $el.closest('.acf-row');
2014
2015 // Bypass confirmation when holding down "shift" key.
2016 if (e.shiftKey) {
2017 return this.remove($row);
2018 }
2019
2020 // add class
2021 $row.addClass('-hover');
2022
2023 // add tooltip
2024 var tooltip = acf.newTooltip({
2025 confirmRemove: true,
2026 target: $el,
2027 context: this,
2028 confirm: function () {
2029 this.remove($row);
2030 },
2031 cancel: function () {
2032 $row.removeClass('-hover');
2033 }
2034 });
2035 },
2036 onClickRowOrder: function (e, $el) {
2037 if (!this.get('pagination')) {
2038 return;
2039 }
2040 if ($el.hasClass('disabled')) {
2041 return;
2042 }
2043 $el.find('.acf-row-number').hide();
2044 $el.find('.acf-order-input').show().trigger('select');
2045 },
2046 onBlurRowOrder: function (e, $el) {
2047 this.onChangeRowOrder(e, $el, false);
2048 },
2049 onChangeRowOrder: function (e, $el, update = true) {
2050 if (!this.get('pagination')) {
2051 return;
2052 }
2053 const $row = $el.closest('.acf-row');
2054 const $orderSpan = $row.find('.acf-row-number').first();
2055 let hrOrder = $el.val();
2056 $row.find('.acf-order-input').first().hide();
2057 if (!acf.isNumeric(hrOrder) || parseFloat(hrOrder) < 0) {
2058 $orderSpan.show();
2059 return;
2060 }
2061 hrOrder = Math.round(hrOrder);
2062 const newOrder = hrOrder - 1;
2063 $el.val(hrOrder);
2064 $orderSpan.text(hrOrder).show();
2065 if (update) {
2066 this.updateRowStatus($row, 'reordered', newOrder);
2067 }
2068 },
2069 onChangeTotalRows: function () {
2070 const perPage = parseInt(this.get('per_page')) || 20;
2071 const totalRows = parseInt(this.get('total_rows')) || 0;
2072 const totalPages = Math.ceil(totalRows / perPage);
2073
2074 // Update the total pages in pagination.
2075 this.$('.acf-total-pages:last').text(totalPages);
2076 this.nextRowNum = totalRows;
2077
2078 // If the current page no longer exists, load the last page.
2079 if (this.page > totalPages) {
2080 this.page = totalPages;
2081 this.ajaxLoadPage();
2082 }
2083 },
2084 remove: function ($row) {
2085 const self = this;
2086 if (this.get('pagination')) {
2087 this.decrementTotalRows();
2088
2089 // If using pagination and the row had already been saved, just hide the row instead of deleting it.
2090 if ($row.data('id').includes('row-')) {
2091 this.updateRowStatus($row, 'deleted');
2092 $row.hide();
2093 self.$input().trigger('change');
2094 self.render(false);
2095 return;
2096 } else if ($row.hasClass('acf-divider')) {
2097 $row.next('.acf-added').addClass('acf-divider');
2098 }
2099 }
2100
2101 // If not using pagination, delete the actual row.
2102 acf.remove({
2103 target: $row,
2104 endHeight: 0,
2105 complete: function () {
2106 // trigger change to allow attachment save
2107 self.$input().trigger('change');
2108
2109 // render
2110 self.render();
2111
2112 // sync collapsed order
2113 //self.sync();
2114 }
2115 });
2116 },
2117 isCollapsed: function ($row) {
2118 return $row.hasClass('-collapsed');
2119 },
2120 collapse: function ($row) {
2121 $row.addClass('-collapsed');
2122 acf.doAction('hide', $row, 'collapse');
2123 },
2124 expand: function ($row) {
2125 $row.removeClass('-collapsed');
2126 acf.doAction('show', $row, 'collapse');
2127 },
2128 onClickCollapse: function (e, $el) {
2129 // vars
2130 var $row = $el.closest('.acf-row');
2131 var isCollpased = this.isCollapsed($row);
2132
2133 // shift
2134 if (e.shiftKey) {
2135 $row = this.$rows();
2136 }
2137
2138 // toggle
2139 if (isCollpased) {
2140 this.expand($row);
2141 } else {
2142 this.collapse($row);
2143 }
2144 },
2145 onShow: function (e, $el, context) {
2146 // get sub fields
2147 var fields = acf.getFields({
2148 is: ':visible',
2149 parent: this.$el
2150 });
2151
2152 // trigger action
2153 // - ignore context, no need to pass through 'conditional_logic'
2154 // - this is just for fields like google_map to render itself
2155 acf.doAction('show_fields', fields);
2156 },
2157 onUnload: function () {
2158 // vars
2159 var indexes = [];
2160
2161 // loop
2162 this.$rows().each(function (i) {
2163 if ($(this).hasClass('-collapsed')) {
2164 indexes.push(i);
2165 }
2166 });
2167
2168 // allow null
2169 indexes = indexes.length ? indexes : null;
2170
2171 // set
2172 preference.save(this.get('key'), indexes);
2173 },
2174 onHover: function () {
2175 // add sortable
2176 this.addSortable(this);
2177
2178 // remove event
2179 this.off('mouseover');
2180 },
2181 onChangeField: function (e, $el) {
2182 const $target = $(e.delegateTarget);
2183 let $row = $el.closest('.acf-row');
2184 if ($row.closest('.acf-field-repeater').data('key') !== $target.data('key')) {
2185 $row = $row.parent().closest('.acf-row');
2186 }
2187 this.updateRowStatus($row, 'changed');
2188 },
2189 updateRowStatus: function ($row, status, data = true) {
2190 if (!this.get('pagination')) {
2191 return;
2192 }
2193 const parent_key = $row.parents('.acf-field-repeater').data('key');
2194 if (this.parent() && parent_key !== this.get('key')) {
2195 return;
2196 }
2197 const row_id = $row.data('id');
2198 const input_name = this.$el.find('.acf-repeater-hidden-input:first').attr('name');
2199 const status_name = `${input_name}[${row_id}][acf_${status}]`;
2200 const status_input = `<input type="hidden" class="acf-row-status" name="${status_name}" value="${data}" />`;
2201 if (!$row.hasClass('acf-' + status)) {
2202 $row.addClass('acf-' + status);
2203 }
2204
2205 // TODO: Update so that this doesn't get messed up with repeater subfields.
2206 const $existing_status = $row.find(`input[name='${status_name}']`);
2207 if (!$existing_status.length) {
2208 $row.find('td').first().append(status_input);
2209 } else {
2210 $existing_status.val(data);
2211 }
2212 },
2213 onClickFirstPage: function () {
2214 this.validatePage(1);
2215 },
2216 onClickPrevPage: function () {
2217 this.validatePage(this.page - 1);
2218 },
2219 onClickNextPage: function (e) {
2220 this.validatePage(this.page + 1);
2221 },
2222 onClickLastPage: function () {
2223 this.validatePage(this.totalPages());
2224 },
2225 onChangeCurrentPage: function () {
2226 this.validatePage(this.$pageInput().val());
2227 },
2228 maybeDisablePagination: function () {
2229 this.$actions().find('.acf-nav').removeClass('disabled');
2230 if (this.page <= 1) {
2231 this.$firstPageButton().addClass('disabled');
2232 this.$prevPageButton().addClass('disabled');
2233 }
2234 if (this.page >= this.totalPages()) {
2235 this.$nextPageButton().addClass('disabled');
2236 this.$lastPageButton().addClass('disabled');
2237 }
2238 },
2239 validatePage: function (nextPage) {
2240 const self = this;
2241
2242 // Validate the current page.
2243 acf.validateForm({
2244 form: this.$control(),
2245 event: '',
2246 reset: true,
2247 success: function ($form) {
2248 self.page = nextPage;
2249
2250 // Set up some sane defaults.
2251 if (self.page <= 1) {
2252 self.page = 1;
2253 }
2254 if (self.page >= self.totalPages()) {
2255 self.page = self.totalPages();
2256 }
2257 self.ajaxLoadPage();
2258 },
2259 failure: function ($form) {
2260 self.$pageInput().val(self.page);
2261 return false;
2262 }
2263 });
2264 },
2265 ajaxLoadPage: function (clearChanged = false) {
2266 const ajaxData = acf.prepareForAjax({
2267 action: 'acf/ajax/query_repeater',
2268 paged: this.page,
2269 field_key: this.get('key'),
2270 field_name: this.get('orig_name'),
2271 rows_per_page: parseInt(this.get('per_page')),
2272 refresh: clearChanged,
2273 nonce: this.get('nonce'),
2274 options_page_slug: acf.get('options_page_slug') || ''
2275 });
2276 $.ajax({
2277 url: ajaxurl,
2278 method: 'POST',
2279 dataType: 'json',
2280 data: ajaxData,
2281 context: this
2282 }).done(function (response) {
2283 const {
2284 rows
2285 } = response.data;
2286 const $existingRows = this.$tbody().find('> tr');
2287 $existingRows.not('.acf-clone').hide();
2288 if (clearChanged) {
2289 // Remove any existing rows since we are refreshing from the server.
2290 $existingRows.not('.acf-clone').remove();
2291
2292 // Trigger a change in total rows, so we can update pagination.
2293 this.set('total_rows', response.data.total_rows, false);
2294 } else {
2295 $existingRows.not('.acf-changed, .acf-deleted, .acf-reordered, .acf-added, .acf-inserted, .acf-clone').remove();
2296 }
2297 Object.keys(rows).forEach(index => {
2298 let $row = false;
2299 let $unsavedRow = this.$tbody().find('> *[data-id=row-' + index + ']');
2300 let $insertedRow = this.$tbody().find('> *[data-inserted=' + index + ']');
2301
2302 // Unsaved new rows that are inserted into this specific position.
2303 if ($insertedRow.length) {
2304 $insertedRow.appendTo(this.$tbody()).show();
2305 acf.doAction('remount', $insertedRow);
2306 }
2307
2308 // Skip unsaved deleted rows; we don't want to show them again.
2309 if ($unsavedRow.hasClass('acf-deleted')) {
2310 return;
2311 }
2312
2313 // Unsaved edited rows should be moved to correct position.
2314 if ($unsavedRow.length) {
2315 acf.doAction('unmount', $unsavedRow);
2316 $unsavedRow.appendTo(this.$tbody()).show();
2317 acf.doAction('remount', $unsavedRow);
2318 return;
2319 }
2320
2321 // Rows from the server (that haven't been changed or deleted) should be appended and shown.
2322 $row = $(rows[index]);
2323 this.$tbody().append($row).show();
2324 acf.doAction('remount', $row);
2325
2326 // Move clone field back to the right spot.
2327 this.$clone().appendTo(this.$tbody());
2328 });
2329 const $addedRows = this.$tbody().find('.acf-added:hidden');
2330
2331 // If there are any new rows that are still hidden, append them to the bottom.
2332 if ($addedRows.length) {
2333 const self = this;
2334 $addedRows.each(function () {
2335 const $addedRow = $(this);
2336 $addedRow.insertBefore(self.$clone()).show();
2337 acf.doAction('remount', $addedRow);
2338 });
2339 }
2340
2341 // Update the page input.
2342 this.$pageInput().val(this.page);
2343 this.maybeDisablePagination();
2344 }).fail(function (jqXHR, textStatus, errorThrown) {
2345 const error = acf.getXhrError(jqXHR);
2346 let message = acf.__('Error loading page');
2347 if ('' !== error) {
2348 message = `${message}: ${error}`;
2349 }
2350 this.showNotice({
2351 text: message,
2352 type: 'warning'
2353 });
2354 });
2355 }
2356 });
2357 acf.registerFieldType(Field);
2358
2359 // register existing conditions
2360 acf.registerConditionForFieldType('hasValue', 'repeater');
2361 acf.registerConditionForFieldType('hasNoValue', 'repeater');
2362 acf.registerConditionForFieldType('lessThan', 'repeater');
2363 acf.registerConditionForFieldType('greaterThan', 'repeater');
2364
2365 // state
2366 var preference = new acf.Model({
2367 name: 'this.collapsedRows',
2368 key: function (key, context) {
2369 // vars
2370 var count = this.get(key + context) || 0;
2371
2372 // update
2373 count++;
2374 this.set(key + context, count, true);
2375
2376 // modify fieldKey
2377 if (count > 1) {
2378 key += '-' + count;
2379 }
2380
2381 // return
2382 return key;
2383 },
2384 load: function (key) {
2385 // vars
2386 var key = this.key(key, 'load');
2387 var data = acf.getPreference(this.name);
2388
2389 // return
2390 if (data && data[key]) {
2391 return data[key];
2392 } else {
2393 return false;
2394 }
2395 },
2396 save: function (key, value) {
2397 // vars
2398 var key = this.key(key, 'save');
2399 var data = acf.getPreference(this.name) || {};
2400
2401 // delete
2402 if (value === null) {
2403 delete data[key];
2404
2405 // append
2406 } else {
2407 data[key] = value;
2408 }
2409
2410 // allow null
2411 if ($.isEmptyObject(data)) {
2412 data = null;
2413 }
2414
2415 // save
2416 acf.setPreference(this.name, data);
2417 }
2418 });
2419 })(jQuery);
2420
2421 /***/ })
2422
2423 /******/ });
2424 /************************************************************************/
2425 /******/ // The module cache
2426 /******/ var __webpack_module_cache__ = {};
2427 /******/
2428 /******/ // The require function
2429 /******/ function __webpack_require__(moduleId) {
2430 /******/ // Check if module is in cache
2431 /******/ var cachedModule = __webpack_module_cache__[moduleId];
2432 /******/ if (cachedModule !== undefined) {
2433 /******/ return cachedModule.exports;
2434 /******/ }
2435 /******/ // Create a new module (and put it into the cache)
2436 /******/ var module = __webpack_module_cache__[moduleId] = {
2437 /******/ // no module.id needed
2438 /******/ // no module.loaded needed
2439 /******/ exports: {}
2440 /******/ };
2441 /******/
2442 /******/ // Execute the module function
2443 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
2444 /******/
2445 /******/ // Return the exports of the module
2446 /******/ return module.exports;
2447 /******/ }
2448 /******/
2449 /************************************************************************/
2450 /******/ /* webpack/runtime/compat get default export */
2451 /******/ (() => {
2452 /******/ // getDefaultExport function for compatibility with non-harmony modules
2453 /******/ __webpack_require__.n = (module) => {
2454 /******/ var getter = module && module.__esModule ?
2455 /******/ () => (module['default']) :
2456 /******/ () => (module);
2457 /******/ __webpack_require__.d(getter, { a: getter });
2458 /******/ return getter;
2459 /******/ };
2460 /******/ })();
2461 /******/
2462 /******/ /* webpack/runtime/define property getters */
2463 /******/ (() => {
2464 /******/ // define getter functions for harmony exports
2465 /******/ __webpack_require__.d = (exports, definition) => {
2466 /******/ for(var key in definition) {
2467 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
2468 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
2469 /******/ }
2470 /******/ }
2471 /******/ };
2472 /******/ })();
2473 /******/
2474 /******/ /* webpack/runtime/hasOwnProperty shorthand */
2475 /******/ (() => {
2476 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
2477 /******/ })();
2478 /******/
2479 /******/ /* webpack/runtime/make namespace object */
2480 /******/ (() => {
2481 /******/ // define __esModule on exports
2482 /******/ __webpack_require__.r = (exports) => {
2483 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
2484 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2485 /******/ }
2486 /******/ Object.defineProperty(exports, '__esModule', { value: true });
2487 /******/ };
2488 /******/ })();
2489 /******/
2490 /************************************************************************/
2491 var __webpack_exports__ = {};
2492 // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
2493 (() => {
2494 "use strict";
2495 /*!********************************************!*\
2496 !*** ./assets/src/js/pro/acf-pro-input.js ***!
2497 \********************************************/
2498 __webpack_require__.r(__webpack_exports__);
2499 /* 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");
2500 /* harmony import */ var _acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0__);
2501 /* 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");
2502 /* 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__);
2503 /* 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");
2504 /* harmony import */ var _acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2__);
2505
2506
2507
2508 })();
2509
2510 /******/ })()
2511 ;
2512 //# sourceMappingURL=acf-pro-input.js.map