Commit 009b8475 by Valera Rozuvan Committed by Vasyl Nakvasiuk

Tracing bug in Firefox whereby the HTML5 native video freezes. Turns out that…

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.
parent e8d07d53
......@@ -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';
}
}
......
(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);
*/
(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')
]
}
......
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