diff --git a/projects/plugins/jetpack/changelog/improve-carousel-a11y b/projects/plugins/jetpack/changelog/improve-carousel-a11y new file mode 100644 index 0000000000000..0b974fcbdfaca --- /dev/null +++ b/projects/plugins/jetpack/changelog/improve-carousel-a11y @@ -0,0 +1,4 @@ +Significance: patch +Type: bugfix + +Carousel: Further improve accessibility by being more selective over which images to apply attributes to diff --git a/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js b/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js index 63b684aeb9a91..be3a01c0657fc 100644 --- a/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js +++ b/projects/plugins/jetpack/modules/carousel/jetpack-carousel.js @@ -377,6 +377,12 @@ } } + function makeGalleryImageAccessible( img ) { + img.role = 'button'; + img.tabIndex = 0; + img.ariaLabel = jetpackCarouselStrings.image_label; + } + function initializeCarousel() { if ( ! carousel.overlay ) { carousel.overlay = document.querySelector( '.jp-carousel-overlay' ); @@ -735,6 +741,8 @@ return; } + makeGalleryImageAccessible( image ); + // Make this node a gallery recognizable by event listener above. link.classList.add( 'single-image-gallery' ); // blog_id is needed to allow posting comments to correct blog. @@ -1579,6 +1587,11 @@ // Register the event listeners for starting the gallery document.body.addEventListener( 'click', handleInteraction ); document.body.addEventListener( 'keydown', handleInteraction ); + document.querySelectorAll( galleryItemSelector + 'img' ).forEach( function ( galleryImage ) { + if ( shouldOpenModal( galleryImage ) ) { + makeGalleryImageAccessible( galleryImage ); + } + } ); function handleInteraction( e ) { if ( e.type === 'click' ) { @@ -1598,6 +1611,47 @@ } } + function shouldOpenModal( el ) { + var parent = el.parentElement; + var grandparent = parent.parentElement; + + // If Gallery is made up of individual Image blocks check for custom link before + // loading carousel. The custom link may be the parent or could be a descendant + // of the parent if the image has rounded corners. + var parentHref = null; + if ( grandparent && grandparent.classList.contains( 'wp-block-image' ) ) { + parentHref = parent.getAttribute( 'href' ); + } else if ( + parent && + parent.classList.contains( 'wp-block-image' ) && + parent.querySelector( ':scope > a' ) + ) { + parentHref = parent.querySelector( ':scope > a' ).getAttribute( 'href' ); + } + + // If the link does not point to the attachment or media file then assume Image has + // a custom link so don't load the carousel. + if ( + parentHref && + parentHref.split( '?' )[ 0 ] !== el.getAttribute( 'data-orig-file' ).split( '?' )[ 0 ] && + parentHref !== el.getAttribute( 'data-permalink' ) + ) { + return false; + } + + // Do not open the modal if we are looking at a gallery caption from before WP5, which may contain a link. + if ( parent.classList.contains( 'gallery-caption' ) ) { + return false; + } + + // Do not open the modal if we are looking at a caption of a gallery block, which may contain a link. + if ( domUtil.matches( parent, 'figcaption' ) ) { + return false; + } + + return true; + } + function handleClick( e ) { var isCompatible = window.CSS && window.CSS.supports && window.CSS.supports( 'display', 'grid' ); @@ -1616,41 +1670,7 @@ return; } - var parent = target.parentElement; - var grandparent = parent.parentElement; - - // If Gallery is made up of individual Image blocks check for custom link before - // loading carousel. The custom link may be the parent or could be a descendant - // of the parent if the image has rounded corners. - var parentHref = null; - if ( grandparent && grandparent.classList.contains( 'wp-block-image' ) ) { - parentHref = parent.getAttribute( 'href' ); - } else if ( - parent && - parent.classList.contains( 'wp-block-image' ) && - parent.querySelector( ':scope > a' ) - ) { - parentHref = parent.querySelector( ':scope > a' ).getAttribute( 'href' ); - } - - // If the link does not point to the attachment or media file then assume Image has - // a custom link so don't load the carousel. - if ( - parentHref && - parentHref.split( '?' )[ 0 ] !== - target.getAttribute( 'data-orig-file' ).split( '?' )[ 0 ] && - parentHref !== target.getAttribute( 'data-permalink' ) - ) { - return; - } - - // Do not open the modal if we are looking at a gallery caption from before WP5, which may contain a link. - if ( parent.classList.contains( 'gallery-caption' ) ) { - return; - } - - // Do not open the modal if we are looking at a caption of a gallery block, which may contain a link. - if ( domUtil.matches( parent, 'figcaption' ) ) { + if ( ! shouldOpenModal( target ) ) { return; } diff --git a/projects/plugins/jetpack/modules/carousel/jetpack-carousel.php b/projects/plugins/jetpack/modules/carousel/jetpack-carousel.php index b979bbbbc2bcb..b7abb5fb2ab40 100644 --- a/projects/plugins/jetpack/modules/carousel/jetpack-carousel.php +++ b/projects/plugins/jetpack/modules/carousel/jetpack-carousel.php @@ -481,6 +481,7 @@ public function enqueue_assets() { 'post_comment' => __( 'Post Comment', 'jetpack' ), 'write_comment' => __( 'Write a Comment...', 'jetpack' ), 'loading_comments' => __( 'Loading Comments...', 'jetpack' ), + 'image_label' => __( 'Open image in full-screen.', 'jetpack' ), 'download_original' => sprintf( /* translators: %1s is the full-size image width, and %2s is the height. */ __( 'View full size %1$s×%2$s', 'jetpack' ), @@ -993,8 +994,6 @@ class_exists( 'Jetpack_AMP_Support' ) $attr['data-image-caption'] = esc_attr( htmlspecialchars( $attachment_caption, ENT_COMPAT ) ); $attr['data-medium-file'] = esc_attr( $medium_file ); $attr['data-large-file'] = esc_attr( $large_file ); - $attr['tabindex'] = '0'; - $attr['role'] = 'button'; return $attr; }