From 28888bda5dc35160e871a37d6531c8211f62dfe5 Mon Sep 17 00:00:00 2001 From: Valera Rozuvan Date: Mon, 9 Sep 2013 16:58:11 +0300 Subject: [PATCH] Initial commit. --- .../xmodule/xmodule/css/video/display.scss | 7 ++ .../xmodule/js/src/video/025_focus_grabber.js | 100 ++++++++++++++++++ .../xmodule/js/src/video/04_video_control.js | 4 +- .../xmodule/xmodule/js/src/video/10_main.js | 3 + common/lib/xmodule/xmodule/video_module.py | 1 + lms/templates/video.html | 4 + 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 common/lib/xmodule/xmodule/js/src/video/025_focus_grabber.js diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index 74f5d22b76..d133426fb5 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -15,6 +15,13 @@ div.video { @include clearfix; } + div.focus_grabber { + position: relative; + display: inline; + width: 0px; + height: 0px; + } + article.video-wrapper { float: left; margin-right: flex-gutter(9); diff --git a/common/lib/xmodule/xmodule/js/src/video/025_focus_grabber.js b/common/lib/xmodule/xmodule/js/src/video/025_focus_grabber.js new file mode 100644 index 0000000000..44a003a484 --- /dev/null +++ b/common/lib/xmodule/xmodule/js/src/video/025_focus_grabber.js @@ -0,0 +1,100 @@ +(function (requirejs, require, define) { + +// FocusGrabber module. +define( +'video/025_focus_grabber.js', +[], +function () { + return function (state) { + state.focusGrabber = {}; + + _makeFunctionsPublic(state); + _renderElements(state); + _bindHandlers(state); + }; + + + // Private functions. + + function _makeFunctionsPublic(state) { + state.focusGrabber.enableFocusGrabber = _.bind(enableFocusGrabber, state); + state.focusGrabber.disableFocusGrabber = _.bind(disableFocusGrabber, state); + state.focusGrabber.onFocus = _.bind(onFocus, state); + state.focusGrabber.onBlur = _.bind(onBlur, state); + } + + function _renderElements(state) { + state.focusGrabber.elFirst = state.el.find('.focus_grabber.first'); + state.focusGrabber.elLast = state.el.find('.focus_grabber.last'); + + state.focusGrabber.disableFocusGrabber(); + } + + function _bindHandlers(state) { + state.focusGrabber.elFirst.on('focus', state.focusGrabber.onFocus); + state.focusGrabber.elLast.on('focus', state.focusGrabber.onFocus); + + state.focusGrabber.elFirst.on('blur', state.focusGrabber.onBlur); + state.focusGrabber.elLast.on('blur', state.focusGrabber.onBlur); + } + + + // Public functions. + + function enableFocusGrabber() { + var tabIndex; + + if ($(document.activeElement).parents().hasClass('video')) { + tabIndex = -1; + } else { + tabIndex = 0; + } + + this.focusGrabber.elFirst.attr('tabindex', tabIndex); + this.focusGrabber.elLast.attr('tabindex', tabIndex); + + $(document.activeElement).blur(); + + if (tabIndex === -1) { + this.focusGrabber.elFirst.trigger( + 'focus', + { + simpleFocus: true + } + ); + } + } + + function disableFocusGrabber() { + this.focusGrabber.elFirst.attr('tabindex', -1); + this.focusGrabber.elLast.attr('tabindex', -1); + } + + function onFocus(event, params) { + if (params && params.simpleFocus) { + this.focusGrabber.elFirst.attr('tabindex', 0); + this.focusGrabber.elLast.attr('tabindex', 0); + + return; + } + + this.el.trigger('mousemove'); + this.el.trigger('focus'); + + $('html, body').animate({ + scrollTop: this.el.offset().top + }, 200); + + this.focusGrabber.disableFocusGrabber(); + } + + function onBlur(event) { + this.el.trigger('mousemove'); + this.el.trigger('focus'); + + $('html, body').animate({ + scrollTop: this.el.offset().top + }, 200); + } +}); +}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); diff --git a/common/lib/xmodule/xmodule/js/src/video/04_video_control.js b/common/lib/xmodule/xmodule/js/src/video/04_video_control.js index 69ebaf18c6..a2644c7daf 100644 --- a/common/lib/xmodule/xmodule/js/src/video/04_video_control.js +++ b/common/lib/xmodule/xmodule/js/src/video/04_video_control.js @@ -77,7 +77,7 @@ function () { state.el.on('mousemove', state.videoControl.showControls); state.el.on('keydown', state.videoControl.showControls); } - // The state.previousFocus is used in video_speed_control to track + // The state.previousFocus is used in video_speed_control to track // the element that had the focus before it. state.videoControl.playPauseEl.on('blur', function () { state.previousFocus = 'playPause'; @@ -128,6 +128,8 @@ function () { this.videoControl.el.fadeOut(this.videoControl.fadeOutTimeout, function () { _this.controlState = 'invisible'; + + _this.focusGrabber.enableFocusGrabber(); }); } diff --git a/common/lib/xmodule/xmodule/js/src/video/10_main.js b/common/lib/xmodule/xmodule/js/src/video/10_main.js index 457433592a..df81ba898e 100644 --- a/common/lib/xmodule/xmodule/js/src/video/10_main.js +++ b/common/lib/xmodule/xmodule/js/src/video/10_main.js @@ -4,6 +4,7 @@ require( [ 'video/01_initialize.js', + 'video/025_focus_grabber.js', 'video/04_video_control.js', 'video/05_video_quality_control.js', 'video/06_video_progress_slider.js', @@ -13,6 +14,7 @@ require( ], function ( Initialize, + FocusGrabber, VideoControl, VideoQualityControl, VideoProgressSlider, @@ -60,6 +62,7 @@ function ( youtubeXhr = state.youtubeXhr; } + FocusGrabber(state); VideoControl(state); VideoQualityControl(state); VideoProgressSlider(state); diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py index 984404ef8c..4c269c1f18 100644 --- a/common/lib/xmodule/xmodule/video_module.py +++ b/common/lib/xmodule/xmodule/video_module.py @@ -136,6 +136,7 @@ class VideoModule(VideoFields, XModule): js = { 'js': [ resource_string(__name__, 'js/src/video/01_initialize.js'), + resource_string(__name__, 'js/src/video/025_focus_grabber.js'), resource_string(__name__, 'js/src/video/02_html5_video.js'), resource_string(__name__, 'js/src/video/03_video_player.js'), resource_string(__name__, 'js/src/video/04_video_control.js'), diff --git a/lms/templates/video.html b/lms/templates/video.html index 3f06f00511..398ea0677b 100644 --- a/lms/templates/video.html +++ b/lms/templates/video.html @@ -26,6 +26,8 @@ data-yt-test-timeout="${yt_test_timeout}" data-yt-test-url="${yt_test_url}" > +
+
@@ -70,6 +72,8 @@
+ +
% if sources.get('main'):