1
0
mirror of https://github.com/videojs/video.js.git synced 2024-11-24 08:42:25 +02:00

fix(fs): make sure there's only one fullscreenchange event (#5686)

Before the fullscreen API was un-prefixed, we listened to triggered a
`fullscreenchange` event on the player manually. This worked fine
because a prefixed `fullscreenchange` event was triggered on the player
element itself. But when it was unprefixed, we ended up with two events
now, the unprefixed event and the one we triggered.

Instead, we should listen the event the browser supports and re-trigger
it as the unprefixed event as necessary.

We also make sure that the handler gets calls when the document level
fullscreenchange handler gets called so that it is cancelled properly.

Fixes #5685.
This commit is contained in:
Gary Katsevman 2019-01-07 16:38:47 -05:00 committed by GitHub
parent 513168f6d3
commit 2f00a68a51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 30 deletions

View File

@ -64,6 +64,7 @@ const apiMap = [
const specApi = apiMap[0];
let browserApi;
let prefixedAPI = true;
// determine the supported set of functions
for (let i = 0; i < apiMap.length; i++) {
@ -79,6 +80,9 @@ if (browserApi) {
for (let i = 0; i < browserApi.length; i++) {
FullscreenApi[specApi[i]] = browserApi[i];
}
prefixedAPI = browserApi[0] !== specApi[0];
}
export default FullscreenApi;
export { prefixedAPI };

View File

@ -15,12 +15,13 @@ import * as Dom from './utils/dom.js';
import * as Fn from './utils/fn.js';
import * as Guid from './utils/guid.js';
import * as browser from './utils/browser.js';
import {IE_VERSION} from './utils/browser.js';
import log, { createLogger } from './utils/log.js';
import toTitleCase, { titleCaseEquals } from './utils/to-title-case.js';
import { createTimeRange } from './utils/time-ranges.js';
import { bufferedPercent } from './utils/buffer.js';
import * as stylesheet from './utils/stylesheet.js';
import FullscreenApi from './fullscreen-api.js';
import FullscreenApi, {prefixedAPI as prefixedFS} from './fullscreen-api.js';
import MediaError from './media-error.js';
import safeParseTuple from 'safe-json-parse/tuple';
import {assign} from './utils/obj';
@ -33,7 +34,6 @@ import * as middleware from './tech/middleware.js';
import {ALL as TRACK_TYPES} from './tracks/track-types';
import filterSource from './utils/filter-source';
import {getMimetype, findMimetype} from './utils/mimetypes';
import {IE_VERSION} from './utils/browser';
// The following imports are used only to ensure that the corresponding modules
// are always included in the video.js package. Importing the modules will
@ -519,7 +519,15 @@ class Player extends Component {
this.reportUserActivity();
this.one('play', this.listenForUserActivity_);
this.on('fullscreenchange', this.handleFullscreenChange_);
if (FullscreenApi.fullscreenchange) {
this.on(FullscreenApi.fullscreenchange, this.handleFullscreenChange_);
if (IE_VERSION || browser.IS_FIREFOX && prefixedFS) {
this.on(document, FullscreenApi.fullscreenchange, this.handleFullscreenChange_);
}
}
this.on('stageclick', this.handleStageClick_);
this.breakpoints(this.options_.breakpoints);
@ -549,6 +557,11 @@ class Player extends Component {
// prevent dispose from being called twice
this.off('dispose');
// make sure to remove fs handler on IE from the document
if (IE_VERSION || browser.IS_FIREFOX && prefixedFS) {
this.off(document, FullscreenApi.fullscreenchange, this.handleFullscreenChange_);
}
if (this.styleEl_ && this.styleEl_.parentNode) {
this.styleEl_.parentNode.removeChild(this.styleEl_);
this.styleEl_ = null;
@ -1908,20 +1921,6 @@ class Player extends Component {
event.preventDefault();
}
/**
* Fired when the player switches in or out of fullscreen mode
*
* @private
* @listens Player#fullscreenchange
*/
handleFullscreenChange_() {
if (this.isFullscreen()) {
this.addClass('vjs-fullscreen');
} else {
this.removeClass('vjs-fullscreen');
}
}
/**
* native click events on the SWF aren't triggered on IE11, Win8.1RT
* use stageclick events triggered from inside the SWF instead
@ -1933,6 +1932,51 @@ class Player extends Component {
this.reportUserActivity();
}
/**
* Fired when the player switches in or out of fullscreen mode
*
* @private
* @listens Player#fullscreenchange
* @listens Player#webkitfullscreenchange
* @listens Player#mozfullscreenchange
* @listens Player#MSFullscreenChange
* @fires Player#fullscreenchange
*/
handleFullscreenChange_(event = {}, retriggerEvent = true) {
if (this.isFullscreen()) {
this.addClass('vjs-fullscreen');
} else {
this.removeClass('vjs-fullscreen');
}
if (prefixedFS && retriggerEvent) {
/**
* @event Player#fullscreenchange
* @type {EventTarget~Event}
*/
this.trigger('fullscreenchange');
}
}
/**
* when the document fschange event triggers it calls this
*/
documentFullscreenChange_(e) {
const fsApi = FullscreenApi;
this.isFullscreen(document[fsApi.fullscreenElement]);
// If cancelling fullscreen, remove event listener.
if (this.isFullscreen() === false) {
Events.off(document, fsApi.fullscreenchange, Fn.bind(this, this.documentFullscreenChange_));
if (prefixedFS) {
this.handleFullscreenChange_({}, false);
} else {
this.on(FullscreenApi.fullscreenchange, this.handleFullscreenChange_);
}
}
}
/**
* Handle Tech Fullscreen Change
*
@ -2568,24 +2612,16 @@ class Player extends Component {
// the browser supports going fullscreen at the element level so we can
// take the controls fullscreen as well as the video
if (!prefixedFS) {
this.off(FullscreenApi.fullscreenchange, this.handleFullscreenChange_);
}
// Trigger fullscreenchange event after change
// We have to specifically add this each time, and remove
// when canceling fullscreen. Otherwise if there's multiple
// players on a page, they would all be reacting to the same fullscreen
// events
Events.on(document, fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e) {
this.isFullscreen(document[fsApi.fullscreenElement]);
// If cancelling fullscreen, remove event listener.
if (this.isFullscreen() === false) {
Events.off(document, fsApi.fullscreenchange, documentFullscreenChange);
}
/**
* @event Player#fullscreenchange
* @type {EventTarget~Event}
*/
this.trigger('fullscreenchange');
}));
Events.on(document, fsApi.fullscreenchange, Fn.bind(this, this.documentFullscreenChange_));
this.el_[fsApi.requestFullscreen]();
@ -2617,6 +2653,8 @@ class Player extends Component {
// Check for browser element fullscreen support
if (fsApi.requestFullscreen) {
// remove the document level handler if we're getting called directly.
Events.off(document, fsApi.fullscreenchange, Fn.bind(this, this.documentFullscreenChange_));
document[fsApi.exitFullscreen]();
} else if (this.tech_.supportsFullScreen()) {
this.techCall_('exitFullScreen');