Tracing bug in Firefox whereby the HTML5 native video freezes. Turns out that setting currentTime property tiggers a canplay event. And this becomes cyclic because the callback for canplay event updates the currentTime property.
Video alpha 2. Work in progress.
This commit is contained in:
committed by
Vasyl Nakvasiuk
parent
e8d07d5377
commit
009b8475dc
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = $(
|
||||
'<div class="slider"></div>' +
|
||||
'<div>' +
|
||||
'<ul class="vcr">' +
|
||||
'<li><a class="video_control" href="#"></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.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("<div class=\"slider\"></div>\n<div>\n <ul class=\"vcr\">\n <li><a class=\"video_control\" href=\"#\"></a></li>\n <li>\n <div class=\"vidtime\">0:00 / 0:00</div>\n </li>\n </ul>\n <div class=\"secondary-controls\">\n <a href=\"#\" class=\"add-fullscreen\" title=\"Fill browser\">Fill Browser</a>\n </div>\n</div>");
|
||||
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);
|
||||
*/
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -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')
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user