Commit 7c59947a by Vasyl Nakvasiuk

refactoring JS -> HTML

second part of refactoring: JS -> Python HTML
Updated JS code to reflect the change that some HTML generation was moved to python side.
Fixed fullscreen bug - now controls are shown properly below the video. Made the transparency a bit more faded for captions in normal mode.
Fixed bug with captions. Now the attribute show_captions correctly removes them when set to true.
Work in progress.
parent 0e24ff14
...@@ -519,7 +519,7 @@ div.videoalpha { ...@@ -519,7 +519,7 @@ div.videoalpha {
} }
ol.subtitles.html5 { ol.subtitles.html5 {
background-color: rgba(243, 243, 243, 0.5); background-color: rgba(243, 243, 243, 0.8);
height: 380px; height: 380px;
position: absolute; position: absolute;
right: 0; right: 0;
...@@ -550,12 +550,22 @@ div.videoalpha { ...@@ -550,12 +550,22 @@ div.videoalpha {
} }
} }
article.video-wrapper div.video-player-pre, article.video-wrapper div.video-player-post {
height: 0px;
}
article.video-wrapper {
position: static;
}
div.tc-wrapper { div.tc-wrapper {
@include clearfix; @include clearfix;
display: table; display: table;
width: 100%; width: 100%;
height: 100%; height: 100%;
position: static;
article.video-wrapper { article.video-wrapper {
width: 100%; width: 100%;
display: table-cell; display: table-cell;
......
...@@ -17,9 +17,7 @@ define( ...@@ -17,9 +17,7 @@ define(
'videoalpha/display/html5_video.js', 'videoalpha/display/html5_video.js',
[], [],
function () { function () {
var HTML5Video; var HTML5Video = {};
HTML5Video = {};
HTML5Video.Player = (function () { HTML5Video.Player = (function () {
Player.prototype.callStateChangeCallback = function () { Player.prototype.callStateChangeCallback = function () {
...@@ -129,9 +127,21 @@ function () { ...@@ -129,9 +127,21 @@ function () {
// If el is string, we assume it is an ID of a DOM element. Get the element, and check that the ID // If el is string, we assume it is an ID of a DOM element. Get the element, and check that the ID
// really belongs to an element. If we didn't get a DOM element, return. At this stage, nothing will // really belongs to an element. If we didn't get a DOM element, return. At this stage, nothing will
// break because other parts of the video player are waiting for 'onReady' callback to be called. // break because other parts of the video player are waiting for 'onReady' callback to be called.
if (typeof el === 'string') {
// REFACTOR: Use .length === 0
this.el = $(el); this.el = $(el);
// REFACTOR: Simplify chck.
if (this.el.length === 0) {
return;
}
if (typeof el === 'string') {
this.el = $(el);
// REFACTOR: Simplify chck.
if (this.el.length === 0) { if (this.el.length === 0) {
return; return;
} }
...@@ -294,6 +304,7 @@ function () { ...@@ -294,6 +304,7 @@ function () {
} }
}()); }());
// REFACTOR: Doc.
HTML5Video.PlayerState = { HTML5Video.PlayerState = {
'UNSTARTED': -1, 'UNSTARTED': -1,
'ENDED': 0, 'ENDED': 0,
......
...@@ -64,20 +64,20 @@ function (VideoPlayer) { ...@@ -64,20 +64,20 @@ function (VideoPlayer) {
// We store all settings passed to us by the server in one place. These are "read only", so don't // We store all settings passed to us by the server in one place. These are "read only", so don't
// modify them. All variable content lives in 'state' object. // modify them. All variable content lives in 'state' object.
state.config = { state.config = {
'element': element, element: element,
'start': state.el.data('start'), start: state.el.data('start'),
'end': state.el.data('end'), end: state.el.data('end'),
'caption_data_dir': state.el.data('caption-data-dir'), caption_data_dir: state.el.data('caption-data-dir'),
'caption_asset_path': state.el.data('caption-asset-path'), caption_asset_path: state.el.data('caption-asset-path'),
'show_captions': (state.el.data('show-captions').toString().toLowerCase === 'true'), show_captions: (state.el.data('show-captions').toString().toLowerCase() === 'true'),
'youtubeStreams': state.el.data('streams'), youtubeStreams: state.el.data('streams'),
'sub': state.el.data('sub'), sub: state.el.data('sub'),
'mp4Source': state.el.data('mp4-source'), mp4Source: state.el.data('mp4-source'),
'webmSource': state.el.data('webm-source'), webmSource: state.el.data('webm-source'),
'oggSource': state.el.data('ogg-source') oggSource: state.el.data('ogg-source')
}; };
// Try to parse YouTube stream ID's. If // Try to parse YouTube stream ID's. If
...@@ -101,7 +101,7 @@ function (VideoPlayer) { ...@@ -101,7 +101,7 @@ function (VideoPlayer) {
} }
); );
if (!state.config.sub.length) { if (!state.config.sub || !state.config.sub.length) {
state.config.sub = ''; state.config.sub = '';
state.config.show_captions = false; state.config.show_captions = false;
} }
...@@ -149,14 +149,14 @@ function (VideoPlayer) { ...@@ -149,14 +149,14 @@ function (VideoPlayer) {
// in a browser that doesn't fully support HTML5. When we have this setting in cookies, we can select // in a browser that doesn't fully support HTML5. When we have this setting in cookies, we can select
// the proper mode from the start (not having to change mode later on). // the proper mode from the start (not having to change mode later on).
(function (currentPlayerMode) { (function (currentPlayerMode) {
if ((currentPlayerMode !== 'html5') && (currentPlayerMode !== 'flash')) { if ((currentPlayerMode === 'html5') || (currentPlayerMode === 'flash')) {
state.currentPlayerMode = currentPlayerMode;
} else {
$.cookie('current_player_mode', 'html5', { $.cookie('current_player_mode', 'html5', {
'expires': 3650, 'expires': 3650,
'path': '/' 'path': '/'
}); });
state.currentPlayerMode = 'html5'; state.currentPlayerMode = 'html5';
} else {
state.currentPlayerMode = currentPlayerMode;
} }
}($.cookie('current_player_mode'))); }($.cookie('current_player_mode')));
...@@ -222,7 +222,7 @@ function (VideoPlayer) { ...@@ -222,7 +222,7 @@ function (VideoPlayer) {
state.html5Sources = { 'mp4': null, 'webm': null, 'ogg': null }; state.html5Sources = { 'mp4': null, 'webm': null, 'ogg': null };
$.each(sources, function (name, source) { $.each(sources, function (name, source) {
if (source.length) { if (source && source.length) {
state.html5Sources[name] = source; state.html5Sources[name] = source;
} }
}); });
...@@ -255,6 +255,14 @@ function (VideoPlayer) { ...@@ -255,6 +255,14 @@ function (VideoPlayer) {
} }
function checkForNativeFunctions() { function checkForNativeFunctions() {
// REFACTOR:
// 1.) IE8 doc.
// 2.) Move to separate file.
// 3.) Write about a generic soluction system wide.
//
// IE browser supports Function.bind() only starting with version 8.
//
// The bind function is a recent addition to ECMA-262, 5th edition; as such it may not be present in all // The bind function is a recent addition to ECMA-262, 5th edition; as such it may not be present in all
// browsers. You can partially work around this by inserting the following code at the beginning of your // browsers. You can partially work around this by inserting the following code at the beginning of your
// scripts, allowing use of much of the functionality of bind() in implementations that do not natively support // scripts, allowing use of much of the functionality of bind() in implementations that do not natively support
......
...@@ -53,10 +53,8 @@ function () { ...@@ -53,10 +53,8 @@ function () {
function renderElements(state) { function renderElements(state) {
state.videoCaption.loaded = false; state.videoCaption.loaded = false;
state.videoCaption.subtitlesEl = $('<ol class="subtitles"></ol>'); state.videoCaption.subtitlesEl = state.el.find('ol.subtitles');
state.videoCaption.hideSubtitlesEl = $( state.videoCaption.hideSubtitlesEl = state.el.find('a.hide-subtitles');
'<a href="#" class="hide-subtitles" title="Turn off captions">Captions</a>'
);
state.el.find('.video-wrapper').after(state.videoCaption.subtitlesEl); state.el.find('.video-wrapper').after(state.videoCaption.subtitlesEl);
state.el.find('.video-controls .secondary-controls').append(state.videoCaption.hideSubtitlesEl); state.el.find('.video-controls .secondary-controls').append(state.videoCaption.hideSubtitlesEl);
...@@ -67,6 +65,7 @@ function () { ...@@ -67,6 +65,7 @@ function () {
fetchCaption(state); fetchCaption(state);
// REFACTOR. Const.
if (state.videoType === 'html5') { if (state.videoType === 'html5') {
state.videoCaption.fadeOutTimeout = 1400; state.videoCaption.fadeOutTimeout = 1400;
...@@ -81,6 +80,8 @@ function () { ...@@ -81,6 +80,8 @@ function () {
function bindHandlers(state) { function bindHandlers(state) {
$(window).bind('resize', state.videoCaption.resize); $(window).bind('resize', state.videoCaption.resize);
state.videoCaption.hideSubtitlesEl.click(state.videoCaption.toggle); state.videoCaption.hideSubtitlesEl.click(state.videoCaption.toggle);
// REFACTOR: Use .on()
state.videoCaption.subtitlesEl.mouseenter( state.videoCaption.subtitlesEl.mouseenter(
state.videoCaption.onMouseEnter state.videoCaption.onMouseEnter
).mouseleave( ).mouseleave(
...@@ -136,6 +137,8 @@ function () { ...@@ -136,6 +137,8 @@ function () {
this.captionsShowLock = true; this.captionsShowLock = true;
// REFACTOR.
if (this.captionState === 'invisible') { if (this.captionState === 'invisible') {
this.videoCaption.subtitlesEl.show(); this.videoCaption.subtitlesEl.show();
this.captionState = 'visible'; this.captionState = 'visible';
...@@ -168,6 +171,7 @@ function () { ...@@ -168,6 +171,7 @@ function () {
_this = this; _this = this;
// REFACTOR.
this.videoCaption.subtitlesEl.fadeOut(1000, function () { this.videoCaption.subtitlesEl.fadeOut(1000, function () {
_this.captionState = 'invisible'; _this.captionState = 'invisible';
}); });
...@@ -178,6 +182,7 @@ function () { ...@@ -178,6 +182,7 @@ function () {
'maxHeight': this.videoCaption.captionHeight() 'maxHeight': this.videoCaption.captionHeight()
}); });
// REFACTOR: Chain.
this.videoCaption.subtitlesEl.find('.spacing:first').height(this.videoCaption.topSpacingHeight()); this.videoCaption.subtitlesEl.find('.spacing:first').height(this.videoCaption.topSpacingHeight());
this.videoCaption.subtitlesEl.find('.spacing:last').height(this.videoCaption.bottomSpacingHeight()); this.videoCaption.subtitlesEl.find('.spacing:last').height(this.videoCaption.bottomSpacingHeight());
...@@ -189,6 +194,7 @@ function () { ...@@ -189,6 +194,7 @@ function () {
clearTimeout(this.videoCaption.frozen); clearTimeout(this.videoCaption.frozen);
} }
// REFACTOR.
this.videoCaption.frozen = setTimeout(this.videoCaption.onMouseLeave, 10000); this.videoCaption.frozen = setTimeout(this.videoCaption.onMouseLeave, 10000);
} }
...@@ -209,23 +215,25 @@ function () { ...@@ -209,23 +215,25 @@ function () {
} }
function renderCaption() { function renderCaption() {
var container, _this; var container, _this = this;
_this = this;
container = $('<ol>'); container = $('<ol>');
$.each(this.videoCaption.captions, function(index, text) { $.each(this.videoCaption.captions, function(index, text) {
// REFACTOR: Use .data()
container.append($('<li>').html(text).attr({ container.append($('<li>').html(text).attr({
'data-index': index, 'data-index': index,
'data-start': _this.videoCaption.start[index] 'data-start': _this.videoCaption.start[index]
})); }));
}); });
// REFACTOR: Chain.
this.videoCaption.subtitlesEl.html(container.html()); this.videoCaption.subtitlesEl.html(container.html());
this.videoCaption.subtitlesEl.find('li[data-index]').on('click', this.videoCaption.seekPlayer); this.videoCaption.subtitlesEl.find('li[data-index]').on('click', this.videoCaption.seekPlayer);
this.videoCaption.subtitlesEl.prepend( this.videoCaption.subtitlesEl
.prepend(
$('<li class="spacing">').height(this.videoCaption.topSpacingHeight()) $('<li class="spacing">').height(this.videoCaption.topSpacingHeight())
).append( )
.append(
$('<li class="spacing">').height(this.videoCaption.bottomSpacingHeight()) $('<li class="spacing">').height(this.videoCaption.bottomSpacingHeight())
); );
...@@ -233,10 +241,17 @@ function () { ...@@ -233,10 +241,17 @@ function () {
} }
function scrollCaption() { function scrollCaption() {
if (!this.videoCaption.frozen && this.videoCaption.subtitlesEl.find('.current:first').length) { // REFACTOR: Cache current:first
this.videoCaption.subtitlesEl.scrollTo(this.videoCaption.subtitlesEl.find('.current:first'), { if (
!this.videoCaption.frozen &&
this.videoCaption.subtitlesEl.find('.current:first').length
) {
this.videoCaption.subtitlesEl.scrollTo(
this.videoCaption.subtitlesEl.find('.current:first'),
{
'offset': -this.videoCaption.calculateOffset(this.videoCaption.subtitlesEl.find('.current:first')) 'offset': -this.videoCaption.calculateOffset(this.videoCaption.subtitlesEl.find('.current:first'))
}); }
);
} }
} }
...@@ -352,6 +367,7 @@ function () { ...@@ -352,6 +367,7 @@ function () {
} }
function captionHeight() { function captionHeight() {
// REFACTOR: Use property instead of class.
if (this.el.hasClass('fullscreen')) { if (this.el.hasClass('fullscreen')) {
return $(window).height() - this.el.find('.video-controls').height(); return $(window).height() - this.el.find('.video-controls').height();
} else { } else {
......
...@@ -40,23 +40,10 @@ function () { ...@@ -40,23 +40,10 @@ function () {
// make the created DOM elements available via the 'state' object. Much easier to work this // make the created DOM elements available via the 'state' object. Much easier to work this
// way - you don't have to do repeated jQuery element selects. // way - you don't have to do repeated jQuery element selects.
function renderElements(state) { function renderElements(state) {
var el, qTipConfig; var qTipConfig;
// REFACTOR move templates and css to one file- to python part
el = $(
'<div class="slider"></div>' +
'<div>' +
'<ul class="vcr">' +
'<li><a class="video_control" href="#" title="Play"></a></li>' +
'<li><div class="vidtime">0:00 / 0:00</div></li>' +
'</ul>' +
'<div class="secondary-controls">' +
'<a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>' +
'</div>' +
'</div>'
);
state.videoControl.el = state.el.find('.video-controls'); state.videoControl.el = state.el.find('.video-controls');
state.videoControl.el.append(el); // state.videoControl.el.append(el);
state.videoControl.sliderEl = state.videoControl.el.find('.slider'); state.videoControl.sliderEl = state.videoControl.el.find('.slider');
state.videoControl.playPauseEl = state.videoControl.el.find('.video_control'); state.videoControl.playPauseEl = state.videoControl.el.find('.video_control');
...@@ -83,6 +70,8 @@ function () { ...@@ -83,6 +70,8 @@ function () {
} }
if (state.videoType === 'html5') { if (state.videoType === 'html5') {
// REFACTOR: constants move to initialize()
state.videoControl.fadeOutTimeout = 1400; state.videoControl.fadeOutTimeout = 1400;
state.videoControl.el.addClass('html5'); state.videoControl.el.addClass('html5');
...@@ -118,6 +107,9 @@ function () { ...@@ -118,6 +107,9 @@ function () {
this.controlShowLock = true; this.controlShowLock = true;
// Refactor: separate UI state in object. No code duplication. // Refactor: separate UI state in object. No code duplication.
// REFACTOR:
// 1.) Chain jQuery calls.
// 2.) Drop out common code.
if (this.controlState === 'invisible') { if (this.controlState === 'invisible') {
this.videoControl.el.show(); this.videoControl.el.show();
this.controlState = 'visible'; this.controlState = 'visible';
...@@ -156,6 +148,7 @@ function () { ...@@ -156,6 +148,7 @@ function () {
} }
function play() { function play() {
// REFACTOR: this.videoControl.playPauseState should be bool.
this.videoControl.playPauseEl.removeClass('play').addClass('pause').attr('title', 'Pause'); this.videoControl.playPauseEl.removeClass('play').addClass('pause').attr('title', 'Pause');
this.videoControl.playPauseState = 'playing'; this.videoControl.playPauseState = 'playing';
} }
...@@ -181,17 +174,18 @@ function () { ...@@ -181,17 +174,18 @@ function () {
if (this.videoControl.fullScreenState) { if (this.videoControl.fullScreenState) {
this.videoControl.fullScreenState = false; this.videoControl.fullScreenState = false;
this.el.removeClass('fullscreen'); this.el.removeClass('fullscreen');
this.videoControl.fullScreenEl.attr('title', 'Fill browser'); this.videoControl.fullScreenEl.attr('title', 'Fullscreen');
} else { } else {
this.videoControl.fullScreenState = true; this.videoControl.fullScreenState = true;
this.el.addClass('fullscreen'); this.el.addClass('fullscreen');
this.videoControl.fullScreenEl.attr('title', 'Exit fill browser'); this.videoControl.fullScreenEl.attr('title', 'Exit fullscreen');
} }
this.trigger(['videoCaption', 'resize'], null); this.trigger(['videoCaption', 'resize'], null);
} }
function exitFullScreen(event) { function exitFullScreen(event) {
// REFACTOR: Add variable instead of class.
if ((this.el.hasClass('fullscreen')) && (event.keyCode === 27)) { if ((this.el.hasClass('fullscreen')) && (event.keyCode === 27)) {
this.videoControl.toggleFullScreen(event); this.videoControl.toggleFullScreen(event);
} }
......
...@@ -250,6 +250,8 @@ function (HTML5Video) { ...@@ -250,6 +250,8 @@ function (HTML5Video) {
function onReady() { function onReady() {
var availablePlaybackRates, baseSpeedSubs, _this; var availablePlaybackRates, baseSpeedSubs, _this;
// REFACTOR: Check if logic.
availablePlaybackRates = this.videoPlayer.player.getAvailablePlaybackRates(); availablePlaybackRates = this.videoPlayer.player.getAvailablePlaybackRates();
if ((this.currentPlayerMode === 'html5') && (this.videoType === 'youtube')) { if ((this.currentPlayerMode === 'html5') && (this.videoType === 'youtube')) {
if (availablePlaybackRates.length === 1) { if (availablePlaybackRates.length === 1) {
......
...@@ -97,7 +97,6 @@ function () { ...@@ -97,7 +97,6 @@ function () {
function onSlide(event, ui) { function onSlide(event, ui) {
this.videoProgressSlider.frozen = true; this.videoProgressSlider.frozen = true;
this.videoProgressSlider.updateTooltip(ui.value); this.videoProgressSlider.updateTooltip(ui.value);
this.trigger(['videoPlayer', 'onSeek'], ui.value); this.trigger(['videoPlayer', 'onSeek'], ui.value);
} }
...@@ -106,9 +105,7 @@ function () { ...@@ -106,9 +105,7 @@ function () {
} }
function onStop(event, ui) { function onStop(event, ui) {
var _this; var _this = this;
_this = this;
this.videoProgressSlider.frozen = true; this.videoProgressSlider.frozen = true;
...@@ -125,6 +122,7 @@ function () { ...@@ -125,6 +122,7 @@ function () {
function updatePlayTime(params) { function updatePlayTime(params) {
if ((this.videoProgressSlider.slider) && (!this.videoProgressSlider.frozen)) { if ((this.videoProgressSlider.slider) && (!this.videoProgressSlider.frozen)) {
// REFACTOR: Check if you can chain.
this.videoProgressSlider.slider.slider('option', 'max', params.duration); this.videoProgressSlider.slider.slider('option', 'max', params.duration);
this.videoProgressSlider.slider.slider('value', params.time); this.videoProgressSlider.slider.slider('value', params.time);
} }
......
...@@ -39,14 +39,12 @@ function () { ...@@ -39,14 +39,12 @@ function () {
// make the created DOM elements available via the 'state' object. Much easier to work this // make the created DOM elements available via the 'state' object. Much easier to work this
// way - you don't have to do repeated jQuery element selects. // way - you don't have to do repeated jQuery element selects.
function renderElements(state) { function renderElements(state) {
state.videoQualityControl.el = $( state.videoQualityControl.el = state.el.find('a.quality_control');
'<a href="#" class="quality_control" title="HD">HD</a>'
);
state.videoControl.secondaryControlsEl.append(state.videoQualityControl.el);
state.videoQualityControl.quality = null; state.videoQualityControl.quality = null;
if (!onTouchBasedDevice()) { if (!onTouchBasedDevice()) {
// REFACTOR: Move qtip config to state.config
state.videoQualityControl.el.qtip({ state.videoQualityControl.el.qtip({
'position': { 'position': {
'my': 'top right', 'my': 'top right',
...@@ -72,6 +70,7 @@ function () { ...@@ -72,6 +70,7 @@ function () {
function onQualityChange(value) { function onQualityChange(value) {
this.videoQualityControl.quality = value; this.videoQualityControl.quality = value;
// refactor: Move constants to state.config.
if ((value === 'hd720') || (value === 'hd1080') || (value === 'highres')) { if ((value === 'hd720') || (value === 'hd1080') || (value === 'highres')) {
this.videoQualityControl.el.addClass('active'); this.videoQualityControl.el.addClass('active');
} else { } else {
...@@ -86,6 +85,7 @@ function () { ...@@ -86,6 +85,7 @@ function () {
_ref = this.videoQualityControl.quality; _ref = this.videoQualityControl.quality;
// refactor: Move constants to state.config.
if ((_ref === 'hd720') || (_ref === 'hd1080') || (_ref === 'highres')) { if ((_ref === 'hd720') || (_ref === 'hd1080') || (_ref === 'highres')) {
newQuality = 'large'; newQuality = 'large';
} else { } else {
......
...@@ -37,27 +37,19 @@ function () { ...@@ -37,27 +37,19 @@ function () {
function renderElements(state) { function renderElements(state) {
state.videoSpeedControl.speeds = state.speeds; state.videoSpeedControl.speeds = state.speeds;
state.videoSpeedControl.el = $( state.videoSpeedControl.el = state.el.find('div.speeds');
'<div class="speeds">' +
'<a href="#">' +
'<h3>Speed</h3>' +
'<p class="active"></p>' +
'</a>' +
'<ol class="video_speeds"></ol>' +
'</div>'
);
state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el.find('.video_speeds'); state.videoSpeedControl.videoSpeedsEl = state.videoSpeedControl.el.find('.video_speeds');
state.videoControl.secondaryControlsEl.prepend(state.videoSpeedControl.el); state.videoControl.secondaryControlsEl.prepend(state.videoSpeedControl.el);
$.each(state.videoSpeedControl.speeds, function(index, speed) { $.each(state.videoSpeedControl.speeds, function(index, speed) {
var link; // REFACTOR: Move all HTML into one function call.
var link = $('<a>').attr({
link = $('<a>').attr({
'href': '#' 'href': '#'
}).html('' + speed + 'x'); }).html('' + speed + 'x');
// REFACTOR: Use jQuery .data()
state.videoSpeedControl.videoSpeedsEl.prepend($('<li>').attr('data-speed', speed).html(link)); state.videoSpeedControl.videoSpeedsEl.prepend($('<li>').attr('data-speed', speed).html(link));
}); });
...@@ -76,6 +68,7 @@ function () { ...@@ -76,6 +68,7 @@ function () {
$(this).toggleClass('open'); $(this).toggleClass('open');
}); });
} else { } else {
// REFACTOR: Chain.
state.videoSpeedControl.el.on('mouseenter', function() { state.videoSpeedControl.el.on('mouseenter', function() {
$(this).addClass('open'); $(this).addClass('open');
}); });
...@@ -98,6 +91,7 @@ function () { ...@@ -98,6 +91,7 @@ function () {
// *************************************************************** // ***************************************************************
function setSpeed(speed) { function setSpeed(speed) {
// REFACTOR: Use chaining.
this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active'); this.videoSpeedControl.videoSpeedsEl.find('li').removeClass('active');
this.videoSpeedControl.videoSpeedsEl.find("li[data-speed='" + speed + "']").addClass('active'); this.videoSpeedControl.videoSpeedsEl.find("li[data-speed='" + speed + "']").addClass('active');
this.videoSpeedControl.el.find('p.active').html('' + speed + 'x'); this.videoSpeedControl.el.find('p.active').html('' + speed + 'x');
...@@ -106,10 +100,12 @@ function () { ...@@ -106,10 +100,12 @@ function () {
function changeVideoSpeed(event) { function changeVideoSpeed(event) {
event.preventDefault(); event.preventDefault();
// REFACTOR: Cache parent el.
if (!$(event.target).parent().hasClass('active')) { if (!$(event.target).parent().hasClass('active')) {
this.videoSpeedControl.currentSpeed = $(event.target).parent().data('speed'); this.videoSpeedControl.currentSpeed = $(event.target).parent().data('speed');
this.videoSpeedControl.setSpeed( this.videoSpeedControl.setSpeed(
// To meet the API expected format.
parseFloat(this.videoSpeedControl.currentSpeed).toFixed(2).replace(/\.00$/, '.0') parseFloat(this.videoSpeedControl.currentSpeed).toFixed(2).replace(/\.00$/, '.0')
); );
...@@ -117,6 +113,7 @@ function () { ...@@ -117,6 +113,7 @@ function () {
} }
} }
// REFACTOR.
function reRender(params /*newSpeeds, currentSpeed*/) { function reRender(params /*newSpeeds, currentSpeed*/) {
var _this; var _this;
......
...@@ -34,14 +34,7 @@ function () { ...@@ -34,14 +34,7 @@ function () {
// make the created DOM elements available via the 'state' object. Much easier to work this // make the created DOM elements available via the 'state' object. Much easier to work this
// way - you don't have to do repeated jQuery element selects. // way - you don't have to do repeated jQuery element selects.
function renderElements(state) { function renderElements(state) {
state.videoVolumeControl.el = $( state.videoVolumeControl.el = state.el.find('div.volume');
'<div class="volume">' +
'<a href="#"></a>' +
'<div class="volume-slider-container">' +
'<div class="volume-slider"></div>' +
'</div>' +
'</div>'
);
state.videoVolumeControl.buttonEl = state.videoVolumeControl.el.find('a'); state.videoVolumeControl.buttonEl = state.videoVolumeControl.el.find('a');
state.videoVolumeControl.volumeSliderEl = state.videoVolumeControl.el.find('.volume-slider'); state.videoVolumeControl.volumeSliderEl = state.videoVolumeControl.el.find('.volume-slider');
...@@ -51,6 +44,7 @@ function () { ...@@ -51,6 +44,7 @@ function () {
// Figure out what the current volume is. Set it up so that muting/unmuting works correctly. // Figure out what the current volume is. Set it up so that muting/unmuting works correctly.
// If no information about volume level could be retrieved, then we will use the default // If no information about volume level could be retrieved, then we will use the default
// 100 level (full volume). // 100 level (full volume).
// REFACTOR: Remove unnecessary checks.
state.videoVolumeControl.currentVolume = parseInt($.cookie('video_player_volume_level'), 10); state.videoVolumeControl.currentVolume = parseInt($.cookie('video_player_volume_level'), 10);
state.videoVolumeControl.previousVolume = 100; state.videoVolumeControl.previousVolume = 100;
if ( if (
......
(function (requirejs, require, define) { (function (requirejs, require, define) {
// REFACTOR. Build JS doc. Add docs on how to build docs.
// Main module. // Main module.
require( require(
[ [
...@@ -49,7 +51,10 @@ function ( ...@@ -49,7 +51,10 @@ function (
VideoProgressSlider(state); VideoProgressSlider(state);
VideoVolumeControl(state); VideoVolumeControl(state);
VideoSpeedControl(state); VideoSpeedControl(state);
if (state.config.show_captions) {
VideoCaption(state); VideoCaption(state);
}
}; };
}); });
......
...@@ -35,7 +35,7 @@ from .discussionsettings import * ...@@ -35,7 +35,7 @@ from .discussionsettings import *
PLATFORM_NAME = "edX" PLATFORM_NAME = "edX"
COURSEWARE_ENABLED = True COURSEWARE_ENABLED = True
ENABLE_JASMINE = False ENABLE_JASMINE = True
PERFSTATS = False PERFSTATS = False
......
...@@ -34,8 +34,42 @@ ...@@ -34,8 +34,42 @@
<div id="${id}"></div> <div id="${id}"></div>
</section> </section>
<div class="video-player-post"></div> <div class="video-player-post"></div>
<section class="video-controls"></section> <section class="video-controls">
<div class="slider"></div>
<div>
<ul class="vcr">
<li><a class="video_control" href="#" title="Play"></a></li>
<li><div class="vidtime">0:00 / 0:00</div></li>
</ul>
<div class="secondary-controls">
<div class="speeds">
<a href="#">
<h3>Speed</h3>
<p class="active"></p>
</a>
<ol class="video_speeds"></ol>
</div>
<div class="volume">
<a href="#"></a>
<div class="volume-slider-container">
<div class="volume-slider"></div>
</div>
</div>
<a href="#" class="add-fullscreen" title="Fill browser">Fill Browser</a>
<a href="#" class="quality_control" title="HD">HD</a>
% if show_captions == 'true':
<a href="#" class="hide-subtitles" title="Turn off captions">Captions</a>
% endif
</div>
</div>
</section>
</article> </article>
% if show_captions == 'true':
<ol class="subtitles"></ol>
% endif
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment