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:
parent
5edc3a5cbc
commit
71c0a72717
@ -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))
|
||||
|
||||
--------------------
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 {}; };
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user