Commit 062c3b45 by Valera Rozuvan

Initial commit.

Adding focus on slider handle when video ends.
Removing unnecessary debug console.log() calls.
Change back to original code.
Adding comments.
Also undid tabindex=-1 for the slider knob. It is unnecessary, and prevents
the user from tabbing onto the slider.
Adding minor details.
startTime and endTime proper reset.

BLD-488
parent f0bbd34a
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// VideoPlayer module. // VideoPlayer module.
define( define(
'video/03_video_player.js', 'video/03_video_player.js',
['video/02_html5_video.js', 'video/00_resizer.js' ], ['video/02_html5_video.js', 'video/00_resizer.js'],
function (HTML5Video, Resizer) { function (HTML5Video, Resizer) {
var dfd = $.Deferred(); var dfd = $.Deferred();
...@@ -83,8 +83,6 @@ function (HTML5Video, Resizer) { ...@@ -83,8 +83,6 @@ function (HTML5Video, Resizer) {
state.videoPlayer.initialSeekToStartTime = true; state.videoPlayer.initialSeekToStartTime = true;
state.videoPlayer.oneTimePauseAtEndTime = true;
// The initial value of the variable `seekToStartTimeOldSpeed` // The initial value of the variable `seekToStartTimeOldSpeed`
// should always differ from the value returned by the duration // should always differ from the value returned by the duration
// function. // function.
...@@ -215,8 +213,7 @@ function (HTML5Video, Resizer) { ...@@ -215,8 +213,7 @@ function (HTML5Video, Resizer) {
// This function gets the video's current play position in time // This function gets the video's current play position in time
// (currentTime) and its duration. // (currentTime) and its duration.
// It is called at a regular interval when the video is playing (see // It is called at a regular interval when the video is playing.
// below).
function update() { function update() {
this.videoPlayer.currentTime = this.videoPlayer.player this.videoPlayer.currentTime = this.videoPlayer.player
.getCurrentTime(); .getCurrentTime();
...@@ -224,22 +221,28 @@ function (HTML5Video, Resizer) { ...@@ -224,22 +221,28 @@ function (HTML5Video, Resizer) {
if (isFinite(this.videoPlayer.currentTime)) { if (isFinite(this.videoPlayer.currentTime)) {
this.videoPlayer.updatePlayTime(this.videoPlayer.currentTime); this.videoPlayer.updatePlayTime(this.videoPlayer.currentTime);
// We need to pause the video is current time is smaller (or equal) // We need to pause the video if current time is smaller (or equal)
// than end time. Also, we must make sure that the end time is the // than end time. Also, we must make sure that this is only done
// one that was set in the configuration parameter. If it differs, // once.
// this means that it was either reset to the end, or the duration
// changed it's value.
// //
// In the case of YouTube Flash mode, we must remember that the // If `endTime` is not `null`, then we are safe to pause the
// start and end times are rescaled based on the current speed of // video. `endTime` will be set to `null`, and this if statement
// the video. // will not be executed on next runs.
if ( if (
this.videoPlayer.endTime <= this.videoPlayer.currentTime && this.videoPlayer.endTime != null &&
this.videoPlayer.oneTimePauseAtEndTime this.videoPlayer.endTime <= this.videoPlayer.currentTime
) { ) {
this.videoPlayer.oneTimePauseAtEndTime = false;
this.videoPlayer.pause(); this.videoPlayer.pause();
this.videoPlayer.endTime = this.videoPlayer.duration();
// After the first time the video reached the `endTime`,
// `startTime` and `endTime` are disabled. The video will play
// from start to the end on subsequent runs.
this.videoPlayer.startTime = 0;
this.videoPlayer.endTime = null;
this.trigger('videoProgressSlider.notifyThroughHandleEnd', {
end: true
});
} }
} }
} }
...@@ -321,8 +324,10 @@ function (HTML5Video, Resizer) { ...@@ -321,8 +324,10 @@ function (HTML5Video, Resizer) {
} }
); );
// After the user seeks, startTime and endTime are disabled. The video
// will play from start to the end on subsequent runs.
this.videoPlayer.startTime = 0; this.videoPlayer.startTime = 0;
this.videoPlayer.endTime = duration; this.videoPlayer.endTime = null;
this.videoPlayer.player.seekTo(newTime, true); this.videoPlayer.player.seekTo(newTime, true);
...@@ -344,11 +349,21 @@ function (HTML5Video, Resizer) { ...@@ -344,11 +349,21 @@ function (HTML5Video, Resizer) {
var time = this.videoPlayer.duration(); var time = this.videoPlayer.duration();
this.trigger('videoControl.pause', null); this.trigger('videoControl.pause', null);
this.trigger('videoProgressSlider.notifyThroughHandleEnd', {
end: true
});
if (this.config.show_captions) { if (this.config.show_captions) {
this.trigger('videoCaption.pause', null); this.trigger('videoCaption.pause', null);
} }
// When only `startTime` is set, the video will play to the end
// starting at `startTime`. After the first time the video reaches the
// end, `startTime` and `endTime` are disabled. The video will play
// from start to the end on subsequent runs.
this.videoPlayer.startTime = 0;
this.videoPlayer.endTime = null;
// Sometimes `onEnded` events fires when `currentTime` not equal // Sometimes `onEnded` events fires when `currentTime` not equal
// `duration`. In this case, slider doesn't reach the end point of // `duration`. In this case, slider doesn't reach the end point of
// timeline. // timeline.
...@@ -391,6 +406,10 @@ function (HTML5Video, Resizer) { ...@@ -391,6 +406,10 @@ function (HTML5Video, Resizer) {
this.trigger('videoControl.play', null); this.trigger('videoControl.play', null);
this.trigger('videoProgressSlider.notifyThroughHandleEnd', {
end: false
});
if (this.config.show_captions) { if (this.config.show_captions) {
this.trigger('videoCaption.play', null); this.trigger('videoCaption.play', null);
} }
...@@ -531,7 +550,7 @@ function (HTML5Video, Resizer) { ...@@ -531,7 +550,7 @@ function (HTML5Video, Resizer) {
function updatePlayTime(time) { function updatePlayTime(time) {
var duration = this.videoPlayer.duration(), var duration = this.videoPlayer.duration(),
durationChange; durationChange, tempStartTime, tempEndTime;
if ( if (
duration > 0 && duration > 0 &&
...@@ -545,13 +564,23 @@ function (HTML5Video, Resizer) { ...@@ -545,13 +564,23 @@ function (HTML5Video, Resizer) {
this.videoPlayer.initialSeekToStartTime === false this.videoPlayer.initialSeekToStartTime === false
) { ) {
durationChange = true; durationChange = true;
} else { } else { // this.videoPlayer.initialSeekToStartTime === true
this.videoPlayer.initialSeekToStartTime = false;
durationChange = false; durationChange = false;
} }
this.videoPlayer.initialSeekToStartTime = false;
this.videoPlayer.seekToStartTimeOldSpeed = this.speed; this.videoPlayer.seekToStartTimeOldSpeed = this.speed;
// Current startTime and endTime could have already been reset.
// We will remember their current values, and reset them at the
// end. We need to perform the below calculations on start and end
// times so that the range on the slider gets correctly updated in
// the case of speed change in Flash player mode (for YouTube
// videos).
tempStartTime = this.videoPlayer.startTime;
tempEndTime = this.videoPlayer.endTime;
// We retrieve the original times. They could have been changed due // We retrieve the original times. They could have been changed due
// to the fact of speed change (duration change). This happens when // to the fact of speed change (duration change). This happens when
// in YouTube Flash mode. There each speed is a different video, // in YouTube Flash mode. There each speed is a different video,
...@@ -566,12 +595,22 @@ function (HTML5Video, Resizer) { ...@@ -566,12 +595,22 @@ function (HTML5Video, Resizer) {
this.videoPlayer.startTime /= Number(this.speed); this.videoPlayer.startTime /= Number(this.speed);
} }
} }
// An `endTime` of `null` means that either the user didn't set
// and `endTime`, or it was set to a value greater than the
// duration of the video.
//
// If `endTime` is `null`, the video will play to the end. We do
// not set the `endTime` to the duration of the video because
// sometimes in YouTube mode the duration changes slightly during
// the course of playback. This would cause the video to pause just
// before the actual end of the video.
if ( if (
this.videoPlayer.endTime === null || this.videoPlayer.endTime !== null &&
this.videoPlayer.endTime > duration this.videoPlayer.endTime > duration
) { ) {
this.videoPlayer.endTime = duration; this.videoPlayer.endTime = null;
} else { } else if (this.videoPlayer.endTime !== null) {
if (this.currentPlayerMode === 'flash') { if (this.currentPlayerMode === 'flash') {
this.videoPlayer.endTime /= Number(this.speed); this.videoPlayer.endTime /= Number(this.speed);
} }
...@@ -581,16 +620,22 @@ function (HTML5Video, Resizer) { ...@@ -581,16 +620,22 @@ function (HTML5Video, Resizer) {
// from current time), then we need to seek the video to the start // from current time), then we need to seek the video to the start
// time. // time.
// //
// We seek only if start time differs from zero. // We seek only if start time differs from zero, and we haven't
if (durationChange === false && this.videoPlayer.startTime > 0) { // performed already such a seek.
if (
durationChange === false &&
this.videoPlayer.startTime > 0 &&
!(tempStartTime === 0 && tempEndTime === null)
) {
this.videoPlayer.player.seekTo(this.videoPlayer.startTime); this.videoPlayer.player.seekTo(this.videoPlayer.startTime);
} }
// Rebuild the slider start-end range (if it doesn't take up the // Rebuild the slider start-end range (if it doesn't take up the
// whole slider). // whole slider). Remember that endTime === null means the end time
// is set to the end of video by default.
if (!( if (!(
this.videoPlayer.startTime === 0 && this.videoPlayer.startTime === 0 &&
this.videoPlayer.endTime === duration this.videoPlayer.endTime === null
)) { )) {
this.trigger( this.trigger(
'videoProgressSlider.updateStartEndTimeRegion', 'videoProgressSlider.updateStartEndTimeRegion',
...@@ -599,6 +644,14 @@ function (HTML5Video, Resizer) { ...@@ -599,6 +644,14 @@ function (HTML5Video, Resizer) {
} }
); );
} }
// Reset back the actual startTime and endTime if they have been
// already reset (a seek event happened, the video already ended
// once, or endTime has already been reached once).
if (tempStartTime === 0 && tempEndTime === null) {
this.videoPlayer.startTime = 0;
this.videoPlayer.endTime = null;
}
} }
this.trigger( this.trigger(
......
...@@ -41,7 +41,8 @@ function () { ...@@ -41,7 +41,8 @@ function () {
onSlide: onSlide, onSlide: onSlide,
onStop: onStop, onStop: onStop,
updatePlayTime: updatePlayTime, updatePlayTime: updatePlayTime,
updateStartEndTimeRegion: updateStartEndTimeRegion updateStartEndTimeRegion: updateStartEndTimeRegion,
notifyThroughHandleEnd: notifyThroughHandleEnd
}; };
state.bindTo(methodsDict, state.videoProgressSlider, state); state.bindTo(methodsDict, state.videoProgressSlider, state);
...@@ -111,11 +112,6 @@ function () { ...@@ -111,11 +112,6 @@ function () {
duration = params.duration; duration = params.duration;
} }
// If the range spans the entire length of video, we don't do anything.
if (!this.videoPlayer.startTime && !this.videoPlayer.endTime) {
return;
}
start = this.videoPlayer.startTime; start = this.videoPlayer.startTime;
// If end is set to null, then we set it to the end of the video. We // If end is set to null, then we set it to the end of the video. We
...@@ -199,8 +195,6 @@ function () { ...@@ -199,8 +195,6 @@ function () {
}, 200); }, 200);
} }
// Changed for tests -- JM: Check if it is the cause of Chrome Bug Valera
// noticed
function updatePlayTime(params) { function updatePlayTime(params) {
var time = Math.floor(params.time), var time = Math.floor(params.time),
duration = Math.floor(params.duration); duration = Math.floor(params.duration);
...@@ -215,6 +209,32 @@ function () { ...@@ -215,6 +209,32 @@ function () {
} }
} }
// When the video stops playing (either because the end was reached, or
// because endTime was reached), the screen reader must be notified that
// the video is no longer playing. We do this by a little trick. Setting
// the title attribute of the slider know to "video ended", and focusing
// on it. The screen reader will read the attr text.
//
// The user can then tab his way forward, landing on the next control
// element, the Play button.
//
// @param params - object with property `end`. If set to true, the
// function must set the title attribute to
// `video ended`;
// if set to false, the function must reset the attr to
// it's original state.
//
// This function will be triggered from VideoPlayer methods onEnded(),
// onPlay(), and update() (update method handles endTime).
function notifyThroughHandleEnd(params) {
if (params.end) {
this.videoProgressSlider.handle.attr('title', 'video ended');
this.videoProgressSlider.handle.focus();
} else {
this.videoProgressSlider.handle.attr('title', 'video position');
}
}
// Returns a string describing the current time of video in hh:mm:ss // Returns a string describing the current time of video in hh:mm:ss
// format. // format.
function getTimeDescription(time) { function getTimeDescription(time) {
......
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