From 3cb0fd4156e7ef304871961811aabf6bcbbfbae2 Mon Sep 17 00:00:00 2001 From: Ari Rizzitano Date: Tue, 21 Mar 2017 10:30:41 -0400 Subject: [PATCH] adjust focus order and fix duplicate ids in video player (TNL-6361, AC-587) move focus to slider on caption select (TNL-6361) toggle video playback on spacebar press sr text for spacebar explanation focus on slider container instead of handle linter issues cleanup quality more quality ugh wrong var name hack to get around linter more quality pls work this time fix transcript height test hopefully last one fix some ie/ff issues fix dupe ids in video sr instructions. [AC-587] fix test --- .../js/spec/video/video_caption_spec.js | 6 ++- .../spec/video/video_progress_slider_spec.js | 2 +- .../xmodule/js/src/video/03_video_player.js | 2 + .../js/src/video/06_video_progress_slider.js | 48 +++++++++++++++---- .../js/src/video/07_video_volume_control.js | 11 +++-- .../js/src/video/08_video_speed_control.js | 9 +++- .../xmodule/js/src/video/09_video_caption.js | 17 ++++--- 7 files changed, 70 insertions(+), 25 deletions(-) diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js index 7ddda1c092..0a0cdd3dbe 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js @@ -986,9 +986,11 @@ videoWrapperHeight = $('.video-wrapper').height(); progressSliderHeight = state.el.find('.slider').height(); controlHeight = state.el.find('.video-controls').height(); - shouldBeHeight = videoWrapperHeight - + shouldBeHeight = parseInt(( + videoWrapperHeight - 0.5 * progressSliderHeight - - controlHeight; + controlHeight + ), 10); expect(realHeight).toBe(shouldBeHeight); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js index 1f3d5f728d..f5149926f3 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_progress_slider_spec.js @@ -44,7 +44,7 @@ expect(timeControl).toHaveAttrs({ 'role': 'slider', - 'aria-label': 'Video position', + 'aria-label': 'Video position. Press space to toggle playback', 'aria-disabled': 'false' }); diff --git a/common/lib/xmodule/xmodule/js/src/video/03_video_player.js b/common/lib/xmodule/xmodule/js/src/video/03_video_player.js index 6eecd3df86..52b2633099 100644 --- a/common/lib/xmodule/xmodule/js/src/video/03_video_player.js +++ b/common/lib/xmodule/xmodule/js/src/video/03_video_player.js @@ -405,6 +405,8 @@ function(HTML5Video, Resizer) { this.videoPlayer.goToStartTime = false; this.videoPlayer.seekTo(time); + this.trigger('videoProgressSlider.focusSlider'); + this.el.trigger('seek', [time, oldTime, type]); } diff --git a/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js b/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js index b79a17fefe..8c87b6b387 100644 --- a/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js +++ b/common/lib/xmodule/xmodule/js/src/video/06_video_progress_slider.js @@ -12,7 +12,9 @@ mind, or whether to act, and in acting, to live." [], function() { var template = [ - '
' + '
' ].join(''); // VideoProgressSlider() function - what this module "exports". @@ -35,6 +37,8 @@ function() { // // Functions which will be accessible via 'state' object. When called, // these functions will get the 'state' object as a context. + + /* eslint-disable no-use-before-define */ function _makeFunctionsPublic(state) { var methodsDict = { destroy: destroy, @@ -45,7 +49,8 @@ function() { updatePlayTime: updatePlayTime, updateStartEndTimeRegion: updateStartEndTimeRegion, notifyThroughHandleEnd: notifyThroughHandleEnd, - getTimeDescription: getTimeDescription + getTimeDescription: getTimeDescription, + focusSlider: focusSlider }; state.bindTo(methodsDict, state.videoProgressSlider, state); @@ -57,6 +62,12 @@ function() { delete this.videoProgressSlider; } + function bindHandlers(state) { + state.videoProgressSlider.el.on('keypress', sliderToggle.bind(state)); + state.el.on('destroy', state.videoProgressSlider.destroy); + } + /* eslint-enable no-use-before-define */ + // function _renderElements(state) // // Create any necessary DOM elements, attach them, and set their @@ -69,6 +80,7 @@ function() { state.el.find('.video-controls').prepend(state.videoProgressSlider.el); state.videoProgressSlider.buildSlider(); _buildHandle(state); + bindHandlers(state); } function _buildHandle(state) { @@ -77,7 +89,10 @@ function() { // ARIA // We just want the knob to be selectable with keyboard - state.videoProgressSlider.el.attr('tabindex', -1); + state.videoProgressSlider.el.attr({ + tabindex: -1 + }); + // Let screen readers know that this div, representing the slider // handle, behaves as a slider named 'video position'. state.videoProgressSlider.handle.attr({ @@ -89,10 +104,8 @@ function() { 'aria-valuemin': '0', 'aria-valuenow': state.videoPlayer.currentTime, 'tabindex': '0', - 'aria-label': gettext('Video position') + 'aria-label': gettext('Video position. Press space to toggle playback') }); - - state.el.on('destroy', state.videoProgressSlider.destroy); } // *************************************************************** @@ -103,8 +116,11 @@ function() { // *************************************************************** function buildSlider() { - this.videoProgressSlider.el - .append('
'); + var sliderContents = edx.HtmlUtils.joinHtml( + edx.HtmlUtils.HTML('
') + ); + + this.videoProgressSlider.el.append(sliderContents.text); this.videoProgressSlider.slider = this.videoProgressSlider.el .slider({ @@ -328,5 +344,21 @@ function() { return i18n(seconds, 'second'); } + + // Shift focus to the progress slider container element. + function focusSlider() { + this.videoProgressSlider.handle.attr( + 'aria-valuetext', getTimeDescription(this.videoPlayer.currentTime) + ); + this.videoProgressSlider.el.trigger('focus'); + } + + // Toggle video playback when the spacebar is pushed. + function sliderToggle(e) { + if (e.which === 32) { + e.preventDefault(); + this.videoCommands.execute('togglePlayback'); + } + } }); }(RequireJS.requirejs, RequireJS.require, RequireJS.define)); diff --git a/common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js b/common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js index 9ac4fa3d6b..63d7b7ee35 100644 --- a/common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js +++ b/common/lib/xmodule/xmodule/js/src/video/07_video_volume_control.js @@ -40,10 +40,10 @@ function(HtmlUtils) { videoVolumeControlHtml: HtmlUtils.interpolateHtml( HtmlUtils.HTML([ '
', - '

', + '

', '{volumeInstructions}', '

', - '', '', '
' - ].join(''), - { - langTitle: gettext('Open language menu') - } - ) - + ].join('')), + { + langTitle: gettext('Open language menu'), + courseId: this.state.id + } ); var subtitlesHtml = HtmlUtils.interpolateHtml( @@ -109,7 +108,7 @@ [ '
', '

', - '
    ', + '
      ', '
      ' ].join('')), {