Source/WebCore/ChangeLog

 12017-03-29 Aaron Chu <aaron_chu@apple.com>
 2
 3 AX: Modern Media Controls Timeline slider should be operable
 4 https://bugs.webkit.org/show_bug.cgi?id=170250
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Added a "change" event listener and aria-valuetext to the slider so that when a VoiceOver
 9 user operates the timeline control, VO speaks the updated timestamp.
 10
 11 Test: media/modern-media-controls/scrubber/scrubber-has-correct-ax-label.html
 12
 13 * English.lproj/modern-media-controls-localized-strings.js:
 14 * Modules/modern-media-controls/controls/scrubber.js:
 15 (Scrubber.prototype.setAccessibleLabelForInput):
 16 (Scrubber.prototype._formatTime):
 17 (Scrubber.prototype._unitizeTime):
 18 * Modules/modern-media-controls/controls/slider.js:
 19 (Slider.prototype.handleEvent):
 20 * Modules/modern-media-controls/controls/time-control.js:
 21 (TimeControl.prototype.updateScrubberLabel):
 22 * Modules/modern-media-controls/controls/time-label.js:
 23 (TimeLabel.prototype.commitProperty):
 24
1252017-03-28 Youenn Fablet <youenn@apple.com>
226
327 [WebRTC] After r214441 addIceCandidate no longer accepts an RTCIceCandidateInit dictionary

Source/WebCore/English.lproj/modern-media-controls-localized-strings.js

@@const UIStrings = {
66 "Exit Full Screen": "Exit Full Screen",
77 "Error": "Error",
88 "Forward": "Forward",
 9 "Hour": "Hour",
 10 "Hours": "Hours",
911 "Invalid": "Invalid",
1012 "Skip Back 30 seconds": "Skip Back 30 seconds",
1113 "Live Broadcast": "Live Broadcast",
1214 "Loading": "Loading",
 15 "Minute": "Minute",
 16 "Minutes": "Minutes",
1317 "Media Selection": "Media Selection",
1418 "Mute": "Mute",
1519 "Pause": "Pause",

@@const UIStrings = {
1822 "Rewind": "Rewind",
1923 "Scale to Fill": "Scale to Fill",
2024 "Scale to Fit": "Scale to Fit",
 25 "Second": "Second",
 26 "Seconds": "Seconds",
2127 "Subtitles": "Subtitles",
2228 "Start": "Start",
2329 "This video is playing in Picture in Picture": "This video is playing in Picture in Picture",

Source/WebCore/Modules/modern-media-controls/controls/scrubber.js

@@class Scrubber extends Slider
5858 this.needsLayout = true;
5959 }
6060
 61 setAccessibleLabelForInput(label)
 62 {
 63 this._input.element.setAttribute("aria-valuetext", this._formatTime(label));
 64 }
 65
6166 layoutTraitsDidChange()
6267 {
6368 this.height = (this.layoutTraits & LayoutTraits.Compact) ? 15 : 23;

@@class Scrubber extends Slider
6570
6671 // Protected
6772
 73 _formatTime(timeInSeconds)
 74 {
 75 const time = timeInSeconds || 0;
 76 const absTime = Math.abs(time);
 77 const intSeconds = Math.floor(absTime % 60).toFixed(0);
 78 const intMinutes = Math.floor((absTime / 60) % 60).toFixed(0);
 79 const intHours = Math.floor(absTime / (60 * 60)).toFixed(0);
 80
 81 const timeStrings = [this._unitizeTime(intMinutes, "Minute"), this._unitizeTime(intSeconds, "Second")];
 82 if (intHours > 0)
 83 timeStrings.unshift(this._unitizeTime(intHours, "Hour"));
 84
 85 return timeStrings.join(" ");
 86 }
 87
 88 _unitizeTime(value, unit)
 89 {
 90 let returnedUnit = UIString(unit);
 91 if (value > 1)
 92 returnedUnit = UIString(`${unit}s`);
 93
 94 return `${value} ${returnedUnit}`;
 95 }
 96
6897 draw(ctx)
6998 {
7099 const width = this.width;

Source/WebCore/Modules/modern-media-controls/controls/slider.js

@@class Slider extends LayoutItem
3838 this._input = new LayoutNode(`<input type="range" min="0" max="1" step="0.001" />`);
3939 this._input.element.addEventListener("mousedown", this);
4040 this._input.element.addEventListener("input", this);
 41 this._input.element.addEventListener("change", this);
4142
4243 this.isActive = false;
4344 this.value = 0;

@@class Slider extends LayoutItem
7576 case "mouseup":
7677 this._handleMouseupEvent();
7778 break;
 79 case "change":
7880 case "input":
7981 this._handleInputEvent();
8082 break;

Source/WebCore/Modules/modern-media-controls/controls/time-control.js

@@class TimeControl extends LayoutItem
8888 this.remainingTimeLabel.x = this.scrubber.x + this.scrubber.width + ScrubberMargin;
8989 }
9090
 91 updateScrubberLabel()
 92 {
 93 if (this.scrubber)
 94 this.scrubber.setAccessibleLabelForInput(this.elapsedTimeLabel.value);
 95 }
 96
9197}

Source/WebCore/Modules/modern-media-controls/controls/time-label.js

@@class TimeLabel extends LayoutNode
5858 this.element.textContent = this._formattedTime();
5959 else
6060 super.commitProperty(propertyName);
 61
 62 if (this._timeControl)
 63 this._timeControl.updateScrubberLabel();
6164 }
6265
6366 // Private

LayoutTests/ChangeLog

 12017-03-29 Aaron Chu <aaron_chu@apple.com>
 2
 3 AX: Modern Media Controls Timeline slider should be operable
 4 https://bugs.webkit.org/show_bug.cgi?id=170250
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * media/modern-media-controls/scrubber/scrubber-has-correct-ax-label-expected.txt: Added.
 9 * media/modern-media-controls/scrubber/scrubber-has-correct-ax-label.html: Added.
 10
1112017-03-28 Youenn Fablet <youenn@apple.com>
212
313 [WebRTC] After r214441 addIceCandidate no longer accepts an RTCIceCandidateInit dictionary

LayoutTests/media/modern-media-controls/scrubber/scrubber-has-correct-ax-label-expected.txt

 1Testing for an accessibility text on the scrubber that correctly reflects the changes in media.currentTime.
 2
 3On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 4
 5
 6PASS scrubber.getAttribute('aria-valuetext') is "0 Minute 0 Second"
 7PASS media.currentTime is 2
 8PASS scrubber.getAttribute('aria-valuetext') === '0 Minute 2 Seconds' became true
 9PASS successfullyParsed is true
 10
 11TEST COMPLETE
 12
 13

LayoutTests/media/modern-media-controls/scrubber/scrubber-has-correct-ax-label.html

 1<script src="../../../resources/js-test-pre.js"></script>
 2<script src="../resources/media-controls-loader.js" type="text/javascript"></script>
 3<script src="../resources/media-controls-utils.js" type="text/javascript"></script>
 4<body>
 5<style type="text/css" media="screen">
 6
 7 video, #host {
 8 position: absolute;
 9 top: 0;
 10 left: 0;
 11 width: 800px;
 12 height: 240px;
 13 }
 14
 15</style>
 16<video src="../../content/test.mp4" style="width: 320px; height: 240px;" controls></video>
 17<div id="host"></div>
 18<script type="text/javascript">
 19
 20window.jsTestIsAsync = true;
 21
 22description("Testing for an accessibility text on the scrubber that correctly reflects the changes in media.currentTime.");
 23
 24const container = document.querySelector("div#host");
 25const media = document.querySelector("video");
 26const mediaController = createControls(container, media, null);
 27
 28mediaController.controls.showsStartButton = false;
 29
 30const scrubber = mediaController.controls.timeControl.scrubber.children[1].element;
 31
 32media.addEventListener("canplay", () => {
 33
 34 shouldBeEqualToString("scrubber.getAttribute('aria-valuetext')", "0 Minute 0 Second");
 35 media.currentTime = 2;
 36 shouldBe("media.currentTime", "2");
 37 shouldBecomeEqual("scrubber.getAttribute('aria-valuetext') === '0 Minute 2 Seconds'", "true", finishJSTest);
 38})
 39
 40</script>
 41<script src="../../../resources/js-test-post.js"></script>
 42</body>