<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[48265] trunk/src: Accessibility: Media: Fix the Image Editor mismatching keyboard focus order and visual reading order.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/48265">48265</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/48265","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>afercia</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2020-07-01 14:27:18 +0000 (Wed, 01 Jul 2020)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Accessibility: Media: Fix the Image Editor mismatching keyboard focus order and visual reading order.

Swaps the DOM order of the two main columns within the admin Image Editor.

When the sequence in which content is presented affects its meaning and the navigation sequences affect meaning or operation, visual order and DOM order must match. See WCAG 2.1 Success Criterion 1.3.2 Meaningful Sequence and Success Criterion 2.4.3 Focus Order.

Props sabernhardt, anevins, audrasjb, afercia.
Fixes <a href="https://core.trac.wordpress.org/ticket/47136">#47136</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcjs_enqueueslibimageeditjs">trunk/src/js/_enqueues/lib/image-edit.js</a></li>
<li><a href="#trunksrcwpadmincssmediacss">trunk/src/wp-admin/css/media.css</a></li>
<li><a href="#trunksrcwpadminincludesimageeditphp">trunk/src/wp-admin/includes/image-edit.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcjs_enqueueslibimageeditjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/js/_enqueues/lib/image-edit.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/js/_enqueues/lib/image-edit.js  2020-07-01 13:50:28 UTC (rev 48264)
+++ trunk/src/js/_enqueues/lib/image-edit.js    2020-07-01 14:27:18 UTC (rev 48265)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -136,6 +136,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                return false;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                });
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               $( document ).on( 'image-editor-image-loaded', this.focusManager );
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -621,11 +623,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">                this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'width': img.innerWidth(), 'height': img.innerHeight() } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                this.toggleEditor(postid, 0);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Editor is ready, move focus to the first focusable element.
-               $( '.imgedit-wrap .imgedit-help-toggle' ).eq( 0 ).focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               $( document ).trigger( 'image-editor-image-loaded' );
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Manages keyboard focus in the Image Editor user interface.
+        *
+        * @since 5.5.0
+        *
+        * @return {void}
+        */
+       focusManager: function() {
+               /*
+                * Editor is ready, move focus to the first focusable element. Since the
+                * DOM update is pretty large, the timeout helps browsers update their
+                * accessibility tree to better support assistive technologies.
+                */
+               setTimeout( function() {
+                       $( '.imgedit-wrap' ).find( ':tabbable:first' ).focus();
+               }, 100 );
+       },
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Initializes the cropping tool.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 2.9.0
</span></span></pre></div>
<a id="trunksrcwpadmincssmediacss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/media.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/media.css  2020-07-01 13:50:28 UTC (rev 48264)
+++ trunk/src/wp-admin/css/media.css    2020-07-01 14:27:18 UTC (rev 48265)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1224,6 +1224,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                float: none;
</span><span class="cx" style="display: block; padding: 0 10px">                width: auto;
</span><span class="cx" style="display: block; padding: 0 10px">                max-width: none;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                padding-bottom: 16px;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        .copy-to-clipboard-container .success {
</span></span></pre></div>
<a id="trunksrcwpadminincludesimageeditphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/image-edit.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/image-edit.php        2020-07-01 13:50:28 UTC (rev 48264)
+++ trunk/src/wp-admin/includes/image-edit.php  2020-07-01 14:27:18 UTC (rev 48265)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -48,6 +48,57 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <div class="imgedit-wrap wp-clearfix">
</span><span class="cx" style="display: block; padding: 0 10px">        <div id="imgedit-panel-<?php echo $post_id; ?>">
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        <div class="imgedit-panel-content wp-clearfix">
+               <?php echo $note; ?>
+               <div class="imgedit-menu wp-clearfix">
+                       <button type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this )" class="imgedit-crop button disabled" disabled><?php esc_html_e( 'Crop' ); ?></button>
+                       <?php
+
+                       // On some setups GD library does not provide imagerotate() - Ticket #11536.
+                       if ( wp_image_editor_supports(
+                               array(
+                                       'mime_type' => get_post_mime_type( $post_id ),
+                                       'methods'   => array( 'rotate' ),
+                               )
+                       ) ) {
+                               $note_no_rotate = '';
+                               ?>
+                               <button type="button" class="imgedit-rleft button" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate left' ); ?></button>
+                               <button type="button" class="imgedit-rright button" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate right' ); ?></button>
+                               <?php
+                       } else {
+                               $note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
+                               ?>
+                               <button type="button" class="imgedit-rleft button disabled" disabled></button>
+                               <button type="button" class="imgedit-rright button disabled" disabled></button>
+                       <?php } ?>
+
+                       <button type="button" onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv button"><?php esc_html_e( 'Flip vertical' ); ?></button>
+                       <button type="button" onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph button"><?php esc_html_e( 'Flip horizontal' ); ?></button>
+
+                       <br class="imgedit-undo-redo-separator" />
+                       <button type="button" id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo button disabled" disabled><?php esc_html_e( 'Undo' ); ?></button>
+                       <button type="button" id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo button disabled" disabled><?php esc_html_e( 'Redo' ); ?></button>
+                       <?php echo $note_no_rotate; ?>
+               </div>
+
+               <input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
+               <input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
+               <input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
+               <input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
+               <input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
+               <input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
+
+               <div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
+               <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand( 1, 99999 ); ?>" alt="" />
+               </div>
+
+               <div class="imgedit-submit">
+                       <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button imgedit-cancel-btn" value="<?php esc_attr_e( 'Cancel' ); ?>" />
+                       <input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" />
+               </div>
+       </div>
+
</ins><span class="cx" style="display: block; padding: 0 10px">         <div class="imgedit-settings">
</span><span class="cx" style="display: block; padding: 0 10px">        <div class="imgedit-group">
</span><span class="cx" style="display: block; padding: 0 10px">        <div class="imgedit-group-top">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -195,58 +246,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        </div>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        <div class="imgedit-panel-content wp-clearfix">
-               <?php echo $note; ?>
-               <div class="imgedit-menu wp-clearfix">
-                       <button type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this )" class="imgedit-crop button disabled" disabled><?php esc_html_e( 'Crop' ); ?></button>
-                       <?php
-
-                       // On some setups GD library does not provide imagerotate() - Ticket #11536.
-                       if ( wp_image_editor_supports(
-                               array(
-                                       'mime_type' => get_post_mime_type( $post_id ),
-                                       'methods'   => array( 'rotate' ),
-                               )
-                       ) ) {
-                               $note_no_rotate = '';
-                               ?>
-                               <button type="button" class="imgedit-rleft button" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate left' ); ?></button>
-                               <button type="button" class="imgedit-rright button" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate right' ); ?></button>
-                               <?php
-                       } else {
-                               $note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
-                               ?>
-                               <button type="button" class="imgedit-rleft button disabled" disabled></button>
-                               <button type="button" class="imgedit-rright button disabled" disabled></button>
-                       <?php } ?>
-
-                       <button type="button" onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-flipv button"><?php esc_html_e( 'Flip vertical' ); ?></button>
-                       <button type="button" onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-fliph button"><?php esc_html_e( 'Flip horizontal' ); ?></button>
-
-                       <br class="imgedit-undo-redo-separator" />
-                       <button type="button" id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo button disabled" disabled><?php esc_html_e( 'Undo' ); ?></button>
-                       <button type="button" id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo button disabled" disabled><?php esc_html_e( 'Redo' ); ?></button>
-                       <?php echo $note_no_rotate; ?>
-               </div>
-
-               <input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
-               <input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
-               <input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
-               <input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
-               <input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
-               <input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
-
-               <div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
-               <img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')" src="<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $post_id; ?>&amp;rand=<?php echo rand( 1, 99999 ); ?>" alt="" />
-               </div>
-
-               <div class="imgedit-submit">
-                       <input type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button imgedit-cancel-btn" value="<?php esc_attr_e( 'Cancel' ); ?>" />
-                       <input type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button button-primary imgedit-submit-btn" value="<?php esc_attr_e( 'Save' ); ?>" />
-               </div>
</del><span class="cx" style="display: block; padding: 0 10px">         </div>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       </div>
</del><span class="cx" style="display: block; padding: 0 10px">         <div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
</span><span class="cx" style="display: block; padding: 0 10px">        <div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e( "There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor." ); ?></div>
</span><span class="cx" style="display: block; padding: 0 10px">        </div>
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/script-loader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/script-loader.php   2020-07-01 13:50:28 UTC (rev 48264)
+++ trunk/src/wp-includes/script-loader.php     2020-07-01 14:27:18 UTC (rev 48265)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1465,7 +1465,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $scripts->add( 'image-edit', "/wp-admin/js/image-edit$suffix.js", array( 'jquery', 'json2', 'imgareaselect' ), false, 1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $scripts->add( 'image-edit', "/wp-admin/js/image-edit$suffix.js", array( 'jquery', 'jquery-ui-core', 'json2', 'imgareaselect' ), false, 1 );
</ins><span class="cx" style="display: block; padding: 0 10px">                 did_action( 'init' ) && $scripts->localize(
</span><span class="cx" style="display: block; padding: 0 10px">                        'image-edit',
</span><span class="cx" style="display: block; padding: 0 10px">                        'imageEditL10n',
</span></span></pre>
</div>
</div>

</body>
</html>