diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index ed0131c54c..989ea33a26 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -74,10 +74,8 @@ div.video { } section.video-player { - height: 0; overflow: hidden; - padding-bottom: 56.25%; - position: relative; + min-height: 300px; div { &.hidden { @@ -85,12 +83,9 @@ div.video { } } - object, iframe { + object, iframe, video { border: none; height: 100%; - left: 0; - position: absolute; - top: 0; width: 100%; } @@ -701,15 +696,12 @@ div.video { display: table-cell; vertical-align: middle; float: none; - } - object, iframe { - bottom: 0; - height: 100%; - left: 0; - overflow: hidden; - position: fixed; - top: 0; + object, iframe, video{ + position: absolute; + width: auto; + height: auto; + } } section.video-controls { diff --git a/common/lib/xmodule/xmodule/js/src/video/00_resizer.js b/common/lib/xmodule/xmodule/js/src/video/00_resizer.js new file mode 100644 index 0000000000..e715fc930f --- /dev/null +++ b/common/lib/xmodule/xmodule/js/src/video/00_resizer.js @@ -0,0 +1,134 @@ +(function (requirejs, require, define) { + +define( +'video/00_resizer.js', +[], +function () { + + var Resizer = function (params) { + var defaults = { + container: window, + element: null, + containerRatio: null, + elementRatio: null + }, + mode = null, + config; + + var initialize = function (params) { + if (config) { + config = $.extend(true, config, params); + } else { + config = $.extend(true, {}, defaults, params); + } + + if (!config.element) { + console.log('Required parameter `element` is not passed.'); + } + + return this; + }; + + var getData = function () { + var container = $(config.container), + containerWidth = container.width(), + containerHeight = container.height(), + containerRatio = config.containerRatio, + + element = $(config.element), + elementRatio = config.elementRatio; + + if (!containerRatio) { + containerRatio = containerWidth/containerHeight; + } + + if (!elementRatio) { + elementRatio = element.width()/element.height(); + } + + return { + containerWidth: containerWidth, + containerHeight: containerHeight, + containerRatio: containerRatio, + element: element, + elementRatio: elementRatio + }; + }; + + var align = function() { + var data = getData(); + + switch (mode) { + case 'height': + alignByHeightOnly(); + break; + + case 'width': + alignByWidthOnly(); + break; + + default: + if (data.containerRatio >= data.elementRatio) { + alignByHeightOnly(); + + } else { + alignByWidthOnly(); + } + break; + } + + return this; + }; + + var alignByWidthOnly = function () { + var data = getData(), + height = data.containerWidth/data.elementRatio; + + data.element.css({ + 'height': height, + 'width': data.containerWidth, + 'top': 0.5*(data.containerHeight - height), + 'left': 0 + }); + + return this; + }; + + var alignByHeightOnly = function () { + var data = getData(), + width = data.containerHeight*data.elementRatio; + + data.element.css({ + 'height': data.containerHeight, + 'width': data.containerHeight*data.elementRatio, + 'top': 0, + 'left': 0.5*(data.containerWidth - width) + }); + + return this; + }; + + var setMode = function (param) { + if (_.isString(param)) { + mode = param; + align(); + } + + return this; + }; + + initialize.apply(this, arguments); + + return { + align: align, + alignByWidthOnly: alignByWidthOnly, + alignByHeightOnly: alignByHeightOnly, + setParams: initialize, + setMode: setMode + }; + }; + + return Resizer; +}); + +}(RequireJS.requirejs, RequireJS.require, RequireJS.define)); diff --git a/common/lib/xmodule/xmodule/js/src/video/02_html5_video.js b/common/lib/xmodule/xmodule/js/src/video/02_html5_video.js index 541c5b0bf4..6cd38b30bd 100644 --- a/common/lib/xmodule/xmodule/js/src/video/02_html5_video.js +++ b/common/lib/xmodule/xmodule/js/src/video/02_html5_video.js @@ -216,10 +216,6 @@ function () { // currently doing. this.videoEl = $(this.video); - this.videoEl.css({ - 'width': '100%' - }); - this.playerState = HTML5Video.PlayerState.UNSTARTED; // this.callStateChangeCallback(); @@ -318,6 +314,6 @@ function () { // HTML5Video object - what this module exports. return HTML5Video; -}) +}); }(RequireJS.requirejs, RequireJS.require, RequireJS.define)); 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 0fcbe42578..455d00c120 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 @@ -3,8 +3,8 @@ // VideoPlayer module. define( 'video/03_video_player.js', -['video/02_html5_video.js'], -function (HTML5Video) { +['video/02_html5_video.js', 'video/00_resizer.js' ], +function (HTML5Video, Resizer) { // VideoPlayer() function - what this module "exports". return function (state) { @@ -343,7 +343,8 @@ function (HTML5Video) { } function onReady() { - var availablePlaybackRates, baseSpeedSubs, _this; + var availablePlaybackRates, baseSpeedSubs, _this, + player, videoWidth, videoHeight; this.videoPlayer.log('load_video'); @@ -420,6 +421,27 @@ function (HTML5Video) { this.videoPlayer.player.setPlaybackRate(this.speed); } + if (this.videoType === 'html5') { + player = this.videoEl = this.videoPlayer.player.videoEl; + videoWidth = player[0].videoWidth || player.width(); + videoHeight = player[0].videoHeight || player.height(); + } else { + player = this.videoEl = this.el.find('iframe'); + videoWidth = player.attr('width') || player.width(); + videoHeight = player.attr('height') || player.height(); + } + + this.resizer = new Resizer({ + element: this.videoEl, + elementRatio: videoWidth/videoHeight, + container: this.videoEl.parent() + }) + .setMode('width'); + + this.trigger('videoCaption.resize', null); + $(window).bind('resize', _.debounce(this.resizer.align, 100)); + + /* The following has been commented out to make sure autoplay is disabled for students. if ( 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 8ba7490cef..9710502aae 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 @@ -170,22 +170,41 @@ function () { function toggleFullScreen(event) { event.preventDefault(); - var fullScreenClassNameEl = this.el.add(document.documentElement); + var fullScreenClassNameEl = this.el.add(document.documentElement), + win = $(window), + text; if (this.videoControl.fullScreenState) { - this.videoControl.fullScreenState = false; + this.videoControl.fullScreenState = this.isFullScreen = false; fullScreenClassNameEl.removeClass('video-fullscreen'); - this.isFullScreen = false; - this.videoControl.fullScreenEl.attr('title', gettext('Fill browser')) - .text(gettext('Fill browser')); + text = gettext('Fill browser'); + + this.resizer + .setParams({ + container: this.videoEl.parent() + }) + .setMode('width'); + + win.scrollTop(this.scrollPos); } else { - this.videoControl.fullScreenState = true; + this.scrollPos = win.scrollTop(); + win.scrollTop(0); + this.videoControl.fullScreenState = this.isFullScreen = true; fullScreenClassNameEl.addClass('video-fullscreen'); - this.isFullScreen = true; - this.videoControl.fullScreenEl.attr('title', gettext('Exit full browser')) - .text(gettext('Exit full browser')); + text = gettext('Exit full browser'); + + this.resizer + .setParams({ + container: window + }) + .setMode('both'); + } + this.videoControl.fullScreenEl + .attr('title', text) + .text(text); + this.trigger('videoCaption.resize', null); } diff --git a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js index 21cc64e81c..668281b533 100644 --- a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js +++ b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js @@ -700,7 +700,7 @@ function () { function hideCaptions(hide_captions, update_cookie) { var hideSubtitlesEl = this.videoCaption.hideSubtitlesEl, - type; + type, text; if (typeof update_cookie === 'undefined') { update_cookie = true; @@ -710,29 +710,33 @@ function () { type = 'hide_transcript'; this.captionsHidden = true; - hideSubtitlesEl - .attr('title', gettext('Turn on captions')) - .text(gettext('Turn on captions')); - this.el.addClass('closed'); + + text = gettext('Turn on captions'); } else { type = 'show_transcript'; this.captionsHidden = false; - hideSubtitlesEl - .attr('title', gettext('Turn off captions')) - .text(gettext('Turn off captions')); - this.el.removeClass('closed'); this.videoCaption.scrollCaption(); + + text = gettext('Turn off captions'); } + hideSubtitlesEl + .attr('title', text) + .text(gettext(text)); + if (this.videoPlayer) { this.videoPlayer.log(type, { currentTime: this.videoPlayer.currentTime }); } + if (this.resizer) { + this.resizer.alignByWidthOnly(); + } + this.videoCaption.setSubtitlesHeight(); if (update_cookie) { diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py index 764456d582..944a86d73b 100644 --- a/common/lib/xmodule/xmodule/video_module.py +++ b/common/lib/xmodule/xmodule/video_module.py @@ -135,6 +135,7 @@ class VideoModule(VideoFields, XModule): js = { 'js': [ + resource_string(__name__, 'js/src/video/00_resizer.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'),