Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve image carousel accessibility #39913

Merged
merged 2 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions projects/plugins/jetpack/changelog/improve-carousel-a11y
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: bugfix

Carousel: Further improve accessibility by being more selective over which images to apply attributes to
90 changes: 55 additions & 35 deletions projects/plugins/jetpack/modules/carousel/jetpack-carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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' ) {
Expand All @@ -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' );
Expand All @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <span class="photo-size">%1$s<span class="photo-size-times">&times;</span>%2$s</span>', 'jetpack' ),
Expand Down Expand Up @@ -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;
}

Expand Down
Loading