1
0
mirror of https://github.com/videojs/video.js.git synced 2024-12-27 02:43:45 +02:00

Fixed an issue with the firstplay event not firing when autoplaying. closes #1271

This commit is contained in:
Steve Heffernan 2014-06-10 16:55:08 -07:00
parent 5edc3a5cbc
commit 71c0a72717
5 changed files with 81 additions and 38 deletions

View File

@ -2,7 +2,7 @@ CHANGELOG
=========
## HEAD (Unreleased)
_(none)_
* Fixed an issue with the firstplay event not firing when autoplaying ([view](https://github.com/videojs/video.js/pull/1271))
--------------------

View File

@ -32,10 +32,7 @@ vjs.Html5 = vjs.MediaTechController.extend({
// If the element source is already set, we may have missed the loadstart event, and want to trigger it.
// We don't want to set the source again and interrupt playback.
if (source && this.el_.currentSrc === source.src && this.el_.networkState > 0) {
// wait for the player to be ready so the player listeners are attached
player.ready(function(){
player.trigger('loadstart');
});
player.trigger('loadstart');
// Otherwise set the source if one was provided.
} else if (source) {
this.el_.src = source.src;

View File

@ -58,20 +58,6 @@ vjs.Player = vjs.Component.extend({
// see enableTouchActivity in Component
options.reportTouchActivity = false;
// Make sure the event listeners are the first things to happen when
// the player is ready. See #1208
// If not, the tech might fire events before the listeners are attached.
this.ready(function(){
this.on('loadstart', this.onLoadStart);
this.on('ended', this.onEnded);
this.on('play', this.onPlay);
this.on('firstplay', this.onFirstPlay);
this.on('pause', this.onPause);
this.on('progress', this.onProgress);
this.on('durationchange', this.onDurationChange);
this.on('fullscreenchange', this.onFullscreenChange);
});
// Run base component initializing with new options.
// Builds the element through createEl()
// Inits and embeds any child components in opts
@ -230,6 +216,22 @@ vjs.Player.prototype.createEl = function(){
}
vjs.insertFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
// The event listeners need to be added before the children are added
// in the component init because the tech (loaded with mediaLoader) may
// fire events, like loadstart, that these events need to capture.
// Long term it might be better to expose a way to do this in component.init
// like component.initEventListeners() that runs between el creation and
// adding children
this.el_ = el;
this.on('loadstart', this.onLoadStart);
this.on('ended', this.onEnded);
this.on('play', this.onPlay);
this.on('firstplay', this.onFirstPlay);
this.on('pause', this.onPause);
this.on('progress', this.onProgress);
this.on('durationchange', this.onDurationChange);
this.on('fullscreenchange', this.onFullscreenChange);
return el;
};
@ -408,30 +410,44 @@ vjs.Player.prototype.stopTrackingCurrentTime = function(){
* @event loadstart
*/
vjs.Player.prototype.onLoadStart = function() {
// remove any first play listeners that weren't triggered from a previous video.
this.off('play', initFirstPlay);
this.one('play', initFirstPlay);
// TODO: Update to use `emptied` event instead. See #1277.
if (this.error()) {
this.error(null);
// reset the error state
this.error(null);
// If it's already playing we want to trigger a firstplay event now.
// The firstplay event relies on both the play and loadstart events
// which can happen in any order for a new source
if (!this.paused()) {
this.trigger('firstplay');
} else {
// reset the hasStarted state
this.hasStarted(false);
this.one('play', function(){
this.hasStarted(true);
});
}
vjs.removeClass(this.el_, 'vjs-has-started');
};
// Need to create this outside the scope of onLoadStart so it
// can be added and removed (to avoid piling first play listeners).
function initFirstPlay(e) {
var fpEvent = { type: 'firstplay', target: this.el_ };
// Using vjs.trigger so we can check if default was prevented
var keepGoing = vjs.trigger(this.el_, fpEvent);
vjs.Player.prototype.hasStarted_ = false;
if (!keepGoing) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
vjs.Player.prototype.hasStarted = function(hasStarted){
if (hasStarted !== undefined) {
// only update if this is a new value
if (this.hasStarted_ !== hasStarted) {
this.hasStarted_ = hasStarted;
if (hasStarted) {
this.addClass('vjs-has-started');
// trigger the firstplay event if this newly has played
this.trigger('firstplay');
} else {
this.removeClass('vjs-has-started');
}
}
return this;
}
}
return this.hasStarted_;
};
/**
* Fired when the player has initial duration and dimension information

View File

@ -40,6 +40,7 @@ vjs.MediaFaker.prototype.src = function(){ return 'movie.mp4'; };
vjs.MediaFaker.prototype.volume = function(){ return 0; };
vjs.MediaFaker.prototype.muted = function(){ return false; };
vjs.MediaFaker.prototype.pause = function(){ return false; };
vjs.MediaFaker.prototype.paused = function(){ return true; };
vjs.MediaFaker.prototype.supportsFullScreen = function(){ return false; };
vjs.MediaFaker.prototype.features = {};
vjs.MediaFaker.prototype.buffered = function(){ return {}; };

View File

@ -378,7 +378,7 @@ test('should not add multiple first play events despite subsequent loads', funct
var player = PlayerTest.makePlayer({});
player.on('firstplay', function(){
ok('First play should fire once.');
ok(true, 'First play should fire once.');
});
// Checking to make sure onLoadStart removes first play listener before adding a new one.
@ -387,6 +387,35 @@ test('should not add multiple first play events despite subsequent loads', funct
player.trigger('play');
});
test('should fire firstplay after resetting the player', function() {
var player = PlayerTest.makePlayer({});
var fpFired = false;
player.on('firstplay', function(){
fpFired = true;
});
// init firstplay listeners
player.trigger('loadstart');
player.trigger('play');
ok(fpFired, 'First firstplay fired');
// reset the player
player.trigger('loadstart');
fpFired = false;
player.trigger('play');
ok(fpFired, 'Second firstplay fired');
// the play event can fire before the loadstart event.
// in that case we still want the firstplay even to fire.
player.tech.paused = function(){ return false; };
fpFired = false;
// reset the player
player.trigger('loadstart');
// player.trigger('play');
ok(fpFired, 'Third firstplay fired');
});
test('should remove vjs-has-started class', function(){
expect(3);