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/spec/video/resizer_spec.js b/common/lib/xmodule/xmodule/js/spec/video/resizer_spec.js
new file mode 100644
index 0000000000..a05e9e8bb8
--- /dev/null
+++ b/common/lib/xmodule/xmodule/js/spec/video/resizer_spec.js
@@ -0,0 +1,93 @@
+(function (requirejs, require, define) {
+
+require(
+['video/00_resizer.js'],
+function (Resizer) {
+
+ describe('Resizer', function () {
+ var html = [
+ '
',
+ '
',
+ 'Content',
+ '
',
+ '
'
+ ].join(''),
+ config, container, element;
+
+ beforeEach(function () {
+ setFixtures(html);
+
+ container = $('.rszr-wrapper');
+ element = $('.rszr-el');
+ config = {
+ container: container,
+ element: element
+ };
+ });
+
+ it('When Initialize without required parameters, log message is shown',
+ function () {
+ spyOn(console, 'log');
+
+ new Resizer({ });
+ expect(console.log).toHaveBeenCalled();
+ }
+ );
+
+ it('`alignByWidthOnly` works correctly', function () {
+ var resizer = new Resizer(config).alignByWidthOnly(),
+ expectedWidth = container.width(),
+ realWidth = element.width();
+
+ expect(realWidth).toBe(expectedWidth);
+ });
+
+ it('`alignByHeightOnly` works correctly', function () {
+ var resizer = new Resizer(config).alignByHeightOnly(),
+ expectedHeight = container.height(),
+ realHeight = element.height(),
+ realWidth;
+
+ expect(realHeight).toBe(expectedHeight);
+ });
+
+ it('`align` works correctly', function () {
+ var resizer = new Resizer(config).align(),
+ expectedHeight = container.height(),
+ realHeight = element.height(),
+ expectedWidth = 50;
+
+ // containerRatio >= elementRatio
+ expect(realHeight).toBe(expectedHeight);
+
+ // containerRatio < elementRatio
+ container.width(expectedWidth);
+ resizer.align();
+ realWidth = element.width();
+
+ expect(realWidth).toBe(expectedWidth);
+
+ });
+
+ it('`setMode` works correctly', function () {
+ var resizer = new Resizer(config).setMode('height'),
+ expectedHeight = container.height(),
+ realHeight = element.height(),
+ expectedWidth = 50;
+
+ // containerRatio >= elementRatio
+ expect(realHeight).toBe(expectedHeight);
+
+ // containerRatio < elementRatio
+ container.width(expectedWidth);
+ resizer.setMode('width');
+ realWidth = element.width();
+
+ expect(realWidth).toBe(expectedWidth);
+ });
+
+ });
+});
+
+
+}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
index 00f51a4c80..3f5e1831ac 100644
--- a/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
+++ b/common/lib/xmodule/xmodule/js/spec/video/video_player_spec.js
@@ -10,6 +10,8 @@
}
state = new Video('#example');
+
+ state.videoEl = $('video, iframe');
videoPlayer = state.videoPlayer;
player = videoPlayer.player;
videoControl = state.videoControl;
@@ -17,6 +19,19 @@
videoProgressSlider = state.videoProgressSlider;
videoSpeedControl = state.videoSpeedControl;
videoVolumeControl = state.videoVolumeControl;
+
+ state.resizer = (function () {
+ var methods = [
+ 'align', 'alignByWidthOnly', 'alignByHeightOnly', 'setParams', 'setMode'
+ ],
+ obj = {};
+
+ $.each(methods, function(index, method) {
+ obj[method] = jasmine.createSpy(method).andReturn(obj);
+ });
+
+ return obj;
+ })();
}
function initializeYouTube() {
@@ -557,6 +572,7 @@
it('tell VideoCaption to resize', function() {
expect(videoCaption.resize).toHaveBeenCalled();
+ expect(state.resizer.setMode).toHaveBeenCalled();
});
});
@@ -583,6 +599,7 @@
it('tell VideoCaption to resize', function() {
expect(videoCaption.resize).toHaveBeenCalled();
+ expect(state.resizer.setMode).toHaveBeenCalledWith('width');
});
});
});
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'),