Ticket #43169: 43169.2.diff
File 43169.2.diff, 19.4 KB (added by , 5 years ago) |
---|
-
src/js/media/views/attachment/details.js
1 1 var Attachment = wp.media.view.Attachment, 2 2 l10n = wp.media.view.l10n, 3 $ = jQuery, 3 4 Details; 4 5 5 6 /** … … 46 47 }, 47 48 48 49 /** 50 * Gets the focusable elements to move focus to. 51 * 52 * @since 5.3.0 53 */ 54 getFocusableElements: function() { 55 var editedAttachment = $( 'li[data-id="' + this.model.id + '"]' ); 56 57 this.previousAttachment = editedAttachment.prev(); 58 this.nextAttachment = editedAttachment.next(); 59 }, 60 61 /** 62 * Moves focus to the previous or next attachment in the grid. 63 * Fallbacks to the upload button or media frame when there are no attachments. 64 * 65 * @since 5.3.0 66 */ 67 moveFocus: function() { 68 if ( this.previousAttachment.length ) { 69 this.previousAttachment.focus(); 70 return; 71 } 72 73 if ( this.nextAttachment.length ) { 74 this.nextAttachment.focus(); 75 return; 76 } 77 78 // Fallback: move focus to the "Select Files" button in the media modal. 79 if ( this.controller.uploader && this.controller.uploader.$browser ) { 80 this.controller.uploader.$browser.focus(); 81 return; 82 } 83 84 // Last fallback. 85 this.moveFocusToLastFallback(); 86 }, 87 88 /** 89 * Moves focus to the media frame as last fallback. 90 * 91 * @since 5.3.0 92 */ 93 moveFocusToLastFallback: function() { 94 // Last fallback: make the frame focusable and move focus to it. 95 $( '.media-frame' ) 96 .attr( 'tabindex', '-1' ) 97 .focus(); 98 }, 99 100 /** 49 101 * @param {Object} event 50 102 */ 51 103 deleteAttachment: function( event ) { 52 104 event.preventDefault(); 53 105 106 this.getFocusableElements(); 107 54 108 if ( window.confirm( l10n.warnDelete ) ) { 55 109 this.model.destroy(); 56 // Keep focus inside media modal 57 // after image is deleted 58 this.controller.modal.focusManager.focus(); 110 this.moveFocus(); 59 111 } 60 112 }, 61 113 /** … … 62 114 * @param {Object} event 63 115 */ 64 116 trashAttachment: function( event ) { 65 var library = this.controller.library; 117 var library = this.controller.library, 118 self = this; 66 119 event.preventDefault(); 67 120 121 this.getFocusableElements(); 122 123 // When in the Media Library and the Media trash is enabled. 68 124 if ( wp.media.view.settings.mediaTrash && 69 125 'edit-metadata' === this.controller.content.mode() ) { 70 126 … … 71 127 this.model.set( 'status', 'trash' ); 72 128 this.model.save().done( function() { 73 129 library._requery( true ); 130 /* 131 * @todo: We need to move focus back to the previous, next, or first 132 * attachment but the library gets re-queried and refreshed. Thus, 133 * the references to the previous attachments are lost. We need an 134 * alternate method. 135 */ 136 self.moveFocusToLastFallback(); 74 137 } ); 75 } 138 } else { 76 139 this.model.destroy(); 140 this.moveFocus(); 77 141 } 78 142 }, 79 143 /** … … 103 167 } 104 168 }, 105 169 /** 106 * When reverse tabbing (shift+tab) out of the right details panel, deliver107 * the focus to the item in the list that was being edited.170 * When reverse tabbing (shift+tab) out of the right details panel, 171 * move focus to the item that was being edited in the attachments list. 108 172 * 109 173 * @param {Object} event 110 174 */ … … 113 177 this.controller.trigger( 'attachment:details:shift-tab', event ); 114 178 return false; 115 179 } 116 117 if ( 37 === event.keyCode || 38 === event.keyCode || 39 === event.keyCode || 40 === event.keyCode ) {118 this.controller.trigger( 'attachment:keydown:arrow', event );119 return;120 }121 180 } 122 181 }); 123 182 -
src/js/media/views/attachments/browser.js
86 86 }, 87 87 88 88 editSelection: function( modal ) { 89 // When editing a selection, move focus to the "Return to library" button. 89 90 modal.$( '.media-button-backToLibrary' ).focus(); 90 91 }, 91 92 -
src/js/media/views/attachments.js
82 82 83 83 this.collection.on( 'reset', this.render, this ); 84 84 85 this. listenTo( this.controller, 'library:selection:add', this.attachmentFocus );85 this.controller.on( 'library:selection:add', this.attachmentFocus, this ); 86 86 87 87 // Throttle the scroll handler and bind this. 88 88 this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value(); … … 130 130 * @returns {void} 131 131 */ 132 132 attachmentFocus: function() { 133 this.$( 'li:first' ).focus(); 133 /* 134 * @todo: when uploading new attachments, this tries to move focus to the 135 * attachmentz grid. Actually, a progress bar gets initially displayed 136 * and then updated when uploading completes, so focus is lost. 137 * Additionally: this view is used for both the attachments list and the 138 * list of selected attachments in the bottom media toolbar. Thus, when 139 * uploading attachments, it is called twice and returns two different `this`. 140 * `this.columns` is truthy within the modal. 141 */ 142 if ( this.columns ) { 143 // Move focus to the grid list within the modal. 144 this.$el.focus(); 145 } 134 146 }, 135 147 136 148 /** 137 149 * Restores focus to the selected item in the collection. 138 150 * 151 * Moves focus back to the first selected attachment in the grid. Used when 152 * tabbing backwards from the attachment details sidebar. 153 * See media.view.AttachmentsBrowser. 154 * 139 155 * @since 4.0.0 140 156 * 141 157 * @returns {void} -
src/js/media/views/edit-image.js
26 26 }, 27 27 28 28 loadEditor: function() { 29 var dfd = this.editor.open( this.model.get('id'), this.model.get('nonces').edit, this ); 30 dfd.done( _.bind( this.focus, this ) ); 29 this.editor.open( this.model.get( 'id' ), this.model.get( 'nonces' ).edit, this ); 31 30 }, 32 31 33 focus: function() {34 this.$( '.imgedit-submit .button' ).eq( 0 ).focus();35 },36 37 32 back: function() { 38 33 var lastState = this.controller.lastState(); 39 34 this.controller.setState( lastState ); -
src/js/media/views/embed/url.js
56 56 return this; 57 57 }, 58 58 59 ready: function() {60 if ( ! wp.media.isTouchDevice ) {61 this.focus();62 }63 },64 65 59 url: function( event ) { 66 60 this.model.set( 'url', $.trim( event.target.value ) ); 67 },68 69 /**70 * If the input is visible, focus and select its contents.71 */72 focus: function() {73 var $input = this.$input;74 if ( $input.is(':visible') ) {75 $input.focus()[0].select();76 }77 61 } 78 62 }); 79 63 -
src/js/media/views/focus-manager.js
15 15 }, 16 16 17 17 /** 18 * Moves focus to the first visible menu item in the modal.18 * Gets all the tabbable elements. 19 19 */ 20 getTabbables: function() { 21 // Skip the file input added by Plupload. 22 return this.$( ':tabbable' ).not( '.moxie-shim input[type="file"]' ); 23 }, 24 25 /** 26 * Moves focus to the modal dialog. 27 */ 20 28 focus: function() { 21 this.$( '.media-m enu-item' ).filter( ':visible' ).first().focus();29 this.$( '.media-modal' ).focus(); 22 30 }, 31 23 32 /** 24 33 * @param {Object} event 25 34 */ … … 31 40 return; 32 41 } 33 42 34 // Skip the file input added by Plupload. 35 tabbables = this.$( ':tabbable' ).not( '.moxie-shim input[type="file"]' ); 43 tabbables = this.getTabbables(); 36 44 37 45 // Keep tab focus within media modal while it's open 38 46 if ( tabbables.last()[0] === event.target && ! event.shiftKey ) { -
src/js/media/views/frame/edit-attachments.js
91 91 92 92 // Completely destroy the modal DOM element when closing it. 93 93 this.modal.on( 'close', _.bind( function() { 94 $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */ 95 // Restore the original focus item if possible 94 // Remove the keydown event. 95 $( 'body' ).off( 'keydown.media-modal' ); 96 // Move focus back to the original item in the grid if possible. 96 97 $( 'li.attachment[data-id="' + this.model.get( 'id' ) +'"]' ).focus(); 97 98 this.resetRoute(); 98 99 }, this ) ); … … 173 174 }, 174 175 175 176 toggleNav: function() { 176 this.$( '.left').toggleClass( 'disabled', ! this.hasPrevious() );177 this.$( '.right').toggleClass( 'disabled', ! this.hasNext() );177 this.$( '.left' ).prop( 'disabled', ! this.hasPrevious() ); 178 this.$( '.right' ).prop( 'disabled', ! this.hasNext() ); 178 179 }, 179 180 180 181 /** … … 204 205 if ( ! this.hasPrevious() ) { 205 206 return; 206 207 } 208 207 209 this.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) ); 208 this.$( '.left' ).focus(); 210 // Move focus to the Previous button. When there are no more items, to the Next button. 211 this.focusNavButton( this.hasPrevious() ? '.left' : '.right' ); 209 212 }, 210 213 211 214 /** … … 215 218 if ( ! this.hasNext() ) { 216 219 return; 217 220 } 221 218 222 this.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) ); 219 this.$( '.right' ).focus(); 223 // Move focus to the Next button. When there are no more items, to the Previous button. 224 this.focusNavButton( this.hasNext() ? '.right' : '.left' ); 220 225 }, 221 226 227 /** 228 * Set focus to the navigation buttons depending on the browsing direction. 229 * 230 * @since 5.3.0 231 * 232 * @param {string} which A CSS selector to target the button to focus. 233 */ 234 focusNavButton: function( which ) { 235 $( which ).focus(); 236 }, 237 222 238 getCurrentIndex: function() { 223 239 return this.library.indexOf( this.model ); 224 240 }, -
src/js/media/views/frame/post.js
290 290 frame.close(); 291 291 } 292 292 293 // Keep focus inside media modal 294 // after canceling a gallery 293 // Move focus to the modal after canceling a Gallery. 295 294 this.controller.modal.focusManager.focus(); 296 295 } 297 296 }, … … 317 316 } else { 318 317 frame.close(); 319 318 } 319 320 // Move focus to the modal after canceling an Audio Playlist. 321 this.controller.modal.focusManager.focus(); 320 322 } 321 323 }, 322 324 separateCancel: new wp.media.View({ … … 341 343 } else { 342 344 frame.close(); 343 345 } 346 347 // Move focus to the modal after canceling a Video Playlist. 348 this.controller.modal.focusManager.focus(); 344 349 } 345 350 }, 346 351 separateCancel: new wp.media.View({ … … 358 363 }).render(); 359 364 360 365 this.content.set( view ); 361 362 if ( ! wp.media.isTouchDevice ) {363 view.url.focus();364 }365 366 }, 366 367 367 368 editSelectionContent: function() { … … 483 484 multiple: true 484 485 }) ); 485 486 486 this.controller.setState('gallery-edit'); 487 // Jump to Edit Gallery view. 488 this.controller.setState( 'gallery-edit' ); 487 489 488 // Keep focus inside media modal 489 // after jumping to gallery view 490 // Move focus to the modal after jumping to Edit Gallery view. 490 491 this.controller.modal.focusManager.focus(); 491 492 } 492 493 }); … … 513 514 multiple: true 514 515 }) ); 515 516 516 this.controller.setState('playlist-edit'); 517 // Jump to Edit Audio Playlist view. 518 this.controller.setState( 'playlist-edit' ); 517 519 518 // Keep focus inside media modal 519 // after jumping to playlist view 520 // Move focus to the modal after jumping to Edit Audio Playlist view. 520 521 this.controller.modal.focusManager.focus(); 521 522 } 522 523 }); … … 543 544 multiple: true 544 545 }) ); 545 546 546 this.controller.setState('video-playlist-edit'); 547 // Jump to Edit Video Playlist view. 548 this.controller.setState( 'video-playlist-edit' ); 547 549 548 // Keep focus inside media modal 549 // after jumping to video playlist view 550 // Move focus to the modal after jumping to Edit Video Playlist view. 550 551 this.controller.modal.focusManager.focus(); 551 552 } 552 553 }); … … 616 617 edit.get('library').add( state.get('selection').models ); 617 618 state.trigger('reset'); 618 619 controller.setState('gallery-edit'); 620 // Move focus to the modal when jumping back from Add to Gallery to Edit Gallery view. 621 this.controller.modal.focusManager.focus(); 619 622 } 620 623 } 621 624 } … … 673 676 edit.get('library').add( state.get('selection').models ); 674 677 state.trigger('reset'); 675 678 controller.setState('playlist-edit'); 679 // Move focus to the modal when jumping back from Add to Audio Playlist to Edit Audio Playlist view. 680 this.controller.modal.focusManager.focus(); 676 681 } 677 682 } 678 683 } … … 727 732 edit.get('library').add( state.get('selection').models ); 728 733 state.trigger('reset'); 729 734 controller.setState('video-playlist-edit'); 735 // Move focus to the modal when jumping back from Add to Video Playlist to Edit Video Playlist view. 736 this.controller.modal.focusManager.focus(); 730 737 } 731 738 } 732 739 } -
src/js/media/views/image-details.js
71 71 }, 72 72 73 73 postRender: function() { 74 setTimeout( _.bind( this. resetFocus, this ), 10 );74 setTimeout( _.bind( this.scrollToTop, this ), 10 ); 75 75 this.toggleLinkSettings(); 76 76 if ( window.getUserSetting( 'advImgDetails' ) === 'show' ) { 77 77 this.toggleAdvanced( true ); … … 79 79 this.trigger( 'post-render' ); 80 80 }, 81 81 82 resetFocus: function() { 83 this.$( '.link-to-custom' ).blur(); 82 scrollToTop: function() { 84 83 this.$( '.embed-media-settings' ).scrollTop( 0 ); 85 84 }, 86 85 -
src/js/media/views/media-details.js
129 129 AttachmentDisplay.prototype.render.apply( this, arguments ); 130 130 131 131 setTimeout( _.bind( function() { 132 this. resetFocus();132 this.scrollToTop(); 133 133 }, this ), 10 ); 134 134 135 135 this.settings = _.defaults( { … … 139 139 return this.setMedia(); 140 140 }, 141 141 142 resetFocus: function() {142 scrollToTop: function() { 143 143 this.$( '.embed-media-settings' ).scrollTop( 0 ); 144 144 } 145 145 },/** @lends wp.media.view.MediaDetails */{ -
src/js/media/views/menu-item.js
1 var $ = jQuery, 2 MenuItem; 1 var MenuItem; 3 2 4 3 /** 5 4 * wp.media.view.MenuItem … … 37 36 } else { 38 37 this.click(); 39 38 } 40 41 // When selecting a tab along the left side,42 // focus should be transferred into the main panel43 if ( ! wp.media.isTouchDevice ) {44 $('.media-frame-content input').first().focus();45 }46 39 }, 47 40 48 41 click: function() { -
src/js/media/views/modal.js
135 135 // Hide modal and remove restricted media modal tab focus once it's closed 136 136 this.$el.hide().undelegate( 'keydown' ); 137 137 138 // Putfocus back in useful location once modal is closed.138 // Move focus back in useful location once modal is closed. 139 139 if ( null !== this.clickedOpenerEl ) { 140 // Move focus back to the element that opened the modal. 140 141 this.clickedOpenerEl.focus(); 141 142 } else { 143 // Fallback to the admin page main element. 142 144 $( '#wpbody-content' ) 143 145 .attr( 'tabindex', '-1' ) 144 146 .focus(); -
src/js/media/views/selection.js
74 74 event.preventDefault(); 75 75 this.collection.reset(); 76 76 77 // Keep focus inside media modal 78 // after clear link is selected 77 // Move focus to the modal. 79 78 this.controller.modal.focusManager.focus(); 80 79 } 81 80 }); -
src/js/media/views/settings/attachment-display.js
83 83 } 84 84 85 85 $input.closest( '.setting' ).removeClass( 'hidden' ); 86 87 // If the input is visible, focus and select its contents.88 if ( ! wp.media.isTouchDevice && $input.is(':visible') ) {89 $input.focus()[0].select();90 }91 86 } 92 87 }); 93 88 -
src/js/media/views/uploader/status.js
124 124 _.invoke( errors, 'remove' ); 125 125 } 126 126 wp.Uploader.errors.reset(); 127 // Keep focus withinthe modal after the dismiss button gets removed from the DOM.127 // Move focus to the modal after the dismiss button gets removed from the DOM. 128 128 this.controller.modal.focusManager.focus(); 129 129 } 130 130 }); -
src/wp-admin/css/media.css
682 682 content: "\f345"; 683 683 } 684 684 685 .edit-attachment-frame .edit-media-header .left.disabled, 686 .edit-attachment-frame .edit-media-header .right.disabled, 687 .edit-attachment-frame .edit-media-header .left.disabled:hover, 688 .edit-attachment-frame .edit-media-header .right.disabled:hover { 685 .edit-attachment-frame .edit-media-header [disabled], 686 .edit-attachment-frame .edit-media-header [disabled]:hover { 689 687 color: #ccc; 690 688 background: inherit; 691 689 cursor: default; 692 pointer-events: none;693 690 } 694 691 695 692 .edit-attachment-frame .media-frame-content, -
src/wp-includes/media-template.php
323 323 <?php // Template for the Attachment Details layout in the media browser. ?> 324 324 <script type="text/html" id="tmpl-edit-attachment-frame"> 325 325 <div class="edit-media-header"> 326 <button class="left dashicons <# if ( ! data.hasPrevious ) { #> disabled <# } #>"><span class="screen-reader-text"><?php _e( 'Previous' ); ?></span></button>327 <button class="right dashicons <# if ( ! data.hasNext ) { #> disabled <# } #>"><span class="screen-reader-text"><?php _e( 'Next' ); ?></span></button>326 <button class="left dashicons"<# if ( ! data.hasPrevious ) { #> disabled<# } #>><span class="screen-reader-text"><?php _e( 'Edit previous media item' ); ?></span></button> 327 <button class="right dashicons"<# if ( ! data.hasNext ) { #> disabled<# } #>><span class="screen-reader-text"><?php _e( 'Edit next media item' ); ?></span></button> 328 328 <button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text"><?php _e( 'Close dialog' ); ?></span></span></button> 329 329 </div> 330 330 <div class="media-frame-title"></div>