From 1026f824a73853f2733e8f58c4df966fff57ffd8 Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Tue, 20 Jun 2023 21:33:44 -0500 Subject: [PATCH 1/9] Add logic to use low-res image while high-res one is loading We need to have two elements in the DOM inside the lightbox because otherwise the image flickers when we change the src. I removed the src and srcset attributes from the responsive image when the larger one is loaded to signal that the low-res one is no longer in use. --- lib/block-supports/behaviors.php | 43 +++++++++++++++-- .../block-library/src/image/interactivity.js | 46 ++++++++++++------- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index 58c8ca7200102..ecb96ec199bc5 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -87,11 +87,16 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { // We want to store the src in the context so we can set it dynamically when the lightbox is opened. $z = new WP_HTML_Tag_Processor( $content ); $z->next_tag( 'img' ); + $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); + $img_width = $img_metadata['width']; + $img_height = $img_metadata['height']; + if ( isset( $block['attrs']['id'] ) ) { $img_src = wp_get_attachment_url( $block['attrs']['id'] ); } else { $img_src = $z->get_attribute( 'src' ); } + $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); $w = new WP_HTML_Tag_Processor( $content ); $w->next_tag( 'figure' ); @@ -99,7 +104,26 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $w->set_attribute( 'data-wp-interactive', true ); $w->set_attribute( 'data-wp-context', - sprintf( '{ "core":{ "image": { "initialized": false, "imageSrc": "%s", "lightboxEnabled": false, "lightboxAnimation": "%s", "hideAnimationEnabled": false } } }', $img_src, $lightbox_animation ) + sprintf( + '{ "core": + { "image": + { "initialized": false, + "lightboxEnabled": false, + "hideAnimationEnabled": false, + "lightboxAnimation": "%s", + "imageSrc": "%s", + "imageSrcSet": "%s", + "targetWidth": "%s", + "targetHeight": "%s" + } + } + }', + $lightbox_animation, + $img_src, + $img_srcset, + $img_width, + $img_height + ) ); $body_content = $w->get_updated_html(); @@ -114,9 +138,19 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { // Add src to the modal image. $m = new WP_HTML_Tag_Processor( $content ); + $m->next_tag( 'figure' ); + $m->add_class( 'responsive-image' ); $m->next_tag( 'img' ); - $m->set_attribute( 'data-wp-bind--src', 'selectors.core.image.imageSrc' ); - $modal_content = $m->get_updated_html(); + $m->set_attribute( 'data-wp-bind--src', 'selectors.core.image.responsiveImgSrc' ); + $m->set_attribute( 'data-wp-bind--srcset', 'selectors.core.image.responsiveImgSrcSet' ); + $initial_image_content = $m->get_updated_html(); + + $q = new WP_HTML_Tag_Processor( $content ); + $q->next_tag( 'figure' ); + $q->add_class( 'enlarged-image' ); + $q->next_tag( 'img' ); + $q->set_attribute( 'data-wp-bind--src', 'selectors.core.image.enlargedImgSrc' ); + $enlarged_image_content = $q->get_updated_html(); $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); @@ -142,7 +176,8 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { - $modal_content + $initial_image_content + $enlarged_image_content
HTML; diff --git a/packages/block-library/src/image/interactivity.js b/packages/block-library/src/image/interactivity.js index 2ef370496a894..a5b2373d2fd4f 100644 --- a/packages/block-library/src/image/interactivity.js +++ b/packages/block-library/src/image/interactivity.js @@ -27,25 +27,27 @@ store( { window.document.activeElement; context.core.image.scrollDelta = 0; + context.core.image.lightboxEnabled = true; + if ( context.core.image.lightboxAnimation === 'zoom' ) { + setZoomStyles( + event.target.nextElementSibling, + context, + event + ); + } + // Hide overflow only when the animation is in progress, + // otherwise the removal of the scrollbars will draw attention + // to itself and look like an error + document.documentElement.classList.add( + 'has-lightbox-open' + ); + // Since the img is hidden and its src not loaded until // the lightbox is opened, let's create an img element on the fly // so we can get the dimensions we need to calculate the styles const imgDom = document.createElement( 'img' ); - imgDom.onload = function () { - // Enable the lightbox only after the image - // is loaded to prevent flashing of unstyled content - context.core.image.lightboxEnabled = true; - if ( context.core.image.lightboxAnimation === 'zoom' ) { - setZoomStyles( imgDom, context, event ); - } - - // Hide overflow only when the animation is in progress, - // otherwise the removal of the scrollbars will draw attention - // to itself and look like an error - document.documentElement.classList.add( - 'has-lightbox-open' - ); + context.core.image.activateLargeImage = true; }; imgDom.setAttribute( 'src', context.core.image.imageSrc ); }, @@ -131,7 +133,17 @@ store( { roleAttribute: ( { context } ) => { return context.core.image.lightboxEnabled ? 'dialog' : ''; }, - imageSrc: ( { context } ) => { + responsiveImgSrc: ( { context } ) => { + return context.core.image.activateLargeImage + ? '' + : context.core.image.imageSrc; + }, + responsiveImgSrcSet: ( { context } ) => { + return context.core.image.activateLargeImage + ? '' + : context.core.image.imageSrcSet; + }, + enlargedImgSrc: ( { context } ) => { return context.core.image.initialized ? context.core.image.imageSrc : ''; @@ -163,8 +175,8 @@ store( { } ); function setZoomStyles( imgDom, context, event ) { - let targetWidth = imgDom.naturalWidth; - let targetHeight = imgDom.naturalHeight; + let targetWidth = context.core.image.targetWidth; + let targetHeight = context.core.image.targetHeight; const verticalPadding = 40; From 8b4ae2009536945dba3fbae2b3d8555cbc447da2 Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Wed, 21 Jun 2023 11:45:27 -0500 Subject: [PATCH 2/9] Add logic to preload image on hover --- lib/block-supports/behaviors.php | 3 ++- packages/block-library/src/image/interactivity.js | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index ecb96ec199bc5..c35f08b98ebc1 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -110,6 +110,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { { "initialized": false, "lightboxEnabled": false, "hideAnimationEnabled": false, + "preloadInitialized": false, "lightboxAnimation": "%s", "imageSrc": "%s", "imageSrcSet": "%s", @@ -131,7 +132,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $img = null; preg_match( '/]+>/', $content, $img ); $button = '
- ' + ' . $img[0] . '
'; $body_content = preg_replace( '/]+>/', $button, $body_content ); diff --git a/packages/block-library/src/image/interactivity.js b/packages/block-library/src/image/interactivity.js index a5b2373d2fd4f..aa17dd61335e9 100644 --- a/packages/block-library/src/image/interactivity.js +++ b/packages/block-library/src/image/interactivity.js @@ -45,6 +45,7 @@ store( { // Since the img is hidden and its src not loaded until // the lightbox is opened, let's create an img element on the fly // so we can get the dimensions we need to calculate the styles + context.core.image.preloadInitialized = true; const imgDom = document.createElement( 'img' ); imgDom.onload = function () { context.core.image.activateLargeImage = true; @@ -154,6 +155,18 @@ store( { effects: { core: { image: { + preloadLightboxImage: ( { context, ref } ) => { + ref.addEventListener( 'mouseover', () => { + if ( ! context.core.image.preloadInitialized ) { + context.core.image.preloadInitialized = true; + const imgDom = document.createElement( 'img' ); + imgDom.setAttribute( + 'src', + context.core.image.imageSrc + ); + } + } ); + }, initLightbox: async ( { context, ref } ) => { context.core.image.figureRef = ref.querySelector( 'figure' ); From 135105c8d94a3a4fc1f5f71583f274ac5c50f190 Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Wed, 21 Jun 2023 16:21:40 -0500 Subject: [PATCH 3/9] Update tests --- lib/block-supports/behaviors.php | 13 ++++++++----- test/e2e/specs/editor/blocks/image.spec.js | 22 ++++++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index c35f08b98ebc1..ba0078a2dc349 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -87,16 +87,19 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { // We want to store the src in the context so we can set it dynamically when the lightbox is opened. $z = new WP_HTML_Tag_Processor( $content ); $z->next_tag( 'img' ); - $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); - $img_width = $img_metadata['width']; - $img_height = $img_metadata['height']; if ( isset( $block['attrs']['id'] ) ) { $img_src = wp_get_attachment_url( $block['attrs']['id'] ); + $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); + $img_width = $img_metadata['width']; + $img_height = $img_metadata['height']; + $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); } else { $img_src = $z->get_attribute( 'src' ); + $img_dimensions = getimagesize( $img_src ); + $img_width = $img_dimensions[0]; + $img_height = $img_dimensions[1]; } - $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); $w = new WP_HTML_Tag_Processor( $content ); $w->next_tag( 'figure' ); @@ -121,7 +124,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { }', $lightbox_animation, $img_src, - $img_srcset, + $img_srcset ?? '', $img_width, $img_height ) diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index 5f802d0e85063..006a5dac2e3e7 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -987,13 +987,19 @@ test.describe( 'Image - interactivity', () => { const lightbox = page.locator( '.wp-lightbox-overlay' ); await expect( lightbox ).toBeHidden(); - const image = lightbox.locator( 'img' ); + const responsiveImage = lightbox.locator( '.responsive-image img' ); + const enlargedImage = lightbox.locator( '.enlarged-image img' ); - await expect( image ).toHaveAttribute( 'src', '' ); + await expect( responsiveImage ).toHaveAttribute( + 'src', + new RegExp( filename ) + ); + await expect( enlargedImage ).toHaveAttribute( 'src', '' ); await page.getByRole( 'button', { name: 'Enlarge image' } ).click(); - await expect( image ).toHaveAttribute( + await expect( responsiveImage ).toHaveAttribute( 'src', '' ); + await expect( enlargedImage ).toHaveAttribute( 'src', new RegExp( filename ) ); @@ -1176,12 +1182,16 @@ test.describe( 'Image - interactivity', () => { await page.goto( `/?p=${ postId }` ); const lightbox = page.locator( '.wp-lightbox-overlay' ); - const imageDom = lightbox.locator( 'img' ); - await expect( imageDom ).toHaveAttribute( 'src', '' ); + const responsiveImage = lightbox.locator( '.responsive-image img' ); + const enlargedImage = lightbox.locator( '.enlarged-image img' ); + + await expect( responsiveImage ).toHaveAttribute( 'src', imgUrl ); + await expect( enlargedImage ).toHaveAttribute( 'src', '' ); await page.getByRole( 'button', { name: 'Enlarge image' } ).click(); - await expect( imageDom ).toHaveAttribute( 'src', imgUrl ); + await expect( responsiveImage ).toHaveAttribute( 'src', '' ); + await expect( enlargedImage ).toHaveAttribute( 'src', imgUrl ); } ); } ); From 54047cbedb032e84a41789356833edaeea9b7d07 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Thu, 22 Jun 2023 13:24:31 +0200 Subject: [PATCH 4/9] PHP format --- lib/block-supports/behaviors.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index ba0078a2dc349..fdd9248cf9f7c 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -89,16 +89,16 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $z->next_tag( 'img' ); if ( isset( $block['attrs']['id'] ) ) { - $img_src = wp_get_attachment_url( $block['attrs']['id'] ); + $img_src = wp_get_attachment_url( $block['attrs']['id'] ); $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); $img_width = $img_metadata['width']; $img_height = $img_metadata['height']; - $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); + $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); } else { - $img_src = $z->get_attribute( 'src' ); + $img_src = $z->get_attribute( 'src' ); $img_dimensions = getimagesize( $img_src ); - $img_width = $img_dimensions[0]; - $img_height = $img_dimensions[1]; + $img_width = $img_dimensions[0]; + $img_height = $img_dimensions[1]; } $w = new WP_HTML_Tag_Processor( $content ); @@ -124,7 +124,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { }', $lightbox_animation, $img_src, - $img_srcset ?? '', + $img_srcset ? $img_srcset : '', $img_width, $img_height ) From b4a3c1d9698df816f2002163712a94e39585d25a Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Thu, 22 Jun 2023 17:41:15 -0500 Subject: [PATCH 5/9] Prevent responsive images from being loaded unnecessarily The src attribute on the img elements was causing the srcset attribute to be added as well before the Interactivity API could remove them, causing images to be loaded before they were needed and in the wrong size. This commit removes the src attribute from the img elements before they are output to the DOM, and also updates the tests. --- lib/block-supports/behaviors.php | 2 ++ .../block-library/src/image/interactivity.js | 20 +++++++++++++------ test/e2e/specs/editor/blocks/image.spec.js | 7 ++----- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index fdd9248cf9f7c..b4c8563c375d6 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -145,6 +145,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $m->next_tag( 'figure' ); $m->add_class( 'responsive-image' ); $m->next_tag( 'img' ); + $m->set_attribute( 'src', '' ); $m->set_attribute( 'data-wp-bind--src', 'selectors.core.image.responsiveImgSrc' ); $m->set_attribute( 'data-wp-bind--srcset', 'selectors.core.image.responsiveImgSrcSet' ); $initial_image_content = $m->get_updated_html(); @@ -153,6 +154,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $q->next_tag( 'figure' ); $q->add_class( 'enlarged-image' ); $q->next_tag( 'img' ); + $q->set_attribute( 'src', '' ); $q->set_attribute( 'data-wp-bind--src', 'selectors.core.image.enlargedImgSrc' ); $enlarged_image_content = $q->get_updated_html(); diff --git a/packages/block-library/src/image/interactivity.js b/packages/block-library/src/image/interactivity.js index aa17dd61335e9..1a259958fc953 100644 --- a/packages/block-library/src/image/interactivity.js +++ b/packages/block-library/src/image/interactivity.js @@ -135,14 +135,22 @@ store( { return context.core.image.lightboxEnabled ? 'dialog' : ''; }, responsiveImgSrc: ( { context } ) => { - return context.core.image.activateLargeImage - ? '' - : context.core.image.imageSrc; + if ( + ! context.core.image.initialized || + context.core.image.activateLargeImage + ) { + return ''; + } + return context.core.image.imageSrc; }, responsiveImgSrcSet: ( { context } ) => { - return context.core.image.activateLargeImage - ? '' - : context.core.image.imageSrcSet; + if ( + ! context.core.image.initialized || + context.core.image.activateLargeImage + ) { + return ''; + } + return context.core.image.imageSrcSet; }, enlargedImgSrc: ( { context } ) => { return context.core.image.initialized diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index 006a5dac2e3e7..3292b044539c4 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -990,10 +990,7 @@ test.describe( 'Image - interactivity', () => { const responsiveImage = lightbox.locator( '.responsive-image img' ); const enlargedImage = lightbox.locator( '.enlarged-image img' ); - await expect( responsiveImage ).toHaveAttribute( - 'src', - new RegExp( filename ) - ); + await expect( responsiveImage ).toHaveAttribute( 'src', '' ); await expect( enlargedImage ).toHaveAttribute( 'src', '' ); await page.getByRole( 'button', { name: 'Enlarge image' } ).click(); @@ -1185,7 +1182,7 @@ test.describe( 'Image - interactivity', () => { const responsiveImage = lightbox.locator( '.responsive-image img' ); const enlargedImage = lightbox.locator( '.enlarged-image img' ); - await expect( responsiveImage ).toHaveAttribute( 'src', imgUrl ); + await expect( responsiveImage ).toHaveAttribute( 'src', '' ); await expect( enlargedImage ).toHaveAttribute( 'src', '' ); await page.getByRole( 'button', { name: 'Enlarge image' } ).click(); From 549e7952bc9dab62a6fe136d0e84eefe0fa3adee Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 23 Jun 2023 12:08:47 +0200 Subject: [PATCH 6/9] Prevent warning of undefined variable --- lib/block-supports/behaviors.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index b4c8563c375d6..b4f036486cc28 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -88,6 +88,8 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $z = new WP_HTML_Tag_Processor( $content ); $z->next_tag( 'img' ); + $img_srcset = ''; + if ( isset( $block['attrs']['id'] ) ) { $img_src = wp_get_attachment_url( $block['attrs']['id'] ); $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); @@ -124,7 +126,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { }', $lightbox_animation, $img_src, - $img_srcset ? $img_srcset : '', + $img_srcset, $img_width, $img_height ) From c0baefa40347f021059d39a5ae9f79c7441caec5 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Fri, 23 Jun 2023 12:11:05 +0200 Subject: [PATCH 7/9] Prevent warning of undefined variable - refactored --- lib/block-supports/behaviors.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index b4f036486cc28..ea4ab0e153401 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -88,8 +88,6 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $z = new WP_HTML_Tag_Processor( $content ); $z->next_tag( 'img' ); - $img_srcset = ''; - if ( isset( $block['attrs']['id'] ) ) { $img_src = wp_get_attachment_url( $block['attrs']['id'] ); $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); @@ -101,6 +99,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $img_dimensions = getimagesize( $img_src ); $img_width = $img_dimensions[0]; $img_height = $img_dimensions[1]; + $img_srcset = ''; } $w = new WP_HTML_Tag_Processor( $content ); From e713211f9d906fb85929dc36f18daedfe0b5427d Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Fri, 23 Jun 2023 06:50:25 -0500 Subject: [PATCH 8/9] Replace getimagesize() with wp_getimagesize() --- lib/block-supports/behaviors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index ea4ab0e153401..437a998077534 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -96,7 +96,7 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); } else { $img_src = $z->get_attribute( 'src' ); - $img_dimensions = getimagesize( $img_src ); + $img_dimensions = wp_getimagesize( $img_src ); $img_width = $img_dimensions[0]; $img_height = $img_dimensions[1]; $img_srcset = ''; From 7d3b3b55925b6aab067fa6250f17d85316151b13 Mon Sep 17 00:00:00 2001 From: Ricardo Artemio Morales Date: Fri, 23 Jun 2023 18:00:20 -0500 Subject: [PATCH 9/9] Resolve image flash when opening lightbox Rather than allowing the browser to pick the lightbox's responsive image, we now explicitly read the currentSrc attribute from the reference image and also prevent users from opening the lightbox until the reference image is fully loaded. Doing this, we can ensure the zoom animation plays smoothly and there are no oddities in the UX. --- lib/block-supports/behaviors.php | 35 ++++++++------- .../block-library/src/image/interactivity.js | 45 +++++++++++-------- test/e2e/specs/editor/blocks/image.spec.js | 10 ++++- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index 437a998077534..b435d769ef340 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -89,17 +89,17 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $z->next_tag( 'img' ); if ( isset( $block['attrs']['id'] ) ) { - $img_src = wp_get_attachment_url( $block['attrs']['id'] ); - $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); - $img_width = $img_metadata['width']; - $img_height = $img_metadata['height']; - $img_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); + $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] ); + $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); + $img_width = $img_metadata['width']; + $img_height = $img_metadata['height']; + $img_uploaded_srcset = wp_get_attachment_image_srcset( $block['attrs']['id'] ); } else { - $img_src = $z->get_attribute( 'src' ); - $img_dimensions = wp_getimagesize( $img_src ); - $img_width = $img_dimensions[0]; - $img_height = $img_dimensions[1]; - $img_srcset = ''; + $img_uploaded_src = $z->get_attribute( 'src' ); + $img_dimensions = wp_getimagesize( $img_uploaded_src ); + $img_width = $img_dimensions[0]; + $img_height = $img_dimensions[1]; + $img_uploaded_srcset = ''; } $w = new WP_HTML_Tag_Processor( $content ); @@ -111,12 +111,14 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { sprintf( '{ "core": { "image": - { "initialized": false, + { "imageLoaded": false, + "initialized": false, "lightboxEnabled": false, "hideAnimationEnabled": false, "preloadInitialized": false, "lightboxAnimation": "%s", - "imageSrc": "%s", + "imageUploadedSrc": "%s", + "imageCurrentSrc": "", "imageSrcSet": "%s", "targetWidth": "%s", "targetHeight": "%s" @@ -124,17 +126,19 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { } }', $lightbox_animation, - $img_src, - $img_srcset, + $img_uploaded_src, + $img_uploaded_srcset, $img_width, $img_height ) ); + $w->next_tag( 'img' ); + $w->set_attribute( 'data-wp-effect', 'effects.core.image.setCurrentSrc' ); $body_content = $w->get_updated_html(); // Wrap the image in the body content with a button. $img = null; - preg_match( '/]+>/', $content, $img ); + preg_match( '/]+>/', $body_content, $img ); $button = '
' . $img[0] . @@ -148,7 +152,6 @@ function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $m->next_tag( 'img' ); $m->set_attribute( 'src', '' ); $m->set_attribute( 'data-wp-bind--src', 'selectors.core.image.responsiveImgSrc' ); - $m->set_attribute( 'data-wp-bind--srcset', 'selectors.core.image.responsiveImgSrcSet' ); $initial_image_content = $m->get_updated_html(); $q = new WP_HTML_Tag_Processor( $content ); diff --git a/packages/block-library/src/image/interactivity.js b/packages/block-library/src/image/interactivity.js index 1a259958fc953..6560cef9e0243 100644 --- a/packages/block-library/src/image/interactivity.js +++ b/packages/block-library/src/image/interactivity.js @@ -22,6 +22,11 @@ store( { core: { image: { showLightbox: ( { context, event } ) => { + // We can't initialize the lightbox until the reference + // image is loaded, otherwise the UX is broken. + if ( ! context.core.image.imageLoaded ) { + return; + } context.core.image.initialized = true; context.core.image.lastFocusedElement = window.document.activeElement; @@ -50,7 +55,10 @@ store( { imgDom.onload = function () { context.core.image.activateLargeImage = true; }; - imgDom.setAttribute( 'src', context.core.image.imageSrc ); + imgDom.setAttribute( + 'src', + context.core.image.imageUploadedSrc + ); }, hideLightbox: async ( { context, event } ) => { context.core.image.hideAnimationEnabled = true; @@ -135,26 +143,13 @@ store( { return context.core.image.lightboxEnabled ? 'dialog' : ''; }, responsiveImgSrc: ( { context } ) => { - if ( - ! context.core.image.initialized || - context.core.image.activateLargeImage - ) { - return ''; - } - return context.core.image.imageSrc; - }, - responsiveImgSrcSet: ( { context } ) => { - if ( - ! context.core.image.initialized || - context.core.image.activateLargeImage - ) { - return ''; - } - return context.core.image.imageSrcSet; + return context.core.image.activateLargeImage + ? '' + : context.core.image.imageCurrentSrc; }, enlargedImgSrc: ( { context } ) => { return context.core.image.initialized - ? context.core.image.imageSrc + ? context.core.image.imageUploadedSrc : ''; }, }, @@ -163,6 +158,18 @@ store( { effects: { core: { image: { + setCurrentSrc: ( { context, ref } ) => { + if ( ref.complete ) { + context.core.image.imageLoaded = true; + context.core.image.imageCurrentSrc = ref.currentSrc; + } else { + ref.addEventListener( 'load', function () { + context.core.image.imageLoaded = true; + context.core.image.imageCurrentSrc = + this.currentSrc; + } ); + } + }, preloadLightboxImage: ( { context, ref } ) => { ref.addEventListener( 'mouseover', () => { if ( ! context.core.image.preloadInitialized ) { @@ -170,7 +177,7 @@ store( { const imgDom = document.createElement( 'img' ); imgDom.setAttribute( 'src', - context.core.image.imageSrc + context.core.image.imageUploadedSrc ); } } ); diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index 3292b044539c4..0735b9a7573e6 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -990,7 +990,10 @@ test.describe( 'Image - interactivity', () => { const responsiveImage = lightbox.locator( '.responsive-image img' ); const enlargedImage = lightbox.locator( '.enlarged-image img' ); - await expect( responsiveImage ).toHaveAttribute( 'src', '' ); + await expect( responsiveImage ).toHaveAttribute( + 'src', + new RegExp( filename ) + ); await expect( enlargedImage ).toHaveAttribute( 'src', '' ); await page.getByRole( 'button', { name: 'Enlarge image' } ).click(); @@ -1182,7 +1185,10 @@ test.describe( 'Image - interactivity', () => { const responsiveImage = lightbox.locator( '.responsive-image img' ); const enlargedImage = lightbox.locator( '.enlarged-image img' ); - await expect( responsiveImage ).toHaveAttribute( 'src', '' ); + await expect( responsiveImage ).toHaveAttribute( + 'src', + new RegExp( imgUrl ) + ); await expect( enlargedImage ).toHaveAttribute( 'src', '' ); await page.getByRole( 'button', { name: 'Enlarge image' } ).click();