diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js
index a87088d147..31a0736929 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js
+++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/initialize.js
@@ -3,8 +3,8 @@
// Initialize module.
define(
'videoalpha/display/initialize.js',
-['videoalpha/display/bind.js'],
-function (bind) {
+['videoalpha/display/bind.js', 'videoalpha/display/video_player.js'],
+function (bind, VideoPlayer) {
// Initialize() function - what this module "exports".
return function (state, element) {
@@ -99,6 +99,23 @@ function (bind) {
state.el.addClass('closed');
}
+ // By default we will be forcing HTML5 player mode. Only in the case when, after initializtion, we will
+ // get one available playback rate, we will change to Flash player mode. There is a need to store this
+ // setting in cookies because otherwise we will have to change from HTML5 to Flash on every page load
+ // 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).
+ (function (currentPlayerMode) {
+ if ((currentPlayerMode !== 'html5') && (currentPlayerMode !== 'flash')) {
+ $.cookie('current_player_mode', 'html5', {
+ expires: 3650,
+ path: '/'
+ });
+ state.currentPlayerMode = 'html5';
+ } else {
+ state.currentPlayerMode = currentPlayerMode;
+ }
+ }($.cookie('current_player_mode')));
+
// Launch embedding of actual video content, or set it up so that it will be done as soon as the
// appropriate video player (YouTube or stand alone HTML5) is loaded, and can handle embedding.
if (
@@ -139,7 +156,7 @@ function (bind) {
var speed;
video = video.split(/:/);
- speed = parseFloat(video[0]).toFixed(2).replace(/\.00$/, ".0");
+ speed = parseFloat(video[0]).toFixed(2).replace(/\.00$/, '.0');
state.videos[speed] = video[1];
});
@@ -179,22 +196,26 @@ function (bind) {
state.setSpeed($.cookie('video_speed'));
}
- function embed(state) { }
+ function embed(state) {
+ VideoPlayer(state);
+ }
// Public functions start here.
// These are available via the 'state' object. Their context ('this' keyword) is the 'state' object.
// The magic private function that makes them available and sets up their context is makeFunctionsPublic().
- function setSpeed(newSpeed) {
+ function setSpeed(newSpeed, updateCookie) {
if (this.speeds.indexOf(newSpeed) !== -1) {
this.speed = newSpeed;
+ } else {
+ this.speed = '1.0';
+ }
- $.cookie('video_speed', '' + newSpeed, {
+ if (updateCookie !== false) {
+ $.cookie('video_speed', this.speed, {
expires: 3650,
path: '/'
});
- } else {
- this.speed = '1.0';
}
}
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js
new file mode 100644
index 0000000000..074fd07682
--- /dev/null
+++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_control.js
@@ -0,0 +1,145 @@
+(function (requirejs, require, define) {
+
+// VideoPlayer module.
+define(
+'videoalpha/display/video_control.js',
+['videoalpha/display/bind.js'],
+function (bind) {
+
+ // VideoControl() function - what this module "exports".
+ return function (state) {
+ state.videoControl = {};
+
+ // Functions which will be accessible via 'state' object.
+ makeFunctionsPublic(state);
+
+ // TODO.
+ console.log('We are inside VideoControl() function.');
+
+ renderElements(state);
+ bindHandlers();
+ };
+
+ // Private functions start here.
+
+ function makeFunctionsPublic(state) {
+ state.videoControl.play = bind(play, state);
+ state.videoControl.pause = bind(pause, state);
+ state.videoControl.togglePlayback = bind(togglePlayback, state);
+ }
+
+ function renderElements(state) {
+ var el;
+
+ el = $(
+ '
' +
+ '' +
+ '
' +
+ ' ' +
+ '0:00 / 0:00
' +
+ '
' +
+ '
' +
+ '
'
+ );
+
+ state.videoControl.el = state.el.find('.video-controls');
+ state.videoControl.el.append(el);
+
+ state.videoControl.playPauseEl = state.videoControl.el.find('.video_control');
+
+ if (!onTouchBasedDevice()) {
+ state.videoControl.playPauseEl.addClass('play').html('Play');
+ }
+ }
+
+ function bindHandlers(state) {
+ state.videoControl.playPauseEl.click(state.videoControl.togglePlayback);
+ }
+
+ // Public functions start here.
+ // These are available via the 'state' object. Their context ('this' keyword) is the 'state' object.
+ // The magic private function that makes them available and sets up their context is makeFunctionsPublic().
+
+ function play() {
+ this.videoControl.playPauseEl.removeClass('play').addClass('pause').html('Pause');
+ this.videoControl.state = 'playing';
+ }
+
+ function pause() {
+ this.videoControl.playPauseEl.removeClass('pause').addClass('play').html('Play');
+ this.videoControl.state = 'paused';
+ }
+
+ function togglePlayback(event) {
+
+ event.preventDefault();
+
+ console.log('We are in togglePlayback() function. this =');
+ console.log(this);
+
+ /*
+ if (this.$('.video_control').hasClass('play')) {
+ $(this).trigger('play');
+ } else if (this.$('.video_control').hasClass('pause')) {
+ $(this).trigger('pause');
+ }
+ */
+ }
+
+});
+
+}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
+
+
+/*
+// Generated by CoffeeScript 1.4.0
+(function() {
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+ __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ this.VideoControlAlpha = (function(_super) {
+
+ __extends(VideoControlAlpha, _super);
+
+ function VideoControlAlpha() {
+ this.togglePlayback = __bind(this.togglePlayback, this);
+ return VideoControlAlpha.__super__.constructor.apply(this, arguments);
+ }
+
+ VideoControlAlpha.prototype.bind = function() {
+ return this.$('.video_control').click(this.togglePlayback);
+ };
+
+ VideoControlAlpha.prototype.render = function() {
+ this.el.append("\n\n
\n \n - \n
0:00 / 0:00
\n \n
\n
\n
");
+ if (!onTouchBasedDevice()) {
+ return this.$('.video_control').addClass('play').html('Play');
+ }
+ };
+
+ VideoControlAlpha.prototype.play = function() {
+ return this.$('.video_control').removeClass('play').addClass('pause').html('Pause');
+ };
+
+ VideoControlAlpha.prototype.pause = function() {
+ return this.$('.video_control').removeClass('pause').addClass('play').html('Play');
+ };
+
+ VideoControlAlpha.prototype.togglePlayback = function(event) {
+ event.preventDefault();
+ if (this.$('.video_control').hasClass('play')) {
+ return $(this).trigger('play');
+ } else if (this.$('.video_control').hasClass('pause')) {
+ return $(this).trigger('pause');
+ }
+ };
+
+ return VideoControlAlpha;
+
+ })(SubviewAlpha);
+
+}).call(this);
+*/
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js
index bc8b76867b..4af1f58407 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js
+++ b/common/lib/xmodule/xmodule/js/src/videoalpha/display/video_player.js
@@ -3,12 +3,233 @@
// VideoPlayer module.
define(
'videoalpha/display/video_player.js',
-['videoalpha/display/html5_video.js'],
-function (HTML5Video) {
+['videoalpha/display/html5_video.js', 'videoalpha/display/bind.js'],
+function (HTML5Video, bind) {
+
+ // VideoPlayer() function - what this module "exports".
return function (state) {
- console.log('HTML5Video object:');
- console.log(HTML5Video);
+ state.videoPlayer = {};
+
+ // Functions which will be accessible via 'state' object.
+ makeFunctionsPublic(state);
+
+ if (state.videoType === 'youtube') {
+ state.videoPlayer.PlayerState = YT.PlayerState;
+ state.videoPlayer.PlayerState.UNSTARTED = -1;
+ } else { // if (state.videoType === 'html5') {
+ state.videoPlayer.PlayerState = HTML5Video.PlayerState;
+ }
+ state.videoPlayer.currentTime = 0;
+
+ renderElements(state);
+ bindHandlers();
};
+
+ // Private functions start here.
+
+ function makeFunctionsPublic(state) {
+ state.videoPlayer.pause = bind(pause, state);
+ state.videoPlayer.play = bind(play, state);
+ state.videoPlayer.toggleFullScreen = bind(toggleFullScreen, state);
+ state.videoPlayer.update = bind(update, state);
+ state.videoPlayer.onVolumeChange = bind(onVolumeChange, state);
+ state.videoPlayer.onSpeedChange = bind(onSpeedChange, state);
+ state.videoPlayer.onSeek = bind(onSeek, state);
+ state.videoPlayer.onEnded = bind(onEnded, state);
+ state.videoPlayer.onPause = bind(onPause, state);
+ state.videoPlayer.onPlay = bind(onPlay, state);
+ state.videoPlayer.onUnstarted = bind(onUnstarted, state);
+ state.videoPlayer.handlePlaybackQualityChange = bind(handlePlaybackQualityChange, state);
+ state.videoPlayer.onPlaybackQualityChange = bind(onPlaybackQualityChange, state);
+ state.videoPlayer.onStateChange = bind(onStateChange, state);
+ state.videoPlayer.onReady = bind(onReady, state);
+ state.videoPlayer.bindExitFullScreen = bind(bindExitFullScreen, state);
+ }
+
+ function renderElements(state) {
+ var youTubeId;
+
+ state.videoPlayer.playerVars = {
+ 'controls': 0,
+ 'wmode': 'transparent',
+ 'rel': 0,
+ 'showinfo': 0,
+ 'enablejsapi': 1,
+ 'modestbranding': 1
+ };
+
+ if (state.currentPlayerMode !== 'flash') {
+ state.videoPlayer.playerVars.html5 = 1;
+ }
+
+ if (state.config.start) {
+ state.videoPlayer.playerVars.start = state.config.start;
+ state.videoPlayer.playerVars.wmode = 'window';
+ }
+ if (state.config.end) {
+ state.videoPlayer.playerVars.end = state.config.end;
+ }
+
+ if (state.videoType === 'html5') {
+ state.videoPlayer.player = new HTML5Video.Player(state.el, {
+ 'playerVars': state.videoPlayer.playerVars,
+ 'videoSources': state.html5Sources,
+ 'events': {
+ 'onReady': state.videoPlayer.onReady,
+ 'onStateChange': state.videoPlayer.onStateChange
+ }
+ });
+ } else if (state.videoType === 'youtube') {
+ if (state.currentPlayerMode === 'flash') {
+ youTubeId = state.youtubeId();
+ } else {
+ youTubeId = state.youtubeId('1.0');
+ }
+ state.videoPlayer.player = new YT.Player(state.id, {
+ 'playerVars': state.videoPlayer.playerVars,
+ 'videoId': youTubeId,
+ 'events': {
+ 'onReady': state.videoPlayer.onReady,
+ 'onStateChange': state.videoPlayer.onStateChange,
+ 'onPlaybackQualityChange': state.videoPlayer.onPlaybackQualityChange
+ }
+ });
+ }
+ }
+
+ function bindHandlers() {
+
+ }
+
+ function reinitAsFlash(state) {
+ state.videoPlayer.player.destroy();
+
+ $.cookie('current_player_mode', 'flash', {
+ expires: 3650,
+ path: '/'
+ });
+ state.currentPlayerMode = 'flash';
+
+ delete state.videoPlayer.playerVars.html5;
+
+ state.videoPlayer.player = new YT.Player(state.id, {
+ 'playerVars': state.videoPlayer.playerVars,
+ 'videoId': state.youtubeId(),
+ 'events': {
+ 'onReady': state.videoPlayer.onReady,
+ 'onStateChange': state.videoPlayer.onStateChange,
+ 'onPlaybackQualityChange': state.videoPlayer.onPlaybackQualityChange
+ }
+ });
+ }
+
+ // Public functions start here.
+ // These are available via the 'state' object. Their context ('this' keyword) is the 'state' object.
+ // The magic private function that makes them available and sets up their context is makeFunctionsPublic().
+
+ function pause() { }
+
+ function play() {
+ if (this.videoPlayer.player.playVideo) {
+ this.videoPlayer.player.playVideo();
+ }
+
+ console.log('state is:');
+ console.log(this);
+ }
+
+ function toggleFullScreen() { }
+
+ function update() { }
+
+ function onVolumeChange() { }
+
+ function onSpeedChange() { }
+
+ function onSeek() { }
+
+ function onEnded() {
+ console.log('this.videoPlayer.PlayerState.ENDED');
+ }
+
+ function onPause() {
+ console.log('this.videoPlayer.PlayerState.PAUSED');
+ }
+
+ function onPlay() {
+ console.log('this.videoPlayer.PlayerState.PLAYING');
+ }
+
+ function onUnstarted() {
+ console.log('this.videoPlayer.PlayerState.UNSTARTED');
+ }
+
+ function handlePlaybackQualityChange() { }
+
+ function onPlaybackQualityChange() { }
+
+ function onReady() {
+ var availablePlaybackRates, baseSpeedSubs, _this;
+
+ console.log('We are in ready function.');
+
+ availablePlaybackRates = this.videoPlayer.player.getAvailablePlaybackRates();
+ if ((this.currentPlayerMode === 'html5') && (this.videoType === 'youtube')) {
+ if (availablePlaybackRates.length === 1) {
+ console.log('We are playing YouTube video in HTML5 mode but have only one speed. Will reload in Flash mode.');
+ reinitAsFlash(this);
+
+ return;
+ } else if (availablePlaybackRates.length > 1) {
+ // We need to synchronize available frame rates with the ones that the user specified.
+ console.log('We are a YouTube video in HTML5 player mode.');
+
+ baseSpeedSubs = this.videos['1.0'];
+ _this = this;
+ $.each(this.videos, function(index, value) {
+ delete _this.videos[index];
+ });
+ this.speeds = [];
+ $.each(availablePlaybackRates, function(index, value) {
+ _this.videos[value.toFixed(2).replace(/\.00$/, '.0')] = baseSpeedSubs;
+ _this.speeds.push(value.toFixed(2).replace(/\.00$/, '.0'));
+ });
+
+ this.setSpeed($.cookie('video_speed'));
+ }
+ }
+
+ if (this.currentPlayerMode === 'html5') {
+ this.videoPlayer.player.setPlaybackRate(this.speed);
+ }
+
+ if (!onTouchBasedDevice()) {
+ this.videoPlayer.play();
+ }
+ }
+
+ function onStateChange() {
+ console.log('function onStateChange()');
+ }
+
+ function onStateChange(event) {
+ switch (event.data) {
+ case this.videoPlayer.PlayerState.UNSTARTED:
+ this.videoPlayer.onUnstarted();
+ break;
+ case this.videoPlayer.PlayerState.PLAYING:
+ this.videoPlayer.onPlay();
+ break;
+ case this.videoPlayer.PlayerState.PAUSED:
+ this.videoPlayer.onPause();
+ break;
+ case this.videoPlayer.PlayerState.ENDED:
+ this.videoPlayer.onEnded();
+ break;
+ }
+ }
+
+ function bindExitFullScreen() { }
});
}(RequireJS.requirejs, RequireJS.require, RequireJS.define));
@@ -17,66 +238,6 @@ function (HTML5Video) {
/*
-// Generated by CoffeeScript 1.4.0
-(function() {
- var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
- __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
- this.VideoPlayerAlpha = (function(_super) {
-
- __extends(VideoPlayerAlpha, _super);
-
- function VideoPlayerAlpha() {
- this.pause = __bind(this.pause, this);
-
- this.play = __bind(this.play, this);
-
- this.toggleFullScreen = __bind(this.toggleFullScreen, this);
-
- this.update = __bind(this.update, this);
-
- this.onVolumeChange = __bind(this.onVolumeChange, this);
-
- this.onSpeedChange = __bind(this.onSpeedChange, this);
-
- this.onSeek = __bind(this.onSeek, this);
-
- this.onEnded = __bind(this.onEnded, this);
-
- this.onPause = __bind(this.onPause, this);
-
- this.onPlay = __bind(this.onPlay, this);
-
- this.onUnstarted = __bind(this.onUnstarted, this);
-
- this.handlePlaybackQualityChange = __bind(this.handlePlaybackQualityChange, this);
-
- this.onPlaybackQualityChange = __bind(this.onPlaybackQualityChange, this);
-
- this.onStateChange = __bind(this.onStateChange, this);
-
- this.onReady = __bind(this.onReady, this);
-
- this.bindExitFullScreen = __bind(this.bindExitFullScreen, this);
- return VideoPlayerAlpha.__super__.constructor.apply(this, arguments);
- }
-
- VideoPlayerAlpha.prototype.initialize = function() {
- if (window.OldVideoPlayerAlpha && window.OldVideoPlayerAlpha.onPause) {
- window.OldVideoPlayerAlpha.onPause();
- }
- window.OldVideoPlayerAlpha = this;
- if (this.video.videoType === 'youtube') {
- this.PlayerState = YT.PlayerState;
- this.PlayerState.UNSTARTED = -1;
- } else if (this.video.videoType === 'html5') {
- this.PlayerState = HTML5Video.PlayerState;
- }
- this.currentTime = 0;
- return this.el = $("#video_" + this.video.id);
- };
-
VideoPlayerAlpha.prototype.bind = function() {
$(this.control).bind('play', this.play).bind('pause', this.pause);
if (this.video.videoType === 'youtube') {
@@ -103,83 +264,6 @@ function (HTML5Video) {
}
};
- VideoPlayerAlpha.prototype.render = function() {
- var prev_player_type, youTubeId;
- this.control = new VideoControlAlpha({
- el: this.$('.video-controls')
- });
- if (this.video.videoType === 'youtube') {
- this.qualityControl = new VideoQualityControlAlpha({
- el: this.$('.secondary-controls')
- });
- }
- if (this.video.show_captions === true) {
- this.caption = new VideoCaptionAlpha({
- el: this.el,
- youtubeId: this.video.youtubeId('1.0'),
- currentSpeed: this.currentSpeed(),
- captionAssetPath: this.video.caption_asset_path
- });
- }
- if (!onTouchBasedDevice()) {
- this.volumeControl = new VideoVolumeControlAlpha({
- el: this.$('.secondary-controls')
- });
- }
- this.speedControl = new VideoSpeedControlAlpha({
- el: this.$('.secondary-controls'),
- speeds: this.video.speeds,
- currentSpeed: this.currentSpeed()
- });
- this.progressSlider = new VideoProgressSliderAlpha({
- el: this.$('.slider')
- });
- this.playerVars = {
- controls: 0,
- wmode: 'transparent',
- rel: 0,
- showinfo: 0,
- enablejsapi: 1,
- modestbranding: 1
- };
- if (this.video.start) {
- this.playerVars.start = this.video.start;
- this.playerVars.wmode = 'window';
- }
- if (this.video.end) {
- this.playerVars.end = this.video.end;
- }
- if (this.video.videoType === 'html5') {
- this.player = new HTML5Video.Player(this.video.el, {
- playerVars: this.playerVars,
- videoSources: this.video.html5Sources,
- events: {
- onReady: this.onReady,
- onStateChange: this.onStateChange
- }
- });
- } else if (this.video.videoType === 'youtube') {
- prev_player_type = $.cookie('prev_player_type');
- if (prev_player_type === 'html5') {
- youTubeId = this.video.videos['1.0'];
- } else {
- youTubeId = this.video.youtubeId();
- }
- this.player = new YT.Player(this.video.id, {
- playerVars: this.playerVars,
- videoId: youTubeId,
- events: {
- onReady: this.onReady,
- onStateChange: this.onStateChange,
- onPlaybackQualityChange: this.onPlaybackQualityChange
- }
- });
- }
- if (this.video.show_captions === true) {
- return this.caption.hideCaptions(this['video'].hide_captions);
- }
- };
-
VideoPlayerAlpha.prototype.addToolTip = function() {
return this.$('.add-fullscreen, .hide-subtitles').qtip({
position: {
@@ -189,67 +273,7 @@ function (HTML5Video) {
});
};
- VideoPlayerAlpha.prototype.onReady = function(event) {
- if (this.video.videoType === 'html5') {
- this.player.setPlaybackRate(this.video.speed);
- }
- if (!onTouchBasedDevice()) {
- return $('.video-load-complete:first').data('video').player.play();
- }
- };
- VideoPlayerAlpha.prototype.onStateChange = function(event) {
- var availableSpeeds, baseSpeedSubs, prev_player_type, _this;
- _this = this;
- switch (event.data) {
- case this.PlayerState.UNSTARTED:
- if (this.video.videoType === "youtube") {
- availableSpeeds = this.player.getAvailablePlaybackRates();
- prev_player_type = $.cookie('prev_player_type');
- if (availableSpeeds.length > 1) {
- if (prev_player_type === 'youtube') {
- $.cookie('prev_player_type', 'html5', {
- expires: 3650,
- path: '/'
- });
- this.onSpeedChange(null, '1.0');
- } else if (prev_player_type !== 'html5') {
- $.cookie('prev_player_type', 'html5', {
- expires: 3650,
- path: '/'
- });
- }
- baseSpeedSubs = this.video.videos["1.0"];
- $.each(this.video.videos, function(index, value) {
- return delete _this.video.videos[index];
- });
- this.video.speeds = [];
- $.each(availableSpeeds, function(index, value) {
- _this.video.videos[value.toFixed(2).replace(/\.00$/, ".0")] = baseSpeedSubs;
- return _this.video.speeds.push(value.toFixed(2).replace(/\.00$/, ".0"));
- });
- this.speedControl.reRender(this.video.speeds, this.video.speed);
- this.video.videoType = 'html5';
- this.video.setSpeed($.cookie('video_speed'));
- this.player.setPlaybackRate(this.video.speed);
- } else {
- if (prev_player_type !== 'youtube') {
- $.cookie('prev_player_type', 'youtube', {
- expires: 3650,
- path: '/'
- });
- }
- }
- }
- return this.onUnstarted();
- case this.PlayerState.PLAYING:
- return this.onPlay();
- case this.PlayerState.PAUSED:
- return this.onPause();
- case this.PlayerState.ENDED:
- return this.onEnded();
- }
- };
VideoPlayerAlpha.prototype.onPlaybackQualityChange = function(event, value) {
var quality;
@@ -308,12 +332,12 @@ function (HTML5Video) {
return this.updatePlayTime(time);
};
- VideoPlayerAlpha.prototype.onSpeedChange = function(event, newSpeed) {
+ VideoPlayerAlpha.prototype.onSpeedChange = function(event, newSpeed, updateCookie) {
if (this.video.videoType === 'youtube') {
this.currentTime = Time.convert(this.currentTime, parseFloat(this.currentSpeed()), newSpeed);
}
newSpeed = parseFloat(newSpeed).toFixed(2).replace(/\.00$/, '.0');
- this.video.setSpeed(newSpeed);
+ this.video.setSpeed(newSpeed, updateCookie);
if (this.video.videoType === 'youtube') {
if (this.video.show_captions === true) {
this.caption.currentSpeed = newSpeed;
@@ -384,12 +408,12 @@ function (HTML5Video) {
};
VideoPlayerAlpha.prototype.duration = function() {
- if (this.video.videoType === "youtube") {
- return this.video.getDuration();
- } else if (this.video.videoType === "html5") {
- return this.player.getDuration();
+ var duration;
+ duration = this.player.getDuration();
+ if (isFinite(duration) === false) {
+ duration = this.video.getDuration();
}
- return 0;
+ return duration;
};
VideoPlayerAlpha.prototype.currentSpeed = function() {
diff --git a/common/lib/xmodule/xmodule/js/src/videoalpha/main.js b/common/lib/xmodule/xmodule/js/src/videoalpha/main.js
index 582c151afb..3602967ff3 100644
--- a/common/lib/xmodule/xmodule/js/src/videoalpha/main.js
+++ b/common/lib/xmodule/xmodule/js/src/videoalpha/main.js
@@ -1,18 +1,38 @@
(function (requirejs, require, define) {
-// Main module
+// Main module.
require(
-['videoalpha/display/initialize.js', 'videoalpha/display/video_player.js'],
-function (Initialize, VideoPlayer) {
+[
+ 'videoalpha/display/initialize.js',
+ 'videoalpha/display/video_control.js',
+],
+function (Initialize, VideoControl) {
+ var previousState;
+
+ // Because this constructor can be called multiple times on a single page (when
+ // the user switches verticals, the page doesn't reload, but the content changes), we must
+ // will check each time if there is a previous copy of 'state' object. If there is, we
+ // will make sure that copy exists cleanly. We have to do this because when verticals switch,
+ // the code does not handle any Xmodule JS code that is running - it simply removes DOM
+ // elements from the page. Any functions that were running during this, and that will run
+ // afterwards (expecting the DOM elements to be present) must be stopped by hand.
+ previousState = null;
+
window.VideoAlpha = function (element) {
var state;
+ // Check for existance of previous state, uninitialize it if necessary, and create a new state.
+ // Store new state for future invocation of this module consturctor function.
+ if (previousState !== null) {
+ previousState.videoPlayer.onPause();
+ }
state = {};
+ previousState = state;
- new Initialize(state, element);
- new VideoPlayer(state);
+ Initialize(state, element);
+ VideoControl(state);
- console.log('Finished constructing "state" object. state = ');
+ console.log('state is:');
console.log(state);
};
});
diff --git a/common/lib/xmodule/xmodule/videoalpha_module.py b/common/lib/xmodule/xmodule/videoalpha_module.py
index 20bab318a9..20b95ec382 100644
--- a/common/lib/xmodule/xmodule/videoalpha_module.py
+++ b/common/lib/xmodule/xmodule/videoalpha_module.py
@@ -73,6 +73,7 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
resource_string(__name__, 'js/src/videoalpha/display/initialize.js'),
resource_string(__name__, 'js/src/videoalpha/display/html5_video.js'),
resource_string(__name__, 'js/src/videoalpha/display/video_player.js'),
+ resource_string(__name__, 'js/src/videoalpha/display/video_control.js'),
resource_string(__name__, 'js/src/videoalpha/main.js')
]
}