WordPress.org

Make WordPress Core

Ticket #43169: 43169.2.diff

File 43169.2.diff, 19.4 KB (added by afercia, 3 months ago)
  • src/js/media/views/attachment/details.js

     
    11var Attachment = wp.media.view.Attachment,
    22        l10n = wp.media.view.l10n,
     3        $ = jQuery,
    34        Details;
    45
    56/**
     
    4647        },
    4748
    4849        /**
     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        /**
    49101         * @param {Object} event
    50102         */
    51103        deleteAttachment: function( event ) {
    52104                event.preventDefault();
    53105
     106                this.getFocusableElements();
     107
    54108                if ( window.confirm( l10n.warnDelete ) ) {
    55109                        this.model.destroy();
    56                         // Keep focus inside media modal
    57                         // after image is deleted
    58                         this.controller.modal.focusManager.focus();
     110                        this.moveFocus();
    59111                }
    60112        },
    61113        /**
     
    62114         * @param {Object} event
    63115         */
    64116        trashAttachment: function( event ) {
    65                 var library = this.controller.library;
     117                var library = this.controller.library,
     118                        self = this;
    66119                event.preventDefault();
    67120
     121                this.getFocusableElements();
     122
     123                // When in the Media Library and the Media trash is enabled.
    68124                if ( wp.media.view.settings.mediaTrash &&
    69125                        'edit-metadata' === this.controller.content.mode() ) {
    70126
     
    71127                        this.model.set( 'status', 'trash' );
    72128                        this.model.save().done( function() {
    73129                                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();
    74137                        } );
    75                 }  else {
     138                } else {
    76139                        this.model.destroy();
     140                        this.moveFocus();
    77141                }
    78142        },
    79143        /**
     
    103167                }
    104168        },
    105169        /**
    106          * When reverse tabbing(shift+tab) out of the right details panel, deliver
    107          * 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.
    108172         *
    109173         * @param {Object} event
    110174         */
     
    113177                        this.controller.trigger( 'attachment:details:shift-tab', event );
    114178                        return false;
    115179                }
    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                 }
    121180        }
    122181});
    123182
  • src/js/media/views/attachments/browser.js

     
    8686        },
    8787
    8888        editSelection: function( modal ) {
     89                // When editing a selection, move focus to the "Return to library" button.
    8990                modal.$( '.media-button-backToLibrary' ).focus();
    9091        },
    9192
  • src/js/media/views/attachments.js

     
    8282
    8383                this.collection.on( 'reset', this.render, this );
    8484
    85                 this.listenTo( this.controller, 'library:selection:add',    this.attachmentFocus );
     85                this.controller.on( 'library:selection:add', this.attachmentFocus, this );
    8686
    8787                // Throttle the scroll handler and bind this.
    8888                this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
     
    130130         * @returns {void}
    131131         */
    132132        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                }
    134146        },
    135147
    136148        /**
    137149         * Restores focus to the selected item in the collection.
    138150         *
     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         *
    139155         * @since 4.0.0
    140156         *
    141157         * @returns {void}
  • src/js/media/views/edit-image.js

     
    2626        },
    2727
    2828        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 );
    3130        },
    3231
    33         focus: function() {
    34                 this.$( '.imgedit-submit .button' ).eq( 0 ).focus();
    35         },
    36 
    3732        back: function() {
    3833                var lastState = this.controller.lastState();
    3934                this.controller.setState( lastState );
  • src/js/media/views/embed/url.js

     
    5656                return this;
    5757        },
    5858
    59         ready: function() {
    60                 if ( ! wp.media.isTouchDevice ) {
    61                         this.focus();
    62                 }
    63         },
    64 
    6559        url: function( event ) {
    6660                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                 }
    7761        }
    7862});
    7963
  • src/js/media/views/focus-manager.js

     
    1515        },
    1616
    1717        /**
    18          * Moves focus to the first visible menu item in the modal.
     18         * Gets all the tabbable elements.
    1919         */
     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         */
    2028        focus: function() {
    21                 this.$( '.media-menu-item' ).filter( ':visible' ).first().focus();
     29                this.$( '.media-modal' ).focus();
    2230        },
     31
    2332        /**
    2433         * @param {Object} event
    2534         */
     
    3140                        return;
    3241                }
    3342
    34                 // Skip the file input added by Plupload.
    35                 tabbables = this.$( ':tabbable' ).not( '.moxie-shim input[type="file"]' );
     43                tabbables = this.getTabbables();
    3644
    3745                // Keep tab focus within media modal while it's open
    3846                if ( tabbables.last()[0] === event.target && ! event.shiftKey ) {
  • src/js/media/views/frame/edit-attachments.js

     
    9191
    9292                        // Completely destroy the modal DOM element when closing it.
    9393                        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.
    9697                                $( 'li.attachment[data-id="' + this.model.get( 'id' ) +'"]' ).focus();
    9798                                this.resetRoute();
    9899                        }, this ) );
     
    173174        },
    174175
    175176        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() );
    178179        },
    179180
    180181        /**
     
    204205                if ( ! this.hasPrevious() ) {
    205206                        return;
    206207                }
     208
    207209                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' );
    209212        },
    210213
    211214        /**
     
    215218                if ( ! this.hasNext() ) {
    216219                        return;
    217220                }
     221
    218222                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' );
    220225        },
    221226
     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
    222238        getCurrentIndex: function() {
    223239                return this.library.indexOf( this.model );
    224240        },
  • src/js/media/views/frame/post.js

     
    290290                                                frame.close();
    291291                                        }
    292292
    293                                         // Keep focus inside media modal
    294                                         // after canceling a gallery
     293                                        // Move focus to the modal after canceling a Gallery.
    295294                                        this.controller.modal.focusManager.focus();
    296295                                }
    297296                        },
     
    317316                                        } else {
    318317                                                frame.close();
    319318                                        }
     319
     320                                        // Move focus to the modal after canceling an Audio Playlist.
     321                                        this.controller.modal.focusManager.focus();
    320322                                }
    321323                        },
    322324                        separateCancel: new wp.media.View({
     
    341343                                        } else {
    342344                                                frame.close();
    343345                                        }
     346
     347                                        // Move focus to the modal after canceling a Video Playlist.
     348                                        this.controller.modal.focusManager.focus();
    344349                                }
    345350                        },
    346351                        separateCancel: new wp.media.View({
     
    358363                }).render();
    359364
    360365                this.content.set( view );
    361 
    362                 if ( ! wp.media.isTouchDevice ) {
    363                         view.url.focus();
    364                 }
    365366        },
    366367
    367368        editSelectionContent: function() {
     
    483484                                        multiple: true
    484485                                }) );
    485486
    486                                 this.controller.setState('gallery-edit');
     487                                // Jump to Edit Gallery view.
     488                                this.controller.setState( 'gallery-edit' );
    487489
    488                                 // Keep focus inside media modal
    489                                 // after jumping to gallery view
     490                                // Move focus to the modal after jumping to Edit Gallery view.
    490491                                this.controller.modal.focusManager.focus();
    491492                        }
    492493                });
     
    513514                                        multiple: true
    514515                                }) );
    515516
    516                                 this.controller.setState('playlist-edit');
     517                                // Jump to Edit Audio Playlist view.
     518                                this.controller.setState( 'playlist-edit' );
    517519
    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.
    520521                                this.controller.modal.focusManager.focus();
    521522                        }
    522523                });
     
    543544                                        multiple: true
    544545                                }) );
    545546
    546                                 this.controller.setState('video-playlist-edit');
     547                                // Jump to Edit Video Playlist view.
     548                                this.controller.setState( 'video-playlist-edit' );
    547549
    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.
    550551                                this.controller.modal.focusManager.focus();
    551552                        }
    552553                });
     
    616617                                                edit.get('library').add( state.get('selection').models );
    617618                                                state.trigger('reset');
    618619                                                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();
    619622                                        }
    620623                                }
    621624                        }
     
    673676                                                edit.get('library').add( state.get('selection').models );
    674677                                                state.trigger('reset');
    675678                                                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();
    676681                                        }
    677682                                }
    678683                        }
     
    727732                                                edit.get('library').add( state.get('selection').models );
    728733                                                state.trigger('reset');
    729734                                                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();
    730737                                        }
    731738                                }
    732739                        }
  • src/js/media/views/image-details.js

     
    7171        },
    7272
    7373        postRender: function() {
    74                 setTimeout( _.bind( this.resetFocus, this ), 10 );
     74                setTimeout( _.bind( this.scrollToTop, this ), 10 );
    7575                this.toggleLinkSettings();
    7676                if ( window.getUserSetting( 'advImgDetails' ) === 'show' ) {
    7777                        this.toggleAdvanced( true );
     
    7979                this.trigger( 'post-render' );
    8080        },
    8181
    82         resetFocus: function() {
    83                 this.$( '.link-to-custom' ).blur();
     82        scrollToTop: function() {
    8483                this.$( '.embed-media-settings' ).scrollTop( 0 );
    8584        },
    8685
  • src/js/media/views/media-details.js

     
    129129                AttachmentDisplay.prototype.render.apply( this, arguments );
    130130
    131131                setTimeout( _.bind( function() {
    132                         this.resetFocus();
     132                        this.scrollToTop();
    133133                }, this ), 10 );
    134134
    135135                this.settings = _.defaults( {
     
    139139                return this.setMedia();
    140140        },
    141141
    142         resetFocus: function() {
     142        scrollToTop: function() {
    143143                this.$( '.embed-media-settings' ).scrollTop( 0 );
    144144        }
    145145},/** @lends wp.media.view.MediaDetails */{
  • src/js/media/views/menu-item.js

     
    1 var $ = jQuery,
    2         MenuItem;
     1var MenuItem;
    32
    43/**
    54 * wp.media.view.MenuItem
     
    3736                } else {
    3837                        this.click();
    3938                }
    40 
    41                 // When selecting a tab along the left side,
    42                 // focus should be transferred into the main panel
    43                 if ( ! wp.media.isTouchDevice ) {
    44                         $('.media-frame-content input').first().focus();
    45                 }
    4639        },
    4740
    4841        click: function() {
  • src/js/media/views/modal.js

     
    135135                // Hide modal and remove restricted media modal tab focus once it's closed
    136136                this.$el.hide().undelegate( 'keydown' );
    137137
    138                 // Put focus back in useful location once modal is closed.
     138                // Move focus back in useful location once modal is closed.
    139139                if ( null !== this.clickedOpenerEl ) {
     140                        // Move focus back to the element that opened the modal.
    140141                        this.clickedOpenerEl.focus();
    141142                } else {
     143                        // Fallback to the admin page main element.
    142144                        $( '#wpbody-content' )
    143145                                .attr( 'tabindex', '-1' )
    144146                                .focus();
  • src/js/media/views/selection.js

     
    7474                event.preventDefault();
    7575                this.collection.reset();
    7676
    77                 // Keep focus inside media modal
    78                 // after clear link is selected
     77                // Move focus to the modal.
    7978                this.controller.modal.focusManager.focus();
    8079        }
    8180});
  • src/js/media/views/settings/attachment-display.js

     
    8383                }
    8484
    8585                $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                 }
    9186        }
    9287});
    9388
  • src/js/media/views/uploader/status.js

     
    124124                        _.invoke( errors, 'remove' );
    125125                }
    126126                wp.Uploader.errors.reset();
    127                 // Keep focus within the 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.
    128128                this.controller.modal.focusManager.focus();
    129129        }
    130130});
  • src/wp-admin/css/media.css

     
    682682        content: "\f345";
    683683}
    684684
    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 {
    689687        color: #ccc;
    690688        background: inherit;
    691689        cursor: default;
    692         pointer-events: none;
    693690}
    694691
    695692.edit-attachment-frame .media-frame-content,
  • src/wp-includes/media-template.php

     
    323323        <?php // Template for the Attachment Details layout in the media browser. ?>
    324324        <script type="text/html" id="tmpl-edit-attachment-frame">
    325325                <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>
    328328                        <button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text"><?php _e( 'Close dialog' ); ?></span></span></button>
    329329                </div>
    330330                <div class="media-frame-title"></div>