Skip to content

Commit f13634e

Browse files
authored
Backports: Update 6.5.1 (#223)
* Migrate PHP * Migrate pro input * Update JS * Backport CSS
1 parent f0bb3ac commit f13634e

File tree

13 files changed

+236
-109
lines changed

13 files changed

+236
-109
lines changed
Lines changed: 4 additions & 2 deletions
Loading

assets/src/js/_acf-notice.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
this.type( this.get( 'type' ) );
3737

3838
// text
39-
this.html( '<p>' + acf.strEscape( this.get( 'text' ) ) + '</p>' );
39+
this.html( '<p>' + acf.escHtml( this.get( 'text' ) ) + '</p>' );
4040

4141
// close
4242
if ( this.get( 'dismiss' ) ) {

assets/src/js/_acf-popup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
</a>
187187
</div>
188188
<div class="inner">
189-
<p>${ acf.strEscape( this.get( 'text' ) ) }</p>
189+
<p>${ acf.escHtml( this.get( 'text' ) ) }</p>
190190
<div class="acf-actions">
191191
<button tabindex="0" type="button" data-event="close" class="acf-btn acf-btn-secondary acf-close-popup">${ acf.strEscape(
192192
this.get( 'textCancel' )

assets/src/js/pro/_acf-field-flexible-content.js

Lines changed: 119 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
'click [data-name="add-layout"]': 'onClickAdd',
88
'click [data-name="duplicate-layout"]': 'onClickDuplicate',
99
'click [data-name="collapse-layout"]': 'onClickCollapse',
10+
'click [data-name="remove-layout"]': 'onClickRemove',
1011
'click [data-name="more-layout-actions"]': 'onClickMoreActions',
1112
'click .acf-fc-expand-all': 'onClickExpandAll',
1213
'click .acf-fc-collapse-all': 'onClickCollapseAll',
@@ -56,7 +57,9 @@
5657
},
5758

5859
$button: function () {
59-
return this.$( '.acf-actions:last .button' );
60+
return this.$(
61+
'.acf-fc-top-actions:first .button, .acf-actions:last .button'
62+
);
6063
},
6164

6265
$popup: function () {
@@ -131,13 +134,12 @@
131134
},
132135

133136
allowAdd: function () {
134-
var max = parseInt( this.get( 'max' ) );
135-
return ! max || max > this.val();
137+
return ! this.isFull();
136138
},
137139

138140
isFull: function () {
139-
var max = parseInt( this.get( 'max' ) );
140-
return max && this.val() >= max;
141+
const max = parseInt( this.get( 'max' ) );
142+
return max && this.countLayouts() >= max;
141143
},
142144

143145
addSortable: function ( self ) {
@@ -233,6 +235,7 @@
233235
} else {
234236
this.$control().removeClass( '-empty' );
235237
}
238+
this.maybeDisableAddLayout();
236239

237240
// max
238241
if ( this.isFull() ) {
@@ -241,6 +244,78 @@
241244
this.$button().removeClass( 'disabled' );
242245
}
243246
},
247+
maybeDisableAddLayout: function () {
248+
const self = this;
249+
const isFull = this.isFull();
250+
const buttonLabel = this.$control().data( 'button-label' );
251+
const duplicateLabel = acf.__( 'Duplicate' );
252+
const maxRowsReached = acf
253+
.__( 'Maximum rows reached ({max})' )
254+
.replace( '{max}', this.get( 'max' ) );
255+
256+
// Disable/enable main add buttons
257+
if ( isFull ) {
258+
this.$button().addClass( 'disabled' );
259+
} else {
260+
this.$button().removeClass( 'disabled' );
261+
}
262+
263+
// Process each layout
264+
this.$layouts().each( function () {
265+
const $layout = $( this );
266+
const $addButton = $layout.find(
267+
'[data-name="add-layout"]:first'
268+
);
269+
const $duplicateButton = $layout.find(
270+
'[data-name="duplicate-layout"]:first'
271+
);
272+
const layoutMax = $layout.data( 'max' ) || 0;
273+
const $enableToggle = $( '.acf-toggle-layout.enable' );
274+
275+
// Handle field-level max
276+
if ( isFull ) {
277+
$addButton
278+
.addClass( 'disabled' )
279+
.attr( 'title', maxRowsReached );
280+
$duplicateButton
281+
.addClass( 'disabled' )
282+
.attr( 'title', maxRowsReached );
283+
$enableToggle.addClass( 'disabled' );
284+
} else {
285+
$addButton
286+
.removeClass( 'disabled' )
287+
.attr( 'title', buttonLabel );
288+
$duplicateButton
289+
.removeClass( 'disabled' )
290+
.attr( 'title', duplicateLabel );
291+
$enableToggle.removeClass( 'disabled' );
292+
}
293+
294+
// Handle layout-specific max
295+
if ( layoutMax ) {
296+
const layoutName = $layout.data( 'layout' ) || '';
297+
const layoutCount = self.countLayouts( layoutName );
298+
299+
if ( layoutCount >= layoutMax ) {
300+
const maxLayoutReached = acf
301+
.__(
302+
'Maximum {label} {identifier} reached ({max})'
303+
)
304+
.replace( '{label}', layoutName )
305+
.replace(
306+
'{identifier}',
307+
acf._n( 'layout', 'layouts', layoutMax )
308+
)
309+
.replace( '{max}', layoutMax );
310+
311+
$duplicateButton
312+
.addClass( 'disabled' )
313+
.attr( 'title', maxLayoutReached );
314+
$enableToggle.addClass( 'disabled' );
315+
}
316+
}
317+
} );
318+
},
244319

245320
setActiveLayout: function ( $layout ) {
246321
// Remove active-layout class from all layouts
@@ -267,10 +342,13 @@
267342

268343
countLayouts: function ( name ) {
269344
return this.$layouts().filter( function () {
270-
return $( this ).data( 'layout' ) === name;
345+
const $layout = $( this );
346+
return (
347+
( ! name || $layout.data( 'layout' ) === name ) &&
348+
'0' !== $layout.attr( 'data-enabled' )
349+
);
271350
} ).length;
272351
},
273-
274352
countLayoutsByName: function ( currentLayout ) {
275353
const layoutMax = currentLayout.data( 'max' );
276354
if ( ! layoutMax ) {
@@ -487,20 +565,24 @@
487565
// Disable the layout
488566
layout.attr( 'data-enabled', '0' );
489567
disabledInput.val( '1' );
490-
} else {
491-
// Enable the layout
568+
} else if (
569+
layout.attr( 'data-enabled' ) === '0' &&
570+
this.countLayoutsByName( layout.first() ) &&
571+
! this.isFull()
572+
) {
573+
// Enable the layout only if validation passes
492574
layout.attr( 'data-enabled', '1' );
493575
disabledInput.val( '0' );
494576
}
495577

496578
// Trigger change event to save the state
497579
this.$input().trigger( 'change' );
580+
this.maybeDisableAddLayout();
498581
},
499582
onClickRenameLayout: function ( event, layout ) {
500583
const currentName = layout
501584
.find( '.acf-fc-layout-custom-label:first' )
502585
.val();
503-
504586
const popupOptions = {
505587
context: this,
506588
title: acf.__( 'Rename Layout' ),
@@ -532,7 +614,7 @@
532614
const titleElement = layout.find( '.acf-fc-layout-title:first' );
533615

534616
// Update the visible title
535-
titleElement.text( newName );
617+
titleElement.html( acf.escHtml( newName ) );
536618

537619
if ( newName.length ) {
538620
// Mark as renamed with custom label
@@ -541,7 +623,7 @@
541623
// Restore original title if name is empty
542624
let originalTitle = layout
543625
.find( '.acf-fc-layout-original-title:first' )
544-
.text()
626+
.html()
545627
.trim();
546628

547629
// Remove parentheses from original title
@@ -550,14 +632,13 @@
550632
originalTitle.length - 1
551633
);
552634

553-
titleElement.text( originalTitle );
635+
titleElement.html( acf.escHtml( originalTitle ) );
554636
layout.attr( 'data-renamed', '0' );
555637
}
556638

557639
// Trigger change event to save the state
558640
this.$input().trigger( 'change' );
559641
},
560-
561642
validateRemove: function () {
562643
// return true if allowed
563644
if ( this.allowRemove() ) {
@@ -585,39 +666,43 @@
585666
},
586667

587668
onClickRemove: function ( e, $el ) {
669+
const $layout = $el.closest( '.layout' );
670+
588671
// Bypass confirmation when holding down "shift" key.
589672
if ( e.shiftKey ) {
590-
return this.removeLayout( $el );
673+
return this.removeLayout( $layout );
591674
}
675+
592676
// add class
593-
$el.addClass( '-hover' );
677+
$layout.addClass( '-hover' );
594678

595679
// add tooltip
596680
const tooltipOptions = {
597681
confirmRemove: true,
598682
context: this,
599683
title: acf.__( 'Delete Layout' ),
600-
text: acf.__( 'Are you sure you want to delete this layout?' ),
684+
text: acf.__( 'Are you sure you want to delete the layout?' ),
601685
textConfirm: acf.__( 'Delete' ),
602686
textCancel: acf.__( 'Cancel' ),
603-
openedBy: $el
687+
openedBy: $layout
604688
.find( 'a[data-name="more-layout-actions"]' )
605689
.first(),
606690
width: '500px',
607-
confirm: function () {
608-
this.removeLayout( $el );
691+
confirm: function ( e, $el ) {
692+
this.removeLayout( $layout );
609693
},
610694
cancel: function () {
611-
$el.removeClass( '-hover' );
695+
$layout.removeClass( '-hover' );
612696
},
613697
};
698+
614699
// Check if layout has a custom label
615-
const customLabel = $el.data( 'label' );
616-
if ( customLabel && customLabel.length ) {
700+
const customLabel = $layout.data( 'label' );
701+
if ( customLabel.length ) {
617702
// Customize the popup title and text with the layout label
618703
tooltipOptions.title = acf
619704
.__( 'Delete %s' )
620-
.replace( '%s', acf.strEscape( customLabel ) );
705+
.replace( '%s', acf.escHtml( customLabel ) );
621706
tooltipOptions.text = acf
622707
.__( 'Are you sure you want to delete %s?' )
623708
.replace( '%s', customLabel );
@@ -626,7 +711,6 @@
626711
// Create and show the confirmation popup
627712
acf.newPopup( tooltipOptions );
628713
},
629-
630714
removeLayout: function ( $layout ) {
631715
// reference
632716
var self = this;
@@ -684,9 +768,6 @@
684768
confirm: function ( e, $el ) {
685769
// Check if the clicked element is a toggle action
686770
const action = $el.data( 'action' );
687-
if ( action === 'remove-layout' ) {
688-
this.onClickRemove( e, $layout );
689-
}
690771
if ( action === 'toggle-layout' ) {
691772
this.onClickToggleLayout( e, $layout );
692773
}
@@ -822,20 +903,15 @@
822903
this.position();
823904
},
824905
show: function () {
825-
const $flexibleContent = this.get( 'target' ).closest(
826-
'.acf-flexible-content'
827-
);
828-
$( $flexibleContent ).append( this.$el );
906+
$( 'body' ).append( this.$el );
829907
},
830908
position: function () {
831909
const $popup = this.$el;
832910
const $target = this.get( 'target' );
833911
const $container = $target.closest( '.acf-flexible-content' );
834912
positionPopup( $popup, $target, $container, 8 );
835913
},
836-
} );
837-
838-
/**
914+
} ); /**
839915
* MoreLayoutActionsPopup
840916
*
841917
* Popup for showing more layout actions (remove, toggle, rename)
@@ -858,17 +934,17 @@
858934
this.$el.removeClass( 'enable-layout' );
859935
}
860936

937+
const context = this.get( 'context' ) || this;
861938
const self = this;
862939
setTimeout( function () {
863940
self.$el.find( 'a' ).first().trigger( 'focus' );
941+
context.maybeDisableAddLayout();
864942
}, 1 );
865943
},
866944

867945
show: function () {
868-
const $layout = this.get( 'target' ).closest( '.layout' );
869-
$layout.append( this.$el );
946+
$( 'body' ).append( this.$el );
870947
},
871-
872948
position: function () {
873949
const $popup = this.$el;
874950
const $target = this.get( 'target' );
@@ -1015,7 +1091,6 @@
10151091
if ( ! $target.length || ! $container.length ) return;
10161092

10171093
const targetOffset = $target.offset();
1018-
const containerOffset = $container.offset();
10191094
const targetWidth = $target.outerWidth();
10201095
const targetHeight = $target.outerHeight();
10211096
const popupWidth = $popup.outerWidth();
@@ -1025,8 +1100,7 @@
10251100
const windowHeight = $( window ).height();
10261101

10271102
let left, positionClass;
1028-
let top =
1029-
targetOffset.top - containerOffset.top + targetHeight + offset;
1103+
let top = targetOffset.top + targetHeight + offset;
10301104
let isAbove = false;
10311105

10321106
// Check if popup would be cut off at bottom of viewport
@@ -1035,29 +1109,23 @@
10351109
windowScrollTop + windowHeight &&
10361110
targetOffset.top - popupHeight - offset > windowScrollTop
10371111
) {
1038-
top = targetOffset.top - containerOffset.top - popupHeight - offset;
1112+
top = targetOffset.top - popupHeight - offset;
10391113
isAbove = true;
10401114
}
10411115

10421116
if ( isRTL ) {
1043-
left = targetOffset.left - containerOffset.left;
1117+
left = targetOffset.left;
10441118
positionClass = isAbove ? 'bottom-left' : 'top-left';
10451119
} else {
1046-
left =
1047-
targetOffset.left -
1048-
containerOffset.left +
1049-
targetWidth -
1050-
popupWidth;
1120+
left = targetOffset.left + targetWidth - popupWidth;
10511121
positionClass = isAbove ? 'bottom-right' : 'top-right';
10521122
}
10531123

10541124
$popup
10551125
.removeClass( 'top-right bottom-right top-left bottom-left' )
10561126
.css( { position: 'absolute', top: top, left: left } )
10571127
.addClass( positionClass );
1058-
};
1059-
1060-
/**
1128+
}; /**
10611129
* conditions
10621130
*
10631131
* description

0 commit comments

Comments
 (0)