Changeset 158713 in webkit
- Timestamp:
- Nov 5, 2013 7:50:51 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r158711 r158713 1 2013-11-05 James Craig <jcraig@apple.com> 2 3 AX: media controls accessibility needs more work 4 https://bugs.webkit.org/show_bug.cgi?id=123749 5 6 Reviewed by Jer Noble. 7 8 Updated some of the control labels/roles to improve accessibility. 9 - Volume slider is now keyboard/screenreader accessible. 10 - muteButton was a checkbox toggling checked state, now a button that toggles label "mute/unmute" 11 - fullscreenButton was a checkbox toggling checked state, now a button that toggles label "display/exit full screen" 12 - captionButton was a checkbox, now a popup button that launches the newly accessible menu. 13 Subtitles menu is now keyboard/screenreader accessible (uses roaming tabindex). 14 Render dump expectations changed because volume slider is now hidden via... 15 ...opacity/size (to make accessible without hover) instead of display:none. 16 17 Updated existing test coverage. 18 19 * platform/mac/accessibility/media-element-expected.txt: 20 * platform/mac/media/audio-controls-rendering-expected.txt: 21 * platform/mac/media/controls-after-reload-expected.txt: 22 * platform/mac/media/controls-strict-expected.txt: 23 * platform/mac/media/controls-styling-strict-expected.txt: 24 * platform/mac/media/controls-without-preload-expected.txt: 25 1 26 2013-11-05 Ryosuke Niwa <rniwa@webkit.org> 2 27 -
trunk/LayoutTests/platform/mac/accessibility/media-element-expected.txt
r158455 r158713 55 55 56 56 57 description: AXDescription: Volume 58 role: AXRole: AXSlider 59 60 61 description: AXDescription: 62 role: AXRole: AXValueIndicator 63 64 57 65 description: AXDescription: Mute 58 role: AXRole: AX CheckBox66 role: AXRole: AXButton 59 67 60 68 61 69 description: AXDescription: Display Full Screen 62 role: AXRole: AX CheckBox70 role: AXRole: AXButton 63 71 64 72 -
trunk/LayoutTests/platform/mac/media/audio-controls-rendering-expected.txt
r156546 r158713 44 44 layer at (184,44) size 22x22 45 45 RenderFlexibleBox {DIV} at (176,2) size 22x22 46 layer at (184,44) size 2x22 47 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 48 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 49 RenderFlexibleBox {DIV} at (1,1) size 0x8 50 RenderBlock {DIV} at (0,0) size 0x8 51 layer at (170,51) size 8x8 52 RenderBlock {DIV} at (-8,0) size 8x8 46 53 layer at (187,47) size 16x16 47 54 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] … … 75 82 layer at (304,87) size 22x22 76 83 RenderFlexibleBox {DIV} at (296,2) size 22x22 84 layer at (304,87) size 2x22 85 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 86 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 87 RenderFlexibleBox {DIV} at (1,1) size 0x8 88 RenderBlock {DIV} at (0,0) size 0x8 89 layer at (290,94) size 8x8 90 RenderBlock {DIV} at (-8,0) size 8x8 77 91 layer at (307,90) size 16x16 78 92 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] … … 108 122 layer at (304,205) size 22x22 109 123 RenderFlexibleBox {DIV} at (296,2) size 22x22 124 layer at (304,205) size 2x22 125 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 126 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 127 RenderFlexibleBox {DIV} at (1,1) size 0x8 128 RenderBlock {DIV} at (0,0) size 0x8 129 layer at (290,212) size 8x8 130 RenderBlock {DIV} at (-8,0) size 8x8 110 131 layer at (307,208) size 16x16 111 132 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] -
trunk/LayoutTests/platform/mac/media/controls-after-reload-expected.txt
r156546 r158713 40 40 layer at (274,259) size 22x22 41 41 RenderFlexibleBox {DIV} at (266,2) size 22x22 42 layer at (274,259) size 2x22 43 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 44 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 45 RenderFlexibleBox {DIV} at (1,1) size 0x8 46 RenderBlock {DIV} at (0,0) size 0x8 47 layer at (260,266) size 8x8 48 RenderBlock {DIV} at (-8,0) size 8x8 42 49 layer at (277,262) size 16x16 43 50 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] -
trunk/LayoutTests/platform/mac/media/controls-strict-expected.txt
r156546 r158713 40 40 layer at (274,267) size 22x22 41 41 RenderFlexibleBox {DIV} at (266,2) size 22x22 42 layer at (274,267) size 2x22 43 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 44 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 45 RenderFlexibleBox {DIV} at (1,1) size 0x8 46 RenderBlock {DIV} at (0,0) size 0x8 47 layer at (260,274) size 8x8 48 RenderBlock {DIV} at (-8,0) size 8x8 42 49 layer at (277,270) size 16x16 43 50 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] -
trunk/LayoutTests/platform/mac/media/controls-styling-strict-expected.txt
r156546 r158713 44 44 layer at (274,267) size 22x22 45 45 RenderFlexibleBox {DIV} at (266,2) size 22x22 46 layer at (274,267) size 2x22 47 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 48 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 49 RenderFlexibleBox {DIV} at (1,1) size 0x8 50 RenderBlock {DIV} at (0,0) size 0x8 51 layer at (260,274) size 8x8 52 RenderBlock {DIV} at (-8,0) size 8x8 46 53 layer at (277,270) size 16x16 47 54 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] … … 77 84 layer at (598,267) size 22x22 78 85 RenderFlexibleBox {DIV} at (266,2) size 22x22 86 layer at (598,267) size 2x22 87 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 88 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 89 RenderFlexibleBox {DIV} at (1,1) size 0x8 90 RenderBlock {DIV} at (0,0) size 0x8 91 layer at (584,274) size 8x8 92 RenderBlock {DIV} at (-8,0) size 8x8 79 93 layer at (601,270) size 16x16 80 94 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] -
trunk/LayoutTests/platform/mac/media/controls-without-preload-expected.txt
r156546 r158713 40 40 layer at (274,259) size 22x22 41 41 RenderFlexibleBox {DIV} at (266,2) size 22x22 42 layer at (274,259) size 2x22 43 RenderFlexibleBox {DIV} at (0,0) size 2x22 [border: (1px solid #000000F3)] 44 RenderSlider {INPUT} at (-7,6) size 2x10 [color=#909090] [border: (1px solid #000000DF)] 45 RenderFlexibleBox {DIV} at (1,1) size 0x8 46 RenderBlock {DIV} at (0,0) size 0x8 47 layer at (260,266) size 8x8 48 RenderBlock {DIV} at (-8,0) size 8x8 42 49 layer at (277,262) size 16x16 43 50 RenderButton {BUTTON} at (3,3) size 16x16 [color=#FFFFFF] -
trunk/Source/WebCore/ChangeLog
r158712 r158713 1 2013-11-05 James Craig <jcraig@apple.com> 2 3 AX: media controls accessibility needs more work 4 https://bugs.webkit.org/show_bug.cgi?id=123749 5 6 Reviewed by Jer Noble. 7 8 Updated some of the control labels/roles to improve accessibility. 9 - Volume slider is now keyboard/screenreader accessible. 10 - muteButton was a checkbox toggling checked state, now a button that toggles label "mute/unmute" 11 - fullscreenButton was a checkbox toggling checked state, now a button that toggles label "display/exit full screen" 12 - captionButton was a checkbox, now a popup button that launches the newly accessible menu. 13 Subtitles menu is now keyboard/screenreader accessible (uses roaming tabindex). 14 Render dump expectations changed because volume slider is now hidden via... 15 ...opacity/size (to make accessible without hover) instead of display:none. 16 17 Updated existing test coverage. 18 19 * Modules/mediacontrols/mediaControlsApple.css: 20 (audio::-webkit-media-controls-panel .volume-box): 21 (audio::-webkit-media-controls-panel .volume-box:active): 22 (audio::-webkit-media-controls-toggle-closed-captions-button): 23 (audio::-webkit-media-controls-closed-captions-container .list): 24 (audio::-webkit-media-controls-closed-captions-container li:focus): 25 * Modules/mediacontrols/mediaControlsApple.js: 26 (Controller.prototype.createControls): 27 (Controller.prototype.handleFullscreenChange): 28 (Controller.prototype.handleMuteButtonClicked): 29 (Controller.prototype.handleMinButtonClicked): 30 (Controller.prototype.handleMaxButtonClicked): 31 (Controller.prototype.handleVolumeSliderChange): 32 (Controller.prototype.buildCaptionMenu): 33 (Controller.prototype.focusSiblingCaptionItem): 34 (Controller.prototype.handleCaptionItemKeyUp): 35 1 36 2013-11-05 Andreas Kling <akling@apple.com> 2 37 -
trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.css
r156546 r158713 173 173 box-sizing: border-box; 174 174 height: 22px; 175 width: 114px;176 175 bottom: 0; 177 176 left: 0; … … 195 194 196 195 opacity: 0; 197 display: none; 198 } 199 196 /* make zero width (rather than display:none) for AX and FKA */ 197 width: 0; /* will become 114px when shown */ 198 199 } 200 201 /* FIXME: needs CSS4 !subject selector to show when slider inside .volume-box is focused */ 200 202 video::-webkit-media-controls-panel .mute-box:hover .volume-box, 201 203 video::-webkit-media-controls-panel .volume-box:hover, … … 205 207 audio::-webkit-media-controls-panel .volume-box:active { 206 208 opacity: 1; 207 display: inherit; 209 /* resize to usable amount (rather than display:none) for AX and FKA */ 210 width: 114px; 208 211 } 209 212 … … 269 272 height: 16px; 270 273 margin: 0 7px; 271 272 274 background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 102 105"><linearGradient id="gradient" x2="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="rgb(216, 216, 216)"/><stop offset="0.46875" stop-color="rgb(216, 216, 216)"/><stop offset="0.46875" stop-color="rgb(208, 208, 208)"/><stop offset="0.53125" stop-color="rgb(208, 208, 208)"/><stop offset="0.53125" stop-color="rgb(200, 200, 200)"/><stop offset="1" stop-color="rgb(208, 208, 208)"/></linearGradient><path d="M98.766,43.224c0-23.163-21.775-41.94-48.637-41.94c-26.859,0-48.635,18.777-48.635,41.94c0,18.266,13.546,33.796,32.444,39.549c1.131,8.356,26.037,24.255,22.864,19.921c-4.462-6.096-5.159-13.183-5.07-17.566C77.85,84.397,98.766,65.923,98.766,43.224z" fill="url(#gradient)"/></svg>'); 275 outline: 0; 273 276 } 274 277 … … 295 298 audio::-webkit-media-controls-closed-captions-container .list { 296 299 display: block; 297 font-family: "Helvetica Bold", Helvetica ;300 font-family: "Helvetica Bold", Helvetica, sans-serif; 298 301 font-size: 10pt; 299 302 -webkit-user-select: none; … … 338 341 } 339 342 343 video::-webkit-media-controls-closed-captions-container li:focus, 344 audio::-webkit-media-controls-closed-captions-container li:focus { 345 outline: 0; 346 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(255, 255, 255, 0.3)), color-stop(1, rgba(255, 255, 255, 0.2))); 347 } 348 340 349 video::-webkit-media-controls-closed-captions-container li:hover, 341 350 audio::-webkit-media-controls-closed-captions-container li:hover { -
trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js
r158455 r158713 77 77 volumeBox: 'volume-box', 78 78 }, 79 KeyCodes: { 80 enter: 13, 81 escape: 27, 82 space: 32, 83 pageUp: 33, 84 pageDown: 34, 85 end: 35, 86 home: 36, 87 left: 37, 88 up: 38, 89 right: 39, 90 down: 40 91 }, 79 92 80 93 // Localized string accessor … … 89 102 'Aborted': 'Aborted', 90 103 'Audio Playback': 'Audio Playback', 104 'Captions': 'Captions', 91 105 'Display Full Screen': 'Display Full Screen', 92 106 'Duration': 'Duration', 107 'Elapsed': 'Elapsed', 93 108 'Error': 'Error', 109 'Exit Full Screen': 'Exit Full Screen', 94 110 'Fast Forward': 'Fast Forward', 95 111 'Loading': 'Loading', … … 97 113 'Minimum Volume': 'Minimum Volume', 98 114 'Mute': 'Mute', 115 'Pause': 'Pause', 99 116 'Play': 'Play', 100 ' Pause': 'Pause',117 'Remaining': 'Remaining', 101 118 'Rewind': 'Rewind', 102 119 'Rewind %%sec%% Seconds': 'Rewind %%sec%% Seconds', 103 'Show Captions': 'Show Captions',104 120 'Stalled': 'Stalled', 121 'Subtitles': 'Subtitles', 105 122 'Suspended': 'Suspended', 106 'Elapsed': 'Elapsed', 107 'Remaining': 'Remaining', 123 'Unmute': 'Unmute', 108 124 'Video Playback': 'Video Playback', 109 125 'Volume': 'Volume', … … 302 318 muteButton.setAttribute('pseudo', '-webkit-media-controls-mute-button'); 303 319 muteButton.setAttribute('aria-label', this.UIString('Mute')); 304 muteButton.setAttribute('role', 'checkbox');305 muteButton.setAttribute('aria-checked', 'false');306 320 this.listenFor(muteButton, 'click', this.handleMuteButtonClicked); 307 321 … … 330 344 var captionButton = this.controls.captionButton = document.createElement('button'); 331 345 captionButton.setAttribute('pseudo', '-webkit-media-controls-toggle-closed-captions-button'); 332 captionButton.setAttribute('aria-label', this.UIString('Show Captions')); 333 captionButton.setAttribute('role', 'checkbox'); 334 captionButton.setAttribute('aria-checked', 'false'); 346 captionButton.setAttribute('aria-label', this.UIString('Captions')); 347 captionButton.setAttribute('aria-haspopup', 'true'); 335 348 this.listenFor(captionButton, 'click', this.handleCaptionButtonClicked); 336 349 … … 338 351 fullscreenButton.setAttribute('pseudo', '-webkit-media-controls-fullscreen-button'); 339 352 fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen')); 340 fullscreenButton.setAttribute('role', 'checkbox');341 fullscreenButton.setAttribute('aria-checked', 'false');342 353 this.listenFor(fullscreenButton, 'click', this.handleFullscreenButtonClicked); 343 354 }, … … 520 531 if (this.isFullScreen()) { 521 532 this.controls.fullscreenButton.classList.add(this.ClassNames.exit); 522 this.controls.fullscreenButton.setAttribute('aria- checked', 'true');533 this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Exit Full Screen')); 523 534 this.setControlsType(Controller.FullScreenControls); 524 535 } else { 525 536 this.controls.fullscreenButton.classList.remove(this.ClassNames.exit); 526 this.controls.fullscreenButton.setAttribute('aria- checked', 'false');537 this.controls.fullscreenButton.setAttribute('aria-label', this.UIString('Display Full Screen')); 527 538 this.setControlsType(Controller.InlineControls); 528 539 } … … 669 680 this.video.muted = !this.video.muted; 670 681 if (this.video.muted) 671 this.controls.muteButton.setAttribute('aria- checked', 'true');682 this.controls.muteButton.setAttribute('aria-label', this.UIString('Unmute')); 672 683 }, 673 684 … … 676 687 if (this.video.muted) { 677 688 this.video.muted = false; 678 this.controls.muteButton.setAttribute('aria- checked', 'false');689 this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); 679 690 } 680 691 this.video.volume = 0; … … 685 696 if (this.video.muted) { 686 697 this.video.muted = false; 687 this.controls.muteButton.setAttribute('aria- checked', 'false');698 this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); 688 699 } 689 700 this.video.volume = 1; … … 694 705 if (this.video.muted) { 695 706 this.video.muted = false; 696 this.controls.muteButton.setAttribute('aria- checked', 'false');707 this.controls.muteButton.setAttribute('aria-label', this.UIString('Mute')); 697 708 } 698 709 this.video.volume = this.controls.volume.value; … … 929 940 930 941 var heading = document.createElement('h3'); 942 heading.id = 'webkitMediaControlsClosedCaptionsHeading'; // for AX menu label 931 943 list.appendChild(heading); 932 heading.innerText = 'Subtitles';944 heading.innerText = this.UIString('Subtitles'); 933 945 934 946 var ul = document.createElement('ul'); 947 ul.setAttribute('role', 'menu'); 948 ul.setAttribute('aria-labelledby', 'webkitMediaControlsClosedCaptionsHeading'); 935 949 list.appendChild(ul); 936 950 937 951 for (var i = 0; i < tracks.length; ++i) { 938 952 var menuItem = document.createElement('li'); 953 menuItem.setAttribute('role', 'menuitemradio'); 954 menuItem.setAttribute('tabindex', '-1'); 939 955 this.captionMenuItems.push(menuItem); 940 956 this.listenFor(menuItem, 'click', this.captionItemSelected); 957 this.listenFor(menuItem, 'keyup', this.handleCaptionItemKeyUp); 941 958 ul.appendChild(menuItem); 942 959 … … 951 968 952 969 if (track === automaticItem) { 953 if (displayMode === 'automatic') 970 if (displayMode === 'automatic') { 954 971 menuItem.classList.add(this.ClassNames.selected); 972 menuItem.setAttribute('tabindex', '0'); 973 menuItem.setAttribute('aria-checked', 'true'); 974 } 955 975 continue; 956 976 } … … 959 979 var trackMenuItemSelected = true; 960 980 menuItem.classList.add(this.ClassNames.selected); 981 menuItem.setAttribute('tabindex', '0'); 982 menuItem.setAttribute('aria-checked', 'true'); 961 983 } 962 } 963 964 if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) 984 985 } 986 987 if (offMenu && displayMode === 'forced-only' && !trackMenuItemSelected) { 965 988 offMenu.classList.add(this.ClassNames.selected); 989 menuItem.setAttribute('tabindex', '0'); 990 menuItem.setAttribute('aria-checked', 'true'); 991 } 992 993 // focus first selected menuitem 994 for (var i = 0, c = this.captionMenuItems.length; i < c; i++) { 995 var item = this.captionMenuItems[i]; 996 if (item.classList.contains(this.ClassNames.selected)) { 997 item.focus(); 998 break; 999 } 1000 } 1001 966 1002 }, 967 1003 … … 972 1008 }, 973 1009 1010 focusSiblingCaptionItem: function(event) 1011 { 1012 var currentItem = event.target; 1013 var pendingItem = false; 1014 switch(event.keyCode) { 1015 case this.KeyCodes.left: 1016 case this.KeyCodes.up: 1017 pendingItem = currentItem.previousSibling; 1018 break; 1019 case this.KeyCodes.right: 1020 case this.KeyCodes.down: 1021 pendingItem = currentItem.nextSibling; 1022 break; 1023 } 1024 if (pendingItem) { 1025 currentItem.setAttribute('tabindex', '-1'); 1026 pendingItem.setAttribute('tabindex', '0'); 1027 pendingItem.focus(); 1028 } 1029 }, 1030 1031 handleCaptionItemKeyUp: function(event) 1032 { 1033 switch (event.keyCode) { 1034 case this.KeyCodes.enter: 1035 case this.KeyCodes.space: 1036 this.captionItemSelected(event); 1037 break; 1038 case this.KeyCodes.escape: 1039 this.destroyCaptionMenu(); 1040 break; 1041 case this.KeyCodes.left: 1042 case this.KeyCodes.up: 1043 case this.KeyCodes.right: 1044 case this.KeyCodes.down: 1045 this.focusSiblingCaptionItem(event); 1046 break; 1047 default: 1048 return; 1049 } 1050 // handled 1051 event.stopPropagation(); 1052 event.preventDefault(); 1053 }, 1054 974 1055 destroyCaptionMenu: function() 975 1056 { … … 979 1060 this.captionMenuItems.forEach(function(item){ 980 1061 this.stopListeningFor(item, 'click', this.captionItemSelected); 1062 this.stopListeningFor(item, 'keyup', this.handleCaptionItemKeyUp); 981 1063 }, this); 1064 1065 // FKA and AX: focus the trigger before destroying the element with focus 1066 if (this.controls.captionButton) 1067 this.controls.captionButton.focus(); 982 1068 983 1069 if (this.captionMenu.parentNode)
Note: See TracChangeset
for help on using the changeset viewer.