aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/fullscreen.js
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2019-01-29 21:34:40 +1100
committerSam Potts <sam@potts.es>2019-01-29 21:34:40 +1100
commitb1da599b5d5891dc1dca44bd6aa9d8d03872fdcb (patch)
treec799fb2b444482f6d99dcdf3f16a957b290888c0 /src/js/fullscreen.js
parentafc969bac322f9b17dc0554a65fa848eb998c8e6 (diff)
parentb798368ba68853558819d79a995aa0deec27f95e (diff)
downloadplyr-b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb.tar.lz
plyr-b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb.tar.xz
plyr-b1da599b5d5891dc1dca44bd6aa9d8d03872fdcb.zip
Merge branch 'develop' into beta
Diffstat (limited to 'src/js/fullscreen.js')
-rw-r--r--src/js/fullscreen.js126
1 files changed, 92 insertions, 34 deletions
diff --git a/src/js/fullscreen.js b/src/js/fullscreen.js
index cd2d8ac6..c86bf877 100644
--- a/src/js/fullscreen.js
+++ b/src/js/fullscreen.js
@@ -1,11 +1,14 @@
// ==========================================================================
// Fullscreen wrapper
// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing
+// https://webkit.org/blog/7929/designing-websites-for-iphone-x/
// ==========================================================================
-import utils from './utils';
-
-const browser = utils.getBrowser();
+import { repaint } from './utils/animation';
+import browser from './utils/browser';
+import { hasClass, toggleClass, trapFocus } from './utils/elements';
+import { on, triggerEvent } from './utils/events';
+import is from './utils/is';
function onChange() {
if (!this.enabled) {
@@ -14,16 +17,16 @@ function onChange() {
// Update toggle button
const button = this.player.elements.buttons.fullscreen;
- if (utils.is.element(button)) {
- utils.toggleState(button, this.active);
+ if (is.element(button)) {
+ button.pressed = this.active;
}
// Trigger an event
- utils.dispatchEvent(this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
+ triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
// Trap focus in container
if (!browser.isIos) {
- utils.trapFocus.call(this.player, this.target, this.active);
+ trapFocus.call(this.player, this.target, this.active);
}
}
@@ -42,7 +45,38 @@ function toggleFallback(toggle = false) {
document.body.style.overflow = toggle ? 'hidden' : '';
// Toggle class hook
- utils.toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);
+ toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);
+
+ // Force full viewport on iPhone X+
+ if (browser.isIos) {
+ let viewport = document.head.querySelector('meta[name="viewport"]');
+ const property = 'viewport-fit=cover';
+
+ // Inject the viewport meta if required
+ if (!viewport) {
+ viewport = document.createElement('meta');
+ viewport.setAttribute('name', 'viewport');
+ }
+
+ // Check if the property already exists
+ const hasProperty = is.string(viewport.content) && viewport.content.includes(property);
+
+ if (toggle) {
+ this.cleanupViewport = !hasProperty;
+
+ if (!hasProperty) {
+ viewport.content += `,${property}`;
+ }
+ } else if (this.cleanupViewport) {
+ viewport.content = viewport.content
+ .split(',')
+ .filter(part => part.trim() !== property)
+ .join(',');
+ }
+
+ // Force a repaint as sometimes Safari doesn't want to fill the screen
+ setTimeout(() => repaint(this.target), 100);
+ }
// Toggle button and fire events
onChange.call(this);
@@ -60,17 +94,25 @@ class Fullscreen {
// Scroll position
this.scrollPosition = { x: 0, y: 0 };
+ // Force the use of 'full window/browser' rather than fullscreen
+ this.forceFallback = player.config.fullscreen.fallback === 'force';
+
// Register event listeners
// Handle event (incase user presses escape etc)
- utils.on(document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {
- // TODO: Filter for target??
- onChange.call(this);
- });
+ on.call(
+ this.player,
+ document,
+ this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,
+ () => {
+ // TODO: Filter for target??
+ onChange.call(this);
+ },
+ );
// Fullscreen toggle on double click
- utils.on(this.player.elements.container, 'dblclick', event => {
+ on.call(this.player, this.player.elements.container, 'dblclick', event => {
// Ignore double click in controls
- if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
+ if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
return;
}
@@ -83,26 +125,32 @@ class Fullscreen {
// Determine if native supported
static get native() {
- return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);
+ return !!(
+ document.fullscreenEnabled ||
+ document.webkitFullscreenEnabled ||
+ document.mozFullScreenEnabled ||
+ document.msFullscreenEnabled
+ );
+ }
+
+ // If we're actually using native
+ get usingNative() {
+ return Fullscreen.native && !this.forceFallback;
}
// Get the prefix for handlers
static get prefix() {
// No prefix
- if (utils.is.function(document.exitFullscreen)) {
+ if (is.function(document.exitFullscreen)) {
return '';
}
// Check for fullscreen support by vendor prefix
let value = '';
- const prefixes = [
- 'webkit',
- 'moz',
- 'ms',
- ];
+ const prefixes = ['webkit', 'moz', 'ms'];
prefixes.some(pre => {
- if (utils.is.function(document[`${pre}ExitFullscreen`]) || utils.is.function(document[`${pre}CancelFullScreen`])) {
+ if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {
value = pre;
return true;
}
@@ -134,8 +182,8 @@ class Fullscreen {
}
// Fallback using classname
- if (!Fullscreen.native) {
- return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
+ if (!Fullscreen.native || this.forceFallback) {
+ return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
}
const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];
@@ -145,19 +193,31 @@ class Fullscreen {
// Get target element
get target() {
- return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container;
+ return browser.isIos && this.player.config.fullscreen.iosNative
+ ? this.player.media
+ : this.player.elements.container;
}
// Update UI
update() {
if (this.enabled) {
- this.player.debug.log(`${Fullscreen.native ? 'Native' : 'Fallback'} fullscreen enabled`);
+ let mode;
+
+ if (this.forceFallback) {
+ mode = 'Fallback (forced)';
+ } else if (Fullscreen.native) {
+ mode = 'Native';
+ } else {
+ mode = 'Fallback';
+ }
+
+ this.player.debug.log(`${mode} fullscreen enabled`);
} else {
this.player.debug.log('Fullscreen not supported and fallback disabled');
}
// Add styling hook to show button
- utils.toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);
+ toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);
}
// Make an element fullscreen
@@ -168,14 +228,12 @@ class Fullscreen {
// iOS native fullscreen doesn't need the request step
if (browser.isIos && this.player.config.fullscreen.iosNative) {
- if (this.player.playing) {
- this.target.webkitEnterFullscreen();
- }
- } else if (!Fullscreen.native) {
+ this.target.webkitEnterFullscreen();
+ } else if (!Fullscreen.native || this.forceFallback) {
toggleFallback.call(this, true);
} else if (!this.prefix) {
this.target.requestFullscreen();
- } else if (!utils.is.empty(this.prefix)) {
+ } else if (!is.empty(this.prefix)) {
this.target[`${this.prefix}Request${this.property}`]();
}
}
@@ -190,11 +248,11 @@ class Fullscreen {
if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitExitFullscreen();
this.player.play();
- } else if (!Fullscreen.native) {
+ } else if (!Fullscreen.native || this.forceFallback) {
toggleFallback.call(this, false);
} else if (!this.prefix) {
(document.cancelFullScreen || document.exitFullscreen).call(document);
- } else if (!utils.is.empty(this.prefix)) {
+ } else if (!is.empty(this.prefix)) {
const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
document[`${this.prefix}${action}${this.property}`]();
}