PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.9.5
Secure Custom Fields v6.9.5
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 3 months ago acf-datastore.js 3 months ago acf-datastore.js.map 3 months ago acf-datastore.min.asset.php 3 months ago acf-datastore.min.js 3 months ago acf-field-bindings.asset.php 3 months ago acf-field-bindings.js 3 months ago acf-field-bindings.js.map 3 months ago acf-field-bindings.min.asset.php 3 months ago acf-field-bindings.min.js 3 months ago acf-pro-blocks.asset.php 1 month ago acf-pro-blocks.js 1 month ago acf-pro-blocks.js.map 1 month ago acf-pro-blocks.min.asset.php 1 month ago acf-pro-blocks.min.js 1 month 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 2 weeks ago acf-pro-input.js 2 weeks ago acf-pro-input.js.map 2 weeks ago acf-pro-input.min.asset.php 2 weeks ago acf-pro-input.min.js 2 weeks 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
2513 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 this.closeSidebar();
1429 return;
1430 }
1431
1432 // vars
1433 var $side = this.$sideData();
1434
1435 // render
1436 $side.html(html);
1437
1438 // remove acf form data
1439 $side.find('.compat-field-acf-form-data').remove();
1440
1441 // merge tables
1442 $side.find('> table.form-table > tbody').append($side.find('> .compat-attachment-fields > tbody > tr'));
1443
1444 // setup fields
1445 acf.doAction('append', $side);
1446 });
1447
1448 // run step 1
1449 step1();
1450 },
1451 onClickSelect: function (e, $el) {
1452 var id = $el.data('id');
1453 if (id) {
1454 this.selectAttachment(id);
1455 }
1456 },
1457 onClickClose: function (e, $el) {
1458 this.closeSidebar();
1459 },
1460 onChangeSort: function (e, $el) {
1461 // Bail early if is disabled.
1462 if ($el.hasClass('disabled')) {
1463 return;
1464 }
1465
1466 // Get sort val.
1467 var val = $el.val();
1468 if (!val) {
1469 return;
1470 }
1471
1472 // find ids
1473 var ids = [];
1474 this.$attachments().each(function () {
1475 ids.push($(this).data('id'));
1476 });
1477
1478 // step 1
1479 var step1 = this.proxy(function () {
1480 const ajaxData = {
1481 action: 'acf/fields/gallery/get_sort_order',
1482 nonce: this.get('nonce'),
1483 field_key: this.get('key'),
1484 ids: ids,
1485 sort: val
1486 };
1487
1488 // get results
1489 var xhr = $.ajax({
1490 url: acf.get('ajaxurl'),
1491 dataType: 'json',
1492 type: 'post',
1493 cache: false,
1494 data: acf.prepareForAjax(ajaxData),
1495 success: step2
1496 });
1497 });
1498
1499 // step 2
1500 var step2 = this.proxy(function (json) {
1501 // validate
1502 if (!acf.isAjaxSuccess(json)) {
1503 return;
1504 }
1505
1506 // reverse order
1507 json.data.reverse();
1508
1509 // loop
1510 json.data.map(function (id) {
1511 this.$collection().prepend(this.$attachment(id));
1512 }, this);
1513 });
1514
1515 // call step 1
1516 step1();
1517 },
1518 onUpdate: function (e, $el) {
1519 // vars
1520 var $submit = this.$('.acf-gallery-update');
1521
1522 // validate
1523 if ($submit.hasClass('disabled')) {
1524 return;
1525 }
1526
1527 // serialize data
1528 const ajaxData = acf.serialize(this.$sideData());
1529
1530 // loading
1531 $submit.addClass('disabled');
1532 $submit.before('<i class="acf-loading"></i> ');
1533
1534 // Append AJAX action and nonce.
1535 ajaxData.action = 'acf/fields/gallery/update_attachment';
1536 ajaxData.nonce = this.get('nonce');
1537 ajaxData.field_key = this.get('key');
1538
1539 // ajax
1540 $.ajax({
1541 url: acf.get('ajaxurl'),
1542 data: acf.prepareForAjax(ajaxData),
1543 type: 'post',
1544 dataType: 'json',
1545 complete: function () {
1546 $submit.removeClass('disabled');
1547 $submit.prev('.acf-loading').remove();
1548 }
1549 });
1550 },
1551 onHover: function () {
1552 // add sortable
1553 this.addSortable(this);
1554
1555 // remove event
1556 this.off('mouseover');
1557 }
1558 });
1559 acf.registerFieldType(Field);
1560
1561 // register existing conditions
1562 acf.registerConditionForFieldType('hasValue', 'gallery');
1563 acf.registerConditionForFieldType('hasNoValue', 'gallery');
1564 acf.registerConditionForFieldType('selectionLessThan', 'gallery');
1565 acf.registerConditionForFieldType('selectionGreaterThan', 'gallery');
1566 })(jQuery);
1567
1568 /***/ }),
1569
1570 /***/ "./assets/src/js/pro/_acf-field-repeater.js":
1571 /*!**************************************************!*\
1572 !*** ./assets/src/js/pro/_acf-field-repeater.js ***!
1573 \**************************************************/
1574 /***/ (() => {
1575
1576 (function ($) {
1577 var Field = acf.Field.extend({
1578 type: 'repeater',
1579 wait: '',
1580 page: 1,
1581 nextRowNum: 0,
1582 events: {
1583 'click a[data-event="add-row"]': 'onClickAdd',
1584 'click a[data-event="duplicate-row"]': 'onClickDuplicate',
1585 'click a[data-event="remove-row"]': 'onClickRemove',
1586 'click a[data-event="collapse-row"]': 'onClickCollapse',
1587 'click a[data-event="first-page"]:not(.disabled)': 'onClickFirstPage',
1588 'click a[data-event="last-page"]:not(.disabled)': 'onClickLastPage',
1589 'click a[data-event="prev-page"]:not(.disabled)': 'onClickPrevPage',
1590 'click a[data-event="next-page"]:not(.disabled)': 'onClickNextPage',
1591 'change .current-page': 'onChangeCurrentPage',
1592 'click .acf-order-input-wrap': 'onClickRowOrder',
1593 'blur .acf-order-input': 'onBlurRowOrder',
1594 'change .acf-order-input': 'onChangeRowOrder',
1595 'changed:total_rows': 'onChangeTotalRows',
1596 showField: 'onShow',
1597 unloadField: 'onUnload',
1598 mouseover: 'onHover',
1599 change: 'onChangeField'
1600 },
1601 $control: function () {
1602 return this.$('.acf-repeater:first');
1603 },
1604 $table: function () {
1605 return this.$('table:first');
1606 },
1607 $tbody: function () {
1608 return this.$('tbody:first');
1609 },
1610 $rows: function () {
1611 return this.$('tbody:first > tr').not('.acf-clone, .acf-deleted');
1612 },
1613 $row: function (index) {
1614 return this.$('tbody:first > tr:eq(' + index + ')');
1615 },
1616 $clone: function () {
1617 return this.$('tbody:first > tr.acf-clone');
1618 },
1619 $actions: function () {
1620 return this.$('.acf-actions:last');
1621 },
1622 $button: function () {
1623 return this.$('.acf-actions:last .button');
1624 },
1625 $firstPageButton: function () {
1626 return this.$('.acf-tablenav:last .first-page');
1627 },
1628 $prevPageButton: function () {
1629 return this.$('.acf-tablenav:last .prev-page');
1630 },
1631 $nextPageButton: function () {
1632 return this.$('.acf-tablenav:last .next-page');
1633 },
1634 $lastPageButton: function () {
1635 return this.$('.acf-tablenav:last .last-page');
1636 },
1637 $pageInput: function () {
1638 return this.$('.current-page:last');
1639 },
1640 totalPages: function () {
1641 const totalPages = this.$('.acf-total-pages:last').text();
1642 return parseInt(totalPages);
1643 },
1644 getValue: function () {
1645 return this.$rows().length;
1646 },
1647 allowRemove: function () {
1648 let numRows = this.val();
1649 let minRows = parseInt(this.get('min'));
1650 if (this.get('pagination')) {
1651 numRows = this.get('total_rows');
1652 }
1653 return !minRows || minRows < numRows;
1654 },
1655 allowAdd: function () {
1656 let numRows = this.val();
1657 let maxRows = parseInt(this.get('max'));
1658 if (this.get('pagination')) {
1659 numRows = this.get('total_rows');
1660 }
1661 return !maxRows || maxRows > numRows;
1662 },
1663 addSortable: function (self) {
1664 // bail early if max 1 row
1665 if (this.get('max') == 1) {
1666 return;
1667 }
1668
1669 // Bail early if using pagination.
1670 if (this.get('pagination')) {
1671 return;
1672 }
1673
1674 // add sortable
1675 this.$tbody().sortable({
1676 items: '> tr',
1677 handle: '> td.order',
1678 zIndex: 9999,
1679 forceHelperSize: true,
1680 forcePlaceholderSize: true,
1681 scroll: true,
1682 stop: function (event, ui) {
1683 self.render();
1684 },
1685 update: function (event, ui) {
1686 self.$input().trigger('change');
1687 }
1688 });
1689 },
1690 addCollapsed: function () {
1691 // vars
1692 var indexes = preference.load(this.get('key'));
1693
1694 // bail early if no collapsed
1695 if (!indexes) {
1696 return false;
1697 }
1698
1699 // loop
1700 this.$rows().each(function (i) {
1701 if (indexes.indexOf(i) > -1) {
1702 if ($(this).find('.-collapsed-target').length) {
1703 $(this).addClass('-collapsed');
1704 }
1705 }
1706 });
1707 },
1708 addUnscopedEvents: function (self) {
1709 // invalidField
1710 this.on('invalidField', '.acf-row', function (e) {
1711 var $row = $(this);
1712 if (self.isCollapsed($row)) {
1713 self.expand($row);
1714 }
1715 });
1716
1717 // Listen for changes to fields, so we can persist them in the DOM.
1718 if (this.get('pagination')) {
1719 this.on('change', 'input, select, textarea', function (e) {
1720 const $changed = $(e.currentTarget);
1721 if (!$changed.hasClass('acf-order-input') && !$changed.hasClass('acf-row-status')) {
1722 self.onChangeField(e, $(this));
1723 }
1724 });
1725 }
1726 this.listenForSavedMetaBoxes();
1727 },
1728 initialize: function () {
1729 // add unscoped events
1730 this.addUnscopedEvents(this);
1731
1732 // add collapsed
1733 this.addCollapsed();
1734
1735 // disable clone
1736 acf.disable(this.$clone(), this.cid);
1737
1738 // Set up the next row number.
1739 if (this.get('pagination')) {
1740 this.nextRowNum = this.get('total_rows');
1741 }
1742
1743 // render
1744 this.render();
1745 },
1746 render: function (update_order_numbers = true) {
1747 // Update order number.
1748 if (update_order_numbers) {
1749 this.$rows().each(function (i) {
1750 $(this).find('> .order > span').html(i + 1);
1751 });
1752 }
1753
1754 // Extract vars.
1755 var $control = this.$control();
1756 var $button = this.$button();
1757
1758 // empty
1759 if (this.val() == 0) {
1760 $control.addClass('-empty');
1761 } else {
1762 $control.removeClass('-empty');
1763 }
1764
1765 // Reached max rows.
1766 if (!this.allowAdd()) {
1767 $control.addClass('-max');
1768 $button.addClass('disabled');
1769 } else {
1770 $control.removeClass('-max');
1771 $button.removeClass('disabled');
1772 }
1773 if (this.get('pagination')) {
1774 this.maybeDisablePagination();
1775 }
1776
1777 // Reached min rows (not used).
1778 //if( !this.allowRemove() ) {
1779 // $control.addClass('-min');
1780 //} else {
1781 // $control.removeClass('-min');
1782 //}
1783 },
1784 listenForSavedMetaBoxes: function () {
1785 if (!acf.isGutenbergPostEditor() || !this.get('pagination')) {
1786 return;
1787 }
1788 let checkedMetaBoxes = true;
1789 wp.data.subscribe(() => {
1790 if (wp.data.select('core/edit-post').isSavingMetaBoxes()) {
1791 checkedMetaBoxes = false;
1792 } else {
1793 if (!checkedMetaBoxes) {
1794 checkedMetaBoxes = true;
1795 this.set('total_rows', 0, true);
1796 this.ajaxLoadPage(true);
1797 }
1798 }
1799 });
1800 },
1801 incrementTotalRows: function () {
1802 let totalRows = this.get('total_rows');
1803 this.set('total_rows', ++totalRows, true);
1804 },
1805 decrementTotalRows: function () {
1806 let totalRows = this.get('total_rows');
1807 this.set('total_rows', --totalRows, true);
1808 },
1809 validateAdd: function () {
1810 // return true if allowed
1811 if (this.allowAdd()) {
1812 return true;
1813 }
1814
1815 // vars
1816 var max = this.get('max');
1817 var text = acf.__('Maximum rows reached ({max} rows)');
1818
1819 // replace
1820 text = text.replace('{max}', max);
1821
1822 // add notice
1823 this.showNotice({
1824 text: text,
1825 type: 'warning'
1826 });
1827
1828 // return
1829 return false;
1830 },
1831 onClickAdd: function (e, $el) {
1832 // validate
1833 if (!this.validateAdd()) {
1834 return false;
1835 }
1836
1837 // add above row
1838 if ($el.hasClass('acf-icon')) {
1839 this.add({
1840 before: $el.closest('.acf-row')
1841 });
1842
1843 // default
1844 } else {
1845 this.add();
1846 }
1847 },
1848 add: function (args) {
1849 // validate
1850 if (!this.allowAdd()) {
1851 return false;
1852 }
1853
1854 // defaults
1855 args = acf.parseArgs(args, {
1856 before: false
1857 });
1858
1859 // add row
1860 var $el = acf.duplicate({
1861 target: this.$clone(),
1862 append: this.proxy(function ($el, $el2) {
1863 // append
1864 if (args.before) {
1865 args.before.before($el2);
1866 } else {
1867 $el.before($el2);
1868 }
1869
1870 // remove clone class
1871 $el2.removeClass('acf-clone');
1872
1873 // enable
1874 acf.enable($el2, this.cid);
1875 })
1876 });
1877 if (this.get('pagination')) {
1878 this.incrementTotalRows();
1879 if (false !== args.before) {
1880 // If the row was inserted above an existing row, try to keep that order.
1881 const prevRowNum = parseInt(args.before.find('.acf-row-number').first().text()) || 0;
1882 let newRowNum = prevRowNum;
1883 if (newRowNum && !args.before.hasClass('acf-inserted') && !args.before.hasClass('acf-added')) {
1884 --newRowNum;
1885 }
1886 if (args.before.hasClass('acf-divider')) {
1887 args.before.removeClass('acf-divider');
1888 $el.addClass('acf-divider');
1889 }
1890 this.updateRowStatus($el, 'inserted');
1891 this.updateRowStatus($el, 'reordered', newRowNum);
1892
1893 // Hide the row numbers to avoid confusion with existing rows.
1894 $el.find('.acf-row-number').first().hide().text(newRowNum);
1895 if (!$el.find('.acf-order-input-wrap').hasClass('disabled')) {
1896 let message = acf.__('Order will be assigned upon save');
1897 $el.find('.acf-order-input-wrap').addClass('disabled');
1898 $el.find('.acf-row-number').first().after('<span title="' + message + '">-</span>');
1899 }
1900 $el.find('.acf-order-input').first().hide();
1901 $el.attr('data-inserted', newRowNum);
1902 } else {
1903 this.nextRowNum++;
1904 $el.find('.acf-order-input').first().val(this.nextRowNum);
1905 $el.find('.acf-row-number').first().text(this.nextRowNum);
1906 this.updateRowStatus($el, 'added');
1907 if (!this.$tbody().find('.acf-divider').length) {
1908 $el.addClass('acf-divider');
1909 }
1910 }
1911 $el.find('.acf-input:first').find('input:not([type=hidden]), select, textarea').first().trigger('focus');
1912 }
1913
1914 // Render and trigger change for validation errors.
1915 this.render();
1916 this.$input().trigger('change');
1917 return $el;
1918 },
1919 onClickDuplicate: function (e, $el) {
1920 // Validate with warning.
1921 if (!this.validateAdd()) {
1922 return false;
1923 }
1924
1925 // get layout and duplicate it.
1926 var $row = $el.closest('.acf-row');
1927 this.duplicateRow($row);
1928 },
1929 duplicateRow: function ($row) {
1930 // Validate without warning.
1931 if (!this.allowAdd()) {
1932 return false;
1933 }
1934
1935 // Vars.
1936 var fieldKey = this.get('key');
1937
1938 // Duplicate row.
1939 var $el = acf.duplicate({
1940 target: $row,
1941 // Provide a custom renaming callback to avoid renaming parent row attributes.
1942 rename: function (name, value, search, replace) {
1943 // Rename id attributes from "field_1-search" to "field_1-replace".
1944 if (name === 'id' || name === 'for') {
1945 return value.replace(fieldKey + '-' + search, fieldKey + '-' + replace);
1946
1947 // Rename name and for attributes from "[field_1][search]" to "[field_1][replace]".
1948 } else {
1949 return value.replace(fieldKey + '][' + search, fieldKey + '][' + replace);
1950 }
1951 },
1952 before: function ($el) {
1953 acf.doAction('unmount', $el);
1954 },
1955 after: function ($el, $el2) {
1956 acf.doAction('remount', $el);
1957 }
1958 });
1959 if (this.get('pagination')) {
1960 this.incrementTotalRows();
1961
1962 // If the row was inserted above an existing row, try to keep that order.
1963 const prevRowNum = parseInt($row.find('.acf-row-number').first().text()) || 0;
1964 this.updateRowStatus($el, 'inserted');
1965 this.updateRowStatus($el, 'reordered', prevRowNum);
1966
1967 // Hide the row numbers to avoid confusion with existing rows.
1968 $el.find('.acf-row-number').first().hide();
1969 if (!$el.find('.acf-order-input-wrap').hasClass('disabled')) {
1970 let message = acf.__('Order will be assigned upon save');
1971 $el.find('.acf-order-input-wrap').addClass('disabled');
1972 $el.find('.acf-row-number').first().after('<span title="' + message + '">-</span>');
1973 }
1974 $el.find('.acf-order-input').first().hide();
1975 $el.attr('data-inserted', prevRowNum);
1976 $el.removeClass('acf-divider');
1977 }
1978
1979 // trigger change for validation errors
1980 this.$input().trigger('change');
1981
1982 // Update order numbers.
1983 this.render();
1984
1985 // Focus on new row.
1986 acf.focusAttention($el);
1987
1988 // Return new layout.
1989 return $el;
1990 },
1991 validateRemove: function () {
1992 // return true if allowed
1993 if (this.allowRemove()) {
1994 return true;
1995 }
1996
1997 // vars
1998 var min = this.get('min');
1999 var text = acf.__('Minimum rows not reached ({min} rows)');
2000
2001 // replace
2002 text = text.replace('{min}', min);
2003
2004 // add notice
2005 this.showNotice({
2006 text: text,
2007 type: 'warning'
2008 });
2009
2010 // return
2011 return false;
2012 },
2013 onClickRemove: function (e, $el) {
2014 var $row = $el.closest('.acf-row');
2015
2016 // Bypass confirmation when holding down "shift" key.
2017 if (e.shiftKey) {
2018 return this.remove($row);
2019 }
2020
2021 // add class
2022 $row.addClass('-hover');
2023
2024 // add tooltip
2025 var tooltip = acf.newTooltip({
2026 confirmRemove: true,
2027 target: $el,
2028 context: this,
2029 confirm: function () {
2030 this.remove($row);
2031 },
2032 cancel: function () {
2033 $row.removeClass('-hover');
2034 }
2035 });
2036 },
2037 onClickRowOrder: function (e, $el) {
2038 if (!this.get('pagination')) {
2039 return;
2040 }
2041 if ($el.hasClass('disabled')) {
2042 return;
2043 }
2044 $el.find('.acf-row-number').hide();
2045 $el.find('.acf-order-input').show().trigger('select');
2046 },
2047 onBlurRowOrder: function (e, $el) {
2048 this.onChangeRowOrder(e, $el, false);
2049 },
2050 onChangeRowOrder: function (e, $el, update = true) {
2051 if (!this.get('pagination')) {
2052 return;
2053 }
2054 const $row = $el.closest('.acf-row');
2055 const $orderSpan = $row.find('.acf-row-number').first();
2056 let hrOrder = $el.val();
2057 $row.find('.acf-order-input').first().hide();
2058 if (!acf.isNumeric(hrOrder) || parseFloat(hrOrder) < 0) {
2059 $orderSpan.show();
2060 return;
2061 }
2062 hrOrder = Math.round(hrOrder);
2063 const newOrder = hrOrder - 1;
2064 $el.val(hrOrder);
2065 $orderSpan.text(hrOrder).show();
2066 if (update) {
2067 this.updateRowStatus($row, 'reordered', newOrder);
2068 }
2069 },
2070 onChangeTotalRows: function () {
2071 const perPage = parseInt(this.get('per_page')) || 20;
2072 const totalRows = parseInt(this.get('total_rows')) || 0;
2073 const totalPages = Math.ceil(totalRows / perPage);
2074
2075 // Update the total pages in pagination.
2076 this.$('.acf-total-pages:last').text(totalPages);
2077 this.nextRowNum = totalRows;
2078
2079 // If the current page no longer exists, load the last page.
2080 if (this.page > totalPages) {
2081 this.page = totalPages;
2082 this.ajaxLoadPage();
2083 }
2084 },
2085 remove: function ($row) {
2086 const self = this;
2087 if (this.get('pagination')) {
2088 this.decrementTotalRows();
2089
2090 // If using pagination and the row had already been saved, just hide the row instead of deleting it.
2091 if ($row.data('id').includes('row-')) {
2092 this.updateRowStatus($row, 'deleted');
2093 $row.hide();
2094 self.$input().trigger('change');
2095 self.render(false);
2096 return;
2097 } else if ($row.hasClass('acf-divider')) {
2098 $row.next('.acf-added').addClass('acf-divider');
2099 }
2100 }
2101
2102 // If not using pagination, delete the actual row.
2103 acf.remove({
2104 target: $row,
2105 endHeight: 0,
2106 complete: function () {
2107 // trigger change to allow attachment save
2108 self.$input().trigger('change');
2109
2110 // render
2111 self.render();
2112
2113 // sync collapsed order
2114 //self.sync();
2115 }
2116 });
2117 },
2118 isCollapsed: function ($row) {
2119 return $row.hasClass('-collapsed');
2120 },
2121 collapse: function ($row) {
2122 $row.addClass('-collapsed');
2123 acf.doAction('hide', $row, 'collapse');
2124 },
2125 expand: function ($row) {
2126 $row.removeClass('-collapsed');
2127 acf.doAction('show', $row, 'collapse');
2128 },
2129 onClickCollapse: function (e, $el) {
2130 // vars
2131 var $row = $el.closest('.acf-row');
2132 var isCollpased = this.isCollapsed($row);
2133
2134 // shift
2135 if (e.shiftKey) {
2136 $row = this.$rows();
2137 }
2138
2139 // toggle
2140 if (isCollpased) {
2141 this.expand($row);
2142 } else {
2143 this.collapse($row);
2144 }
2145 },
2146 onShow: function (e, $el, context) {
2147 // get sub fields
2148 var fields = acf.getFields({
2149 is: ':visible',
2150 parent: this.$el
2151 });
2152
2153 // trigger action
2154 // - ignore context, no need to pass through 'conditional_logic'
2155 // - this is just for fields like google_map to render itself
2156 acf.doAction('show_fields', fields);
2157 },
2158 onUnload: function () {
2159 // vars
2160 var indexes = [];
2161
2162 // loop
2163 this.$rows().each(function (i) {
2164 if ($(this).hasClass('-collapsed')) {
2165 indexes.push(i);
2166 }
2167 });
2168
2169 // allow null
2170 indexes = indexes.length ? indexes : null;
2171
2172 // set
2173 preference.save(this.get('key'), indexes);
2174 },
2175 onHover: function () {
2176 // add sortable
2177 this.addSortable(this);
2178
2179 // remove event
2180 this.off('mouseover');
2181 },
2182 onChangeField: function (e, $el) {
2183 const $target = $(e.delegateTarget);
2184 let $row = $el.closest('.acf-row');
2185 if ($row.closest('.acf-field-repeater').data('key') !== $target.data('key')) {
2186 $row = $row.parent().closest('.acf-row');
2187 }
2188 this.updateRowStatus($row, 'changed');
2189 },
2190 updateRowStatus: function ($row, status, data = true) {
2191 if (!this.get('pagination')) {
2192 return;
2193 }
2194 const parent_key = $row.parents('.acf-field-repeater').data('key');
2195 if (this.parent() && parent_key !== this.get('key')) {
2196 return;
2197 }
2198 const row_id = $row.data('id');
2199 const input_name = this.$el.find('.acf-repeater-hidden-input:first').attr('name');
2200 const status_name = `${input_name}[${row_id}][acf_${status}]`;
2201 const status_input = `<input type="hidden" class="acf-row-status" name="${status_name}" value="${data}" />`;
2202 if (!$row.hasClass('acf-' + status)) {
2203 $row.addClass('acf-' + status);
2204 }
2205
2206 // TODO: Update so that this doesn't get messed up with repeater subfields.
2207 const $existing_status = $row.find(`input[name='${status_name}']`);
2208 if (!$existing_status.length) {
2209 $row.find('td').first().append(status_input);
2210 } else {
2211 $existing_status.val(data);
2212 }
2213 },
2214 onClickFirstPage: function () {
2215 this.validatePage(1);
2216 },
2217 onClickPrevPage: function () {
2218 this.validatePage(this.page - 1);
2219 },
2220 onClickNextPage: function (e) {
2221 this.validatePage(this.page + 1);
2222 },
2223 onClickLastPage: function () {
2224 this.validatePage(this.totalPages());
2225 },
2226 onChangeCurrentPage: function () {
2227 this.validatePage(this.$pageInput().val());
2228 },
2229 maybeDisablePagination: function () {
2230 this.$actions().find('.acf-nav').removeClass('disabled');
2231 if (this.page <= 1) {
2232 this.$firstPageButton().addClass('disabled');
2233 this.$prevPageButton().addClass('disabled');
2234 }
2235 if (this.page >= this.totalPages()) {
2236 this.$nextPageButton().addClass('disabled');
2237 this.$lastPageButton().addClass('disabled');
2238 }
2239 },
2240 validatePage: function (nextPage) {
2241 const self = this;
2242
2243 // Validate the current page.
2244 acf.validateForm({
2245 form: this.$control(),
2246 event: '',
2247 reset: true,
2248 success: function ($form) {
2249 self.page = nextPage;
2250
2251 // Set up some sane defaults.
2252 if (self.page <= 1) {
2253 self.page = 1;
2254 }
2255 if (self.page >= self.totalPages()) {
2256 self.page = self.totalPages();
2257 }
2258 self.ajaxLoadPage();
2259 },
2260 failure: function ($form) {
2261 self.$pageInput().val(self.page);
2262 return false;
2263 }
2264 });
2265 },
2266 ajaxLoadPage: function (clearChanged = false) {
2267 const ajaxData = acf.prepareForAjax({
2268 action: 'acf/ajax/query_repeater',
2269 paged: this.page,
2270 field_key: this.get('key'),
2271 field_name: this.get('orig_name'),
2272 rows_per_page: parseInt(this.get('per_page')),
2273 refresh: clearChanged,
2274 nonce: this.get('nonce'),
2275 options_page_slug: acf.get('options_page_slug') || ''
2276 });
2277 $.ajax({
2278 url: ajaxurl,
2279 method: 'POST',
2280 dataType: 'json',
2281 data: ajaxData,
2282 context: this
2283 }).done(function (response) {
2284 const {
2285 rows
2286 } = response.data;
2287 const $existingRows = this.$tbody().find('> tr');
2288 $existingRows.not('.acf-clone').hide();
2289 if (clearChanged) {
2290 // Remove any existing rows since we are refreshing from the server.
2291 $existingRows.not('.acf-clone').remove();
2292
2293 // Trigger a change in total rows, so we can update pagination.
2294 this.set('total_rows', response.data.total_rows, false);
2295 } else {
2296 $existingRows.not('.acf-changed, .acf-deleted, .acf-reordered, .acf-added, .acf-inserted, .acf-clone').remove();
2297 }
2298 Object.keys(rows).forEach(index => {
2299 let $row = false;
2300 let $unsavedRow = this.$tbody().find('> *[data-id=row-' + index + ']');
2301 let $insertedRow = this.$tbody().find('> *[data-inserted=' + index + ']');
2302
2303 // Unsaved new rows that are inserted into this specific position.
2304 if ($insertedRow.length) {
2305 $insertedRow.appendTo(this.$tbody()).show();
2306 acf.doAction('remount', $insertedRow);
2307 }
2308
2309 // Skip unsaved deleted rows; we don't want to show them again.
2310 if ($unsavedRow.hasClass('acf-deleted')) {
2311 return;
2312 }
2313
2314 // Unsaved edited rows should be moved to correct position.
2315 if ($unsavedRow.length) {
2316 acf.doAction('unmount', $unsavedRow);
2317 $unsavedRow.appendTo(this.$tbody()).show();
2318 acf.doAction('remount', $unsavedRow);
2319 return;
2320 }
2321
2322 // Rows from the server (that haven't been changed or deleted) should be appended and shown.
2323 $row = $(rows[index]);
2324 this.$tbody().append($row).show();
2325 acf.doAction('remount', $row);
2326
2327 // Move clone field back to the right spot.
2328 this.$clone().appendTo(this.$tbody());
2329 });
2330 const $addedRows = this.$tbody().find('.acf-added:hidden');
2331
2332 // If there are any new rows that are still hidden, append them to the bottom.
2333 if ($addedRows.length) {
2334 const self = this;
2335 $addedRows.each(function () {
2336 const $addedRow = $(this);
2337 $addedRow.insertBefore(self.$clone()).show();
2338 acf.doAction('remount', $addedRow);
2339 });
2340 }
2341
2342 // Update the page input.
2343 this.$pageInput().val(this.page);
2344 this.maybeDisablePagination();
2345 }).fail(function (jqXHR, textStatus, errorThrown) {
2346 const error = acf.getXhrError(jqXHR);
2347 let message = acf.__('Error loading page');
2348 if ('' !== error) {
2349 message = `${message}: ${error}`;
2350 }
2351 this.showNotice({
2352 text: message,
2353 type: 'warning'
2354 });
2355 });
2356 }
2357 });
2358 acf.registerFieldType(Field);
2359
2360 // register existing conditions
2361 acf.registerConditionForFieldType('hasValue', 'repeater');
2362 acf.registerConditionForFieldType('hasNoValue', 'repeater');
2363 acf.registerConditionForFieldType('lessThan', 'repeater');
2364 acf.registerConditionForFieldType('greaterThan', 'repeater');
2365
2366 // state
2367 var preference = new acf.Model({
2368 name: 'this.collapsedRows',
2369 key: function (key, context) {
2370 // vars
2371 var count = this.get(key + context) || 0;
2372
2373 // update
2374 count++;
2375 this.set(key + context, count, true);
2376
2377 // modify fieldKey
2378 if (count > 1) {
2379 key += '-' + count;
2380 }
2381
2382 // return
2383 return key;
2384 },
2385 load: function (key) {
2386 // vars
2387 var key = this.key(key, 'load');
2388 var data = acf.getPreference(this.name);
2389
2390 // return
2391 if (data && data[key]) {
2392 return data[key];
2393 } else {
2394 return false;
2395 }
2396 },
2397 save: function (key, value) {
2398 // vars
2399 var key = this.key(key, 'save');
2400 var data = acf.getPreference(this.name) || {};
2401
2402 // delete
2403 if (value === null) {
2404 delete data[key];
2405
2406 // append
2407 } else {
2408 data[key] = value;
2409 }
2410
2411 // allow null
2412 if ($.isEmptyObject(data)) {
2413 data = null;
2414 }
2415
2416 // save
2417 acf.setPreference(this.name, data);
2418 }
2419 });
2420 })(jQuery);
2421
2422 /***/ })
2423
2424 /******/ });
2425 /************************************************************************/
2426 /******/ // The module cache
2427 /******/ var __webpack_module_cache__ = {};
2428 /******/
2429 /******/ // The require function
2430 /******/ function __webpack_require__(moduleId) {
2431 /******/ // Check if module is in cache
2432 /******/ var cachedModule = __webpack_module_cache__[moduleId];
2433 /******/ if (cachedModule !== undefined) {
2434 /******/ return cachedModule.exports;
2435 /******/ }
2436 /******/ // Create a new module (and put it into the cache)
2437 /******/ var module = __webpack_module_cache__[moduleId] = {
2438 /******/ // no module.id needed
2439 /******/ // no module.loaded needed
2440 /******/ exports: {}
2441 /******/ };
2442 /******/
2443 /******/ // Execute the module function
2444 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
2445 /******/
2446 /******/ // Return the exports of the module
2447 /******/ return module.exports;
2448 /******/ }
2449 /******/
2450 /************************************************************************/
2451 /******/ /* webpack/runtime/compat get default export */
2452 /******/ (() => {
2453 /******/ // getDefaultExport function for compatibility with non-harmony modules
2454 /******/ __webpack_require__.n = (module) => {
2455 /******/ var getter = module && module.__esModule ?
2456 /******/ () => (module['default']) :
2457 /******/ () => (module);
2458 /******/ __webpack_require__.d(getter, { a: getter });
2459 /******/ return getter;
2460 /******/ };
2461 /******/ })();
2462 /******/
2463 /******/ /* webpack/runtime/define property getters */
2464 /******/ (() => {
2465 /******/ // define getter functions for harmony exports
2466 /******/ __webpack_require__.d = (exports, definition) => {
2467 /******/ for(var key in definition) {
2468 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
2469 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
2470 /******/ }
2471 /******/ }
2472 /******/ };
2473 /******/ })();
2474 /******/
2475 /******/ /* webpack/runtime/hasOwnProperty shorthand */
2476 /******/ (() => {
2477 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
2478 /******/ })();
2479 /******/
2480 /******/ /* webpack/runtime/make namespace object */
2481 /******/ (() => {
2482 /******/ // define __esModule on exports
2483 /******/ __webpack_require__.r = (exports) => {
2484 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
2485 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2486 /******/ }
2487 /******/ Object.defineProperty(exports, '__esModule', { value: true });
2488 /******/ };
2489 /******/ })();
2490 /******/
2491 /************************************************************************/
2492 var __webpack_exports__ = {};
2493 // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
2494 (() => {
2495 "use strict";
2496 /*!********************************************!*\
2497 !*** ./assets/src/js/pro/acf-pro-input.js ***!
2498 \********************************************/
2499 __webpack_require__.r(__webpack_exports__);
2500 /* 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");
2501 /* harmony import */ var _acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_acf_field_repeater_js__WEBPACK_IMPORTED_MODULE_0__);
2502 /* 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");
2503 /* 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__);
2504 /* 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");
2505 /* harmony import */ var _acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_acf_field_gallery_js__WEBPACK_IMPORTED_MODULE_2__);
2506
2507
2508
2509 })();
2510
2511 /******/ })()
2512 ;
2513 //# sourceMappingURL=acf-pro-input.js.map