Ticket #23560: 23560.8.diff
File 23560.8.diff, 8.5 KB (added by , 6 years ago) |
---|
-
wp-includes/js/media-views.js
1375 1375 frame.setState( previous ); 1376 1376 else 1377 1377 frame.close(); 1378 1379 // Keep focus inside media modal 1380 // after canceling a gallery 1381 new media.view.FocusManager({ 1382 el: this.el 1383 }).focus(); 1378 1384 } 1379 1385 }, 1380 1386 separateCancel: new media.View({ … … 1485 1491 }) ); 1486 1492 1487 1493 this.controller.setState('gallery-edit'); 1494 1495 // Keep focus inside media modal 1496 // after jumping to gallery view 1497 new media.view.FocusManager({ 1498 el: this.el 1499 }).focus(); 1488 1500 } 1489 1501 }); 1490 1502 }, … … 1577 1589 propagate: true, 1578 1590 freeze: true 1579 1591 }); 1592 1593 this.focusManager = new media.view.FocusManager({ 1594 el: this.el 1595 }); 1580 1596 }, 1581 1597 1582 1598 prepare: function() { … … 1637 1653 if ( ! this.views.attached || ! this.$el.is(':visible') ) 1638 1654 return this; 1639 1655 1640 this.$el.hide(); 1656 // Hide modal and remove restricted media modal tab focus once it's closed 1657 this.$el.hide().undelegate( 'keydown' ); 1658 1659 // Put focus back in useful location once modal is closed 1660 $('#wpbody-content').focus(); 1661 1641 1662 this.propagate('close'); 1642 1663 1643 1664 // If the `freeze` option is set, restore the container's scroll position. … … 1683 1704 this.escape(); 1684 1705 return; 1685 1706 } 1707 1708 // Keep focus inside the media modal 1709 this.focusManager; 1686 1710 } 1687 1711 }); 1688 1712 … … 1695 1719 }, 1696 1720 1697 1721 focus: function() { 1698 if ( _.isUndefined( this.index ) ) 1699 return; 1700 1701 // Update our collection of `$tabbables`. 1702 this.$tabbables = this.$(':tabbable'); 1703 1704 // If tab is saved, focus it. 1705 this.$tabbables.eq( this.index ).focus(); 1722 // Reset focus on first left menu item 1723 $('.media-menu-item').first().focus(); 1706 1724 }, 1707 1725 1708 1726 recordTab: function( event ) { … … 1710 1728 if ( 9 !== event.keyCode ) 1711 1729 return; 1712 1730 1713 // First try to update the index. 1714 if ( _.isUndefined( this.index ) ) 1715 this.updateIndex( event ); 1716 1717 // If we still don't have an index, bail. 1718 if ( _.isUndefined( this.index ) ) 1719 return; 1720 1721 var index = this.index + ( event.shiftKey ? -1 : 1 ); 1722 1723 if ( index >= 0 && index < this.$tabbables.length ) 1724 this.index = index; 1725 else 1726 delete this.index; 1731 // Keep tab focus within media modal while it's open 1732 if ( event.target === this.tabbablesLast[0] && !event.shiftKey ) { 1733 this.tabbableFirst.focus(); 1734 return false; 1735 } else if ( event.target === this.tabbableFirst[0] && event.shiftKey ) { 1736 this.tabbablesLast.focus(); 1737 return false; 1738 } 1727 1739 }, 1728 1740 1729 1741 updateIndex: function( event ) { 1730 this.$tabbables = this.$(':tabbable'); 1731 1732 var index = this.$tabbables.index( event.target ); 1733 1734 if ( -1 === index ) 1735 delete this.index; 1736 else 1737 this.index = index; 1742 // Resets tabbable elements 1743 this.tabbables = $( ':tabbable', this.$el ); 1744 this.tabbableFirst = this.tabbables.filter( ':first' ); 1745 this.tabbablesLast = this.tabbables.filter( ':last' ); 1738 1746 } 1739 1747 }); 1740 1748 … … 2493 2501 className: 'attachment', 2494 2502 template: media.template('attachment'), 2495 2503 2504 attributes: { 2505 tabIndex: 0, 2506 role: 'checkbox' 2507 }, 2508 2496 2509 events: { 2497 2510 'click .attachment-preview': 'toggleSelectionHandler', 2498 2511 'change [data-setting]': 'updateSetting', … … 2501 2514 'change [data-setting] textarea': 'updateSetting', 2502 2515 'click .close': 'removeFromLibrary', 2503 2516 'click .check': 'removeFromSelection', 2504 'click a': 'preventDefault' 2517 'click a': 'preventDefault', 2518 'keydown': 'toggleSelectionHandler' 2505 2519 }, 2506 2520 2507 2521 buttons: {}, … … 2509 2523 initialize: function() { 2510 2524 var selection = this.options.selection; 2511 2525 2526 this.$el.attr('aria-label', this.model.attributes.title).attr('aria-checked', false); 2512 2527 this.model.on( 'change:sizes change:uploading', this.render, this ); 2513 2528 this.model.on( 'change:title', this._syncTitle, this ); 2514 2529 this.model.on( 'change:caption', this._syncCaption, this ); … … 2599 2614 toggleSelectionHandler: function( event ) { 2600 2615 var method; 2601 2616 2617 // Catch enter and space events 2618 if ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) 2619 return; 2620 2602 2621 if ( event.shiftKey ) 2603 2622 method = 'between'; 2604 2623 else if ( event.ctrlKey || event.metaKey ) … … 2647 2666 return; 2648 2667 } 2649 2668 2669 // Fixes bug that loses focus when selecting a featured image 2670 if ( !method ) 2671 method = 'add'; 2672 2650 2673 if ( method !== 'add' ) 2651 2674 method = 'reset'; 2652 2675 … … 2682 2705 if ( ! selection || ( collection && collection !== selection ) ) 2683 2706 return; 2684 2707 2685 this.$el.addClass('selected') ;2708 this.$el.addClass('selected').attr('aria-checked', true); 2686 2709 }, 2687 2710 2688 2711 deselect: function( model, collection ) { … … 2694 2717 if ( ! selection || ( collection && collection !== selection ) ) 2695 2718 return; 2696 2719 2697 this.$el.removeClass('selected') ;2720 this.$el.removeClass('selected').attr('aria-checked', false); 2698 2721 }, 2699 2722 2700 2723 details: function( model, collection ) { … … 2876 2899 tagName: 'ul', 2877 2900 className: 'attachments', 2878 2901 2902 attributes: { 2903 tabIndex: -1 2904 }, 2905 2879 2906 cssTemplate: media.template('attachments-css'), 2880 2907 2881 2908 events: { … … 3488 3515 clear: function( event ) { 3489 3516 event.preventDefault(); 3490 3517 this.collection.reset(); 3518 3519 // Keep focus inside media modal 3520 // after clear link is selected 3521 new media.view.FocusManager({ 3522 el: this.el 3523 }).focus(); 3491 3524 } 3492 3525 }); 3493 3526 … … 3731 3764 }, 3732 3765 3733 3766 initialize: function() { 3734 this.focusManager = new media.view.FocusManager({3735 el: this.el3736 });3737 3738 3767 media.view.Attachment.prototype.initialize.apply( this, arguments ); 3739 3768 }, 3740 3769 3741 3770 render: function() { 3742 3771 media.view.Attachment.prototype.render.apply( this, arguments ); 3743 this.focusManager.focus();3744 3772 return this; 3745 3773 }, 3746 3774 … … 3749 3777 3750 3778 if ( confirm( l10n.warnDelete ) ) 3751 3779 this.model.destroy(); 3780 3781 // Keep focus inside media modal 3782 // after image is deleted 3783 new media.view.FocusManager({ 3784 el: this.el 3785 }).focus(); 3752 3786 }, 3753 3787 3754 3788 editAttachment: function() { … … 3777 3811 }, 3778 3812 3779 3813 initialize: function() { 3780 this.focusManager = new media.view.FocusManager({3781 el: this.el3782 });3783 3784 3814 this.model.on( 'change:compat', this.render, this ); 3785 3815 }, 3786 3816 … … 3799 3829 this.views.detach(); 3800 3830 this.$el.html( compat.item ); 3801 3831 this.views.render(); 3802 3803 this.focusManager.focus();3804 3832 return this; 3805 3833 }, 3806 3834 -
wp-includes/media-template.php
18 18 if ( $is_IE && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false ) 19 19 $class .= ' ie7'; 20 20 ?> 21 <!--[if lte IE 8]> 22 <style> 23 .attachment:focus { 24 outline: #1e8cbe solid; 25 } 26 .selected.attachment { 27 outline: #1e8cbe solid; 28 } 29 </style> 30 <![endif]--> 21 31 <script type="text/html" id="tmpl-media-frame"> 22 32 <div class="media-frame-menu"></div> 23 33 <div class="media-frame-title"></div> … … 142 152 <# } else if ( 'image' === data.type ) { #> 143 153 <div class="thumbnail"> 144 154 <div class="centered"> 145 <img src="{{ data.size.url }}" draggable="false" />155 <img src="{{ data.size.url }}" draggable="false" alt="" /> 146 156 </div> 147 157 </div> 148 158 <# } else { #> … … 157 167 <# } #> 158 168 159 169 <# if ( data.buttons.check ) { #> 160 <a class="check" href="#" title="<?php _e('Deselect'); ?>" ><div class="media-modal-icon"></div></a>170 <a class="check" href="#" title="<?php _e('Deselect'); ?>" tabindex="-1"><div class="media-modal-icon"></div></a> 161 171 <# } #> 162 172 </div> 163 173 <# -
wp-includes/css/media-views.css
460 460 border-right: 0; 461 461 } 462 462 463 .media-router > a:active, 464 .media-router > a:focus { 463 .media-router > a:active { 465 464 outline: none; 466 465 } 467 466 … … 654 653 user-select: none; 655 654 } 656 655 656 .attachment:focus { 657 box-shadow: 0px 0px 2pt 2pt #1e8cbe; 658 outline: none; 659 } 660 657 661 .selected.attachment { 658 662 box-shadow: 659 663 0 0 0 1px #fff, … … 855 859 right: 300px; 856 860 bottom: 0; 857 861 overflow: auto; 862 outline: none; 858 863 } 859 864 860 865 .attachments-browser .instructions {