diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-admin/js/customize-controls.js --- a/wp/wp-admin/js/customize-controls.js Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-admin/js/customize-controls.js Fri Sep 05 18:52:52 2025 +0200 @@ -1530,7 +1530,7 @@ } // Expand/Collapse accordion sections on click. - section.container.find( '.accordion-section-title, .customize-section-back' ).on( 'click keydown', function( event ) { + section.container.find( '.accordion-section-title button, .customize-section-back, .accordion-section-title[tabindex]' ).on( 'click keydown', function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } @@ -1605,7 +1605,7 @@ content = section.contentContainer, overlay = section.headContainer.closest( '.wp-full-overlay' ), backBtn = content.find( '.customize-section-back' ), - sectionTitle = section.headContainer.find( '.accordion-section-title' ).first(), + sectionTitle = section.headContainer.find( '.accordion-section-title button, .accordion-section-title[tabindex]' ).first(), expand, panel; if ( expanded && ! content.hasClass( 'open' ) ) { @@ -1615,9 +1615,6 @@ } else { expand = function() { section._animateChangeExpanded( function() { - sectionTitle.attr( 'tabindex', '-1' ); - backBtn.attr( 'tabindex', '0' ); - backBtn.trigger( 'focus' ); content.css( 'top', '' ); container.scrollTop( 0 ); @@ -1663,8 +1660,6 @@ } } section._animateChangeExpanded( function() { - backBtn.attr( 'tabindex', '-1' ); - sectionTitle.attr( 'tabindex', '0' ); sectionTitle.trigger( 'focus' ); content.css( 'top', '' ); @@ -2699,7 +2694,7 @@ container = section.headContainer.closest( '.wp-full-overlay-sidebar-content' ), content = section.contentContainer, backBtn = content.find( '.customize-section-back' ), - sectionTitle = section.headContainer.find( '.accordion-section-title' ).first(), + sectionTitle = section.headContainer.find( '.accordion-section-title button, .accordion-section-title[tabindex]' ).first(), body = $( document.body ), expand, panel; @@ -2719,9 +2714,6 @@ } else { expand = function() { section._animateChangeExpanded( function() { - sectionTitle.attr( 'tabindex', '-1' ); - backBtn.attr( 'tabindex', '0' ); - backBtn.trigger( 'focus' ); content.css( 'top', '' ); container.scrollTop( 0 ); @@ -2752,8 +2744,6 @@ } } section._animateChangeExpanded( function() { - backBtn.attr( 'tabindex', '-1' ); - sectionTitle.attr( 'tabindex', '0' ); sectionTitle.trigger( 'focus' ); content.css( 'top', '' ); @@ -2843,7 +2833,7 @@ var meta, panel = this; // Expand/Collapse accordion sections on click. - panel.headContainer.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { + panel.headContainer.find( '.accordion-section-title button, .accordion-section-title[tabindex]' ).on( 'click keydown', function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } @@ -2947,7 +2937,7 @@ accordionSection = panel.contentContainer, overlay = accordionSection.closest( '.wp-full-overlay' ), container = accordionSection.closest( '.wp-full-overlay-sidebar-content' ), - topPanel = panel.headContainer.find( '.accordion-section-title' ), + topPanel = panel.headContainer.find( '.accordion-section-title button, .accordion-section-title[tabindex]' ), backBtn = accordionSection.find( '.customize-panel-back' ), childSections = panel.sections(), skipTransition; @@ -2974,9 +2964,6 @@ } ); } else { panel._animateChangeExpanded( function() { - topPanel.attr( 'tabindex', '-1' ); - backBtn.attr( 'tabindex', '0' ); - backBtn.trigger( 'focus' ); accordionSection.css( 'top', '' ); container.scrollTop( 0 ); @@ -2996,8 +2983,6 @@ skipTransition = accordionSection.hasClass( 'skip-transition' ); if ( ! skipTransition ) { panel._animateChangeExpanded( function() { - topPanel.attr( 'tabindex', '0' ); - backBtn.attr( 'tabindex', '-1' ); topPanel.focus(); accordionSection.css( 'top', '' ); @@ -4602,26 +4587,29 @@ * @return {Object} Options */ calculateImageSelectOptions: function( attachment, controller ) { - var control = controller.get( 'control' ), - flexWidth = !! parseInt( control.params.flex_width, 10 ), - flexHeight = !! parseInt( control.params.flex_height, 10 ), - realWidth = attachment.get( 'width' ), - realHeight = attachment.get( 'height' ), - xInit = parseInt( control.params.width, 10 ), - yInit = parseInt( control.params.height, 10 ), - ratio = xInit / yInit, - xImg = xInit, - yImg = yInit, + var control = controller.get( 'control' ), + flexWidth = !! parseInt( control.params.flex_width, 10 ), + flexHeight = !! parseInt( control.params.flex_height, 10 ), + realWidth = attachment.get( 'width' ), + realHeight = attachment.get( 'height' ), + xInit = parseInt( control.params.width, 10 ), + yInit = parseInt( control.params.height, 10 ), + requiredRatio = xInit / yInit, + realRatio = realWidth / realHeight, + xImg = xInit, + yImg = yInit, x1, y1, imgSelectOptions; + controller.set( 'hasRequiredAspectRatio', control.hasRequiredAspectRatio( requiredRatio, realRatio ) ); + controller.set( 'suggestedCropSize', { width: realWidth, height: realHeight, x1: 0, y1: 0, x2: xInit, y2: yInit } ); controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) ); - if ( realWidth / realHeight > ratio ) { + if ( realRatio > requiredRatio ) { yInit = realHeight; - xInit = yInit * ratio; + xInit = yInit * requiredRatio; } else { xInit = realWidth; - yInit = xInit / ratio; + yInit = xInit / requiredRatio; } x1 = ( realWidth - xInit ) / 2; @@ -4662,13 +4650,13 @@ /** * Return whether the image must be cropped, based on required dimensions. * - * @param {boolean} flexW - * @param {boolean} flexH - * @param {number} dstW - * @param {number} dstH - * @param {number} imgW - * @param {number} imgH - * @return {boolean} + * @param {boolean} flexW Width is flexible. + * @param {boolean} flexH Height is flexible. + * @param {number} dstW Required width. + * @param {number} dstH Required height. + * @param {number} imgW Provided image's width. + * @param {number} imgH Provided image's height. + * @return {boolean} Whether cropping is required. */ mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) { if ( true === flexW && true === flexH ) { @@ -4695,6 +4683,25 @@ }, /** + * Check if the image's aspect ratio essentially matches the required aspect ratio. + * + * Floating point precision is low, so this allows a small tolerance. This + * tolerance allows for images over 100,000 px on either side to still trigger + * the cropping flow. + * + * @param {number} requiredRatio Required image ratio. + * @param {number} realRatio Provided image ratio. + * @return {boolean} Whether the image has the required aspect ratio. + */ + hasRequiredAspectRatio: function ( requiredRatio, realRatio ) { + if ( Math.abs( requiredRatio - realRatio ) < 0.000001 ) { + return true; + } + + return false; + }, + + /** * If cropping was skipped, apply the image data directly to the setting. */ onSkippedCrop: function() {