aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/fullscreen.js
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2020-04-11 16:23:14 +1000
committerSam Potts <sam@potts.es>2020-04-11 16:23:14 +1000
commit502d5977d79148957828cbf313b7ef4c9f31973f (patch)
tree71bbffcffc9745c5b672a122f3937519ba67c1c4 /src/js/fullscreen.js
parent8f5b59c18cc7837bde9af55d24d12e1fd939043d (diff)
downloadplyr-502d5977d79148957828cbf313b7ef4c9f31973f.tar.lz
plyr-502d5977d79148957828cbf313b7ef4c9f31973f.tar.xz
plyr-502d5977d79148957828cbf313b7ef4c9f31973f.zip
Converted to 2 space indentation
Diffstat (limited to 'src/js/fullscreen.js')
-rw-r--r--src/js/fullscreen.js477
1 files changed, 237 insertions, 240 deletions
diff --git a/src/js/fullscreen.js b/src/js/fullscreen.js
index 4d3c89ac..9d433c80 100644
--- a/src/js/fullscreen.js
+++ b/src/js/fullscreen.js
@@ -11,283 +11,280 @@ import is from './utils/is';
import { silencePromise } from './utils/promise';
class Fullscreen {
- constructor(player) {
- // Keep reference to parent
- this.player = player;
-
- // Get prefix
- this.prefix = Fullscreen.prefix;
- this.property = Fullscreen.property;
-
- // 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)
- on.call(
- this.player,
- document,
- this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,
- () => {
- // TODO: Filter for target??
- this.onChange();
- },
- );
-
- // Fullscreen toggle on double click
- on.call(this.player, this.player.elements.container, 'dblclick', event => {
- // Ignore double click in controls
- if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
- return;
- }
-
- this.toggle();
- });
-
- // Tap focus when in fullscreen
- on.call(this, this.player.elements.container, 'keydown', event => this.trapFocus(event));
-
- // Update the UI
- this.update();
+ constructor(player) {
+ // Keep reference to parent
+ this.player = player;
+
+ // Get prefix
+ this.prefix = Fullscreen.prefix;
+ this.property = Fullscreen.property;
+
+ // 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)
+ on.call(
+ this.player,
+ document,
+ this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,
+ () => {
+ // TODO: Filter for target??
+ this.onChange();
+ },
+ );
+
+ // Fullscreen toggle on double click
+ on.call(this.player, this.player.elements.container, 'dblclick', event => {
+ // Ignore double click in controls
+ if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
+ return;
+ }
+
+ this.toggle();
+ });
+
+ // Tap focus when in fullscreen
+ on.call(this, this.player.elements.container, 'keydown', event => this.trapFocus(event));
+
+ // Update the UI
+ this.update();
+ }
+
+ // Determine if native supported
+ static get native() {
+ 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 (is.function(document.exitFullscreen)) {
+ return '';
}
- // Determine if native supported
- static get native() {
- return !!(
- document.fullscreenEnabled ||
- document.webkitFullscreenEnabled ||
- document.mozFullScreenEnabled ||
- document.msFullscreenEnabled
- );
+ // Check for fullscreen support by vendor prefix
+ let value = '';
+ const prefixes = ['webkit', 'moz', 'ms'];
+
+ prefixes.some(pre => {
+ if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {
+ value = pre;
+ return true;
+ }
+
+ return false;
+ });
+
+ return value;
+ }
+
+ static get property() {
+ return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
+ }
+
+ // Determine if fullscreen is enabled
+ get enabled() {
+ return (
+ (Fullscreen.native || this.player.config.fullscreen.fallback) &&
+ this.player.config.fullscreen.enabled &&
+ this.player.supported.ui &&
+ this.player.isVideo
+ );
+ }
+
+ // Get active state
+ get active() {
+ if (!this.enabled) {
+ return false;
}
- // If we're actually using native
- get usingNative() {
- return Fullscreen.native && !this.forceFallback;
+ // Fallback using classname
+ if (!Fullscreen.native || this.forceFallback) {
+ return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
}
- // Get the prefix for handlers
- static get prefix() {
- // No prefix
- if (is.function(document.exitFullscreen)) {
- return '';
- }
-
- // Check for fullscreen support by vendor prefix
- let value = '';
- const prefixes = ['webkit', 'moz', 'ms'];
+ const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];
- prefixes.some(pre => {
- if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {
- value = pre;
- return true;
- }
+ return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
+ }
- return false;
- });
+ // Get target element
+ get target() {
+ return browser.isIos && this.player.config.fullscreen.iosNative
+ ? this.player.media
+ : this.player.elements.container;
+ }
- return value;
+ onChange() {
+ if (!this.enabled) {
+ return;
}
- static get property() {
- return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
+ // Update toggle button
+ const button = this.player.elements.buttons.fullscreen;
+ if (is.element(button)) {
+ button.pressed = this.active;
}
- // Determine if fullscreen is enabled
- get enabled() {
- return (
- (Fullscreen.native || this.player.config.fullscreen.fallback) &&
- this.player.config.fullscreen.enabled &&
- this.player.supported.ui &&
- this.player.isVideo
- );
+ // Trigger an event
+ triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
+ }
+
+ toggleFallback(toggle = false) {
+ // Store or restore scroll position
+ if (toggle) {
+ this.scrollPosition = {
+ x: window.scrollX || 0,
+ y: window.scrollY || 0,
+ };
+ } else {
+ window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);
}
- // Get active state
- get active() {
- if (!this.enabled) {
- return false;
- }
+ // Toggle scroll
+ document.body.style.overflow = toggle ? 'hidden' : '';
- // Fallback using classname
- if (!Fullscreen.native || this.forceFallback) {
- return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
- }
+ // Toggle class hook
+ toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);
- const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];
+ // Force full viewport on iPhone X+
+ if (browser.isIos) {
+ let viewport = document.head.querySelector('meta[name="viewport"]');
+ const property = 'viewport-fit=cover';
- return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
- }
+ // Inject the viewport meta if required
+ if (!viewport) {
+ viewport = document.createElement('meta');
+ viewport.setAttribute('name', 'viewport');
+ }
- // Get target element
- get target() {
- return browser.isIos && this.player.config.fullscreen.iosNative
- ? this.player.media
- : this.player.elements.container;
- }
+ // Check if the property already exists
+ const hasProperty = is.string(viewport.content) && viewport.content.includes(property);
- onChange() {
- if (!this.enabled) {
- return;
- }
+ if (toggle) {
+ this.cleanupViewport = !hasProperty;
- // Update toggle button
- const button = this.player.elements.buttons.fullscreen;
- if (is.element(button)) {
- button.pressed = this.active;
+ if (!hasProperty) {
+ viewport.content += `,${property}`;
}
-
- // Trigger an event
- triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
+ } else if (this.cleanupViewport) {
+ viewport.content = viewport.content
+ .split(',')
+ .filter(part => part.trim() !== property)
+ .join(',');
+ }
}
- toggleFallback(toggle = false) {
- // Store or restore scroll position
- if (toggle) {
- this.scrollPosition = {
- x: window.scrollX || 0,
- y: window.scrollY || 0,
- };
- } else {
- window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);
- }
-
- // Toggle scroll
- document.body.style.overflow = toggle ? 'hidden' : '';
-
- // Toggle class hook
- 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(',');
- }
- }
+ // Toggle button and fire events
+ this.onChange();
+ }
- // Toggle button and fire events
- this.onChange();
+ // Trap focus inside container
+ trapFocus(event) {
+ // Bail if iOS, not active, not the tab key
+ if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {
+ return;
}
- // Trap focus inside container
- trapFocus(event) {
- // Bail if iOS, not active, not the tab key
- if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {
- return;
- }
-
- // Get the current focused element
- const focused = document.activeElement;
- const focusable = getElements.call(
- this.player,
- 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]',
- );
- const [first] = focusable;
- const last = focusable[focusable.length - 1];
-
- if (focused === last && !event.shiftKey) {
- // Move focus to first element that can be tabbed if Shift isn't used
- first.focus();
- event.preventDefault();
- } else if (focused === first && event.shiftKey) {
- // Move focus to last element that can be tabbed if Shift is used
- last.focus();
- event.preventDefault();
- }
+ // Get the current focused element
+ const focused = document.activeElement;
+ const focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');
+ const [first] = focusable;
+ const last = focusable[focusable.length - 1];
+
+ if (focused === last && !event.shiftKey) {
+ // Move focus to first element that can be tabbed if Shift isn't used
+ first.focus();
+ event.preventDefault();
+ } else if (focused === first && event.shiftKey) {
+ // Move focus to last element that can be tabbed if Shift is used
+ last.focus();
+ event.preventDefault();
}
-
- // Update UI
- update() {
- if (this.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
- toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);
+ }
+
+ // Update UI
+ update() {
+ if (this.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');
}
- // Make an element fullscreen
- enter() {
- if (!this.enabled) {
- return;
- }
+ // Add styling hook to show button
+ toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);
+ }
- // iOS native fullscreen doesn't need the request step
- if (browser.isIos && this.player.config.fullscreen.iosNative) {
- this.target.webkitEnterFullscreen();
- } else if (!Fullscreen.native || this.forceFallback) {
- this.toggleFallback(true);
- } else if (!this.prefix) {
- this.target.requestFullscreen({ navigationUI: 'hide' });
- } else if (!is.empty(this.prefix)) {
- this.target[`${this.prefix}Request${this.property}`]();
- }
+ // Make an element fullscreen
+ enter() {
+ if (!this.enabled) {
+ return;
}
- // Bail from fullscreen
- exit() {
- if (!this.enabled) {
- return;
- }
+ // iOS native fullscreen doesn't need the request step
+ if (browser.isIos && this.player.config.fullscreen.iosNative) {
+ this.target.webkitEnterFullscreen();
+ } else if (!Fullscreen.native || this.forceFallback) {
+ this.toggleFallback(true);
+ } else if (!this.prefix) {
+ this.target.requestFullscreen({ navigationUI: 'hide' });
+ } else if (!is.empty(this.prefix)) {
+ this.target[`${this.prefix}Request${this.property}`]();
+ }
+ }
- // iOS native fullscreen
- if (browser.isIos && this.player.config.fullscreen.iosNative) {
- this.target.webkitExitFullscreen();
- silencePromise(this.player.play());
- } else if (!Fullscreen.native || this.forceFallback) {
- this.toggleFallback(false);
- } else if (!this.prefix) {
- (document.cancelFullScreen || document.exitFullscreen).call(document);
- } else if (!is.empty(this.prefix)) {
- const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
- document[`${this.prefix}${action}${this.property}`]();
- }
+ // Bail from fullscreen
+ exit() {
+ if (!this.enabled) {
+ return;
}
- // Toggle state
- toggle() {
- if (!this.active) {
- this.enter();
- } else {
- this.exit();
- }
+ // iOS native fullscreen
+ if (browser.isIos && this.player.config.fullscreen.iosNative) {
+ this.target.webkitExitFullscreen();
+ silencePromise(this.player.play());
+ } else if (!Fullscreen.native || this.forceFallback) {
+ this.toggleFallback(false);
+ } else if (!this.prefix) {
+ (document.cancelFullScreen || document.exitFullscreen).call(document);
+ } else if (!is.empty(this.prefix)) {
+ const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
+ document[`${this.prefix}${action}${this.property}`]();
+ }
+ }
+
+ // Toggle state
+ toggle() {
+ if (!this.active) {
+ this.enter();
+ } else {
+ this.exit();
}
+ }
}
export default Fullscreen;