Plugins: Respect `prefers-reduced-motion` on plugin thumbnails.

Pause animated plugin thumbnails when a user has reduced motion preferences configured in their device or operating system.

Props Travel_girl, audrasjb, bordoni, stevejonesdev, joedolson.
Fixes #55723.
Built from https://develop.svn.wordpress.org/trunk@56541


git-svn-id: http://core.svn.wordpress.org/trunk@56053 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
joedolson 2023-09-07 20:37:15 +00:00
parent aaec843875
commit eb635e4796
3 changed files with 118 additions and 2 deletions

View File

@ -2104,3 +2104,119 @@ $( function( $ ) {
})();
}( jQuery, window ));
/**
* Freeze animated plugin icons when reduced motion is enabled.
*
* When the user has enabled the 'prefers-reduced-motion' setting, this module
* stops animations for all GIFs on the page with the class 'plugin-icon' or
* plugin icon images in the update plugins table.
*
* @since 6.4
*/
(function() {
// Private variables and methods.
var priv = {},
pub = {},
mediaQuery;
// Initialize pauseAll to false; it will be set to true if reduced motion is preferred.
priv.pauseAll = false;
if ( window.matchMedia ) {
mediaQuery = window.matchMedia( '(prefers-reduced-motion: reduce)' );
if ( ! mediaQuery || mediaQuery.matches ) {
priv.pauseAll = true;
}
}
// Method to replace animated GIFs with a static frame.
priv.freezeAnimatedPluginIcons = function( img ) {
var coverImage = function() {
var width = img.width;
var height = img.height;
var canvas = document.createElement( 'canvas' );
// Set canvas dimensions.
canvas.width = width;
canvas.height = height;
// Copy classes from the image to the canvas.
canvas.className = img.className;
// Check if the image is inside a specific table.
var isInsideUpdateTable = img.closest( '#update-plugins-table' );
if ( isInsideUpdateTable ) {
// Transfer computed styles from image to canvas.
var computedStyles = window.getComputedStyle( img ),
i, max;
for ( i = 0, max = computedStyles.length; i < max; i++ ) {
var propName = computedStyles[ i ];
var propValue = computedStyles.getPropertyValue( propName );
canvas.style[ propName ] = propValue;
}
}
// Draw the image onto the canvas.
canvas.getContext( '2d' ).drawImage( img, 0, 0, width, height );
// Set accessibility attributes on canvas.
canvas.setAttribute( 'aria-hidden', 'true' );
canvas.setAttribute( 'role', 'presentation' );
// Insert canvas before the image and set the image to be near-invisible.
var parent = img.parentNode;
parent.insertBefore( canvas, img );
img.style.opacity = 0.01;
img.style.width = '0px';
img.style.height = '0px';
};
// If the image is already loaded, apply the coverImage function.
if ( img.complete ) {
coverImage();
} else {
// Otherwise, wait for the image to load.
img.addEventListener( 'load', coverImage, true );
}
};
// Public method to freeze all relevant GIFs on the page.
pub.freezeAll = function() {
var images = document.querySelectorAll( '.plugin-icon, #update-plugins-table img' );
for ( var x = 0; x < images.length; x++ ) {
if ( /\.gif(?:\?|$)/i.test( images[ x ].src ) ) {
priv.freezeAnimatedPluginIcons( images[ x ] );
}
}
};
// Only run the freezeAll method if the user prefers reduced motion.
if ( true === priv.pauseAll ) {
pub.freezeAll();
}
// Listen for jQuery AJAX events.
( function( $ ) {
$( document ).ajaxComplete( function( event, xhr, settings ) {
// Check if this is the 'search-install-plugins' request.
if ( settings.data && settings.data.includes( 'action=search-install-plugins' ) ) {
// Recheck if the user prefers reduced motion.
if ( window.matchMedia ) {
var mediaQuery = window.matchMedia( '(prefers-reduced-motion: reduce)' );
if ( mediaQuery.matches ) {
pub.freezeAll();
}
} else {
// Fallback for browsers that don't support matchMedia.
if ( true === priv.pauseAll ) {
pub.freezeAll();
}
}
}
} );
} )( jQuery );
// Expose public methods.
return pub;
})();

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '6.4-alpha-56540';
$wp_version = '6.4-alpha-56541';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.