Merge branch 'develop' into css-variables
# Conflicts: # src/js/captions.js # src/js/config/defaults.js # src/js/fullscreen.js # src/js/listeners.js # src/js/plyr.js
This commit is contained in:
commit
2458eaa11b
@ -13,6 +13,6 @@
|
|||||||
--plyr-font-weight-regular: 500,
|
--plyr-font-weight-regular: 500,
|
||||||
--plyr-font-weight-bold: 600,
|
--plyr-font-weight-bold: 600,
|
||||||
--plyr-font-size-captions-medium: 18px,
|
--plyr-font-size-captions-medium: 18px,
|
||||||
--plyr-font-size-captions-large: 21px
|
--plyr-font-size-captions-large: 21px,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -400,7 +400,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
|||||||
| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. |
|
| `toggleInvert` | Boolean | `true` | Allow users to click to toggle the above. |
|
||||||
| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. |
|
| `listeners` | Object | `null` | Allows binding of event listeners to the controls before the default handlers. See the `defaults.js` for available listeners. If your handler prevents default on the event (`event.preventDefault()`), the default handler will not fire. |
|
||||||
| `captions` | Object | `{ active: false, language: 'auto', update: false }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). 'auto' uses the browser language. `update`: Listen to changes to tracks and update menu. This is needed for some streaming libraries, but can result in unselectable language options). |
|
| `captions` | Object | `{ active: false, language: 'auto', update: false }` | `active`: Toggles if captions should be active by default. `language`: Sets the default language to load (if available). 'auto' uses the browser language. `update`: Listen to changes to tracks and update menu. This is needed for some streaming libraries, but can result in unselectable language options). |
|
||||||
| `fullscreen` | Object | `{ enabled: true, fallback: true, iosNative: false }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution (`true`/`false`/`'force'`). `iosNative`: whether to use native iOS fullscreen when entering fullscreen (no custom controls) |
|
| `fullscreen` | Object | `{ enabled: true, fallback: true, iosNative: false, container: null }` | `enabled`: Toggles whether fullscreen should be enabled. `fallback`: Allow fallback to a full-window solution (`true`/`false`/`'force'`). `iosNative`: whether to use native iOS fullscreen when entering fullscreen (no custom controls). `container`: A selector for an ancestor of the player element, allows contextual content to remain visual in fullscreen mode. Non-ancestors are ignored. |
|
||||||
| `ratio` | String | `null` | Force an aspect ratio for all videos. The format is `'w:h'` - e.g. `'16:9'` or `'4:3'`. If this is not specified then the default for HTML5 and Vimeo is to use the native resolution of the video. As dimensions are not available from YouTube via SDK, 16:9 is forced as a sensible default. |
|
| `ratio` | String | `null` | Force an aspect ratio for all videos. The format is `'w:h'` - e.g. `'16:9'` or `'4:3'`. If this is not specified then the default for HTML5 and Vimeo is to use the native resolution of the video. As dimensions are not available from YouTube via SDK, 16:9 is forced as a sensible default. |
|
||||||
| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. |
|
| `storage` | Object | `{ enabled: true, key: 'plyr' }` | `enabled`: Allow use of local storage to store user settings. `key`: The key name to use. |
|
||||||
| `speed` | Object | `{ selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] }` | `selected`: The default speed for playback. `options`: The speed options to display in the UI. YouTube and Vimeo will ignore any options outside of the 0.5-2 range, so options outside of this range will be hidden automatically. |
|
| `speed` | Object | `{ selected: 1, options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] }` | `selected`: The default speed for playback. `options`: The speed options to display in the UI. YouTube and Vimeo will ignore any options outside of the 0.5-2 range, so options outside of this range will be hidden automatically. |
|
||||||
|
@ -133,8 +133,12 @@ const captions = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Turn off native caption rendering to avoid double captions
|
// Turn off native caption rendering to avoid double captions
|
||||||
|
// Note: mode='hidden' forces a track to download. To ensure every track
|
||||||
|
// isn't downloaded at once, only 'showing' tracks should be reassigned
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
track.mode = 'hidden';
|
if (track.mode === 'showing') {
|
||||||
|
track.mode = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
// Add event listener for cue changes
|
// Add event listener for cue changes
|
||||||
on.call(this, track, 'cuechange', () => captions.updateCues.call(this));
|
on.call(this, track, 'cuechange', () => captions.updateCues.call(this));
|
||||||
@ -211,6 +215,14 @@ const captions = {
|
|||||||
// Trigger event (not used internally)
|
// Trigger event (not used internally)
|
||||||
triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
|
triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for the call stack to clear before setting mode='hidden'
|
||||||
|
// on the active track - forcing the browser to download it
|
||||||
|
setTimeout(() => {
|
||||||
|
if (active && this.captions.toggled) {
|
||||||
|
this.captions.currentTrackNode.mode = 'hidden';
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set captions by track index
|
// Set captions by track index
|
||||||
|
@ -115,6 +115,9 @@ const defaults = {
|
|||||||
enabled: true, // Allow fullscreen?
|
enabled: true, // Allow fullscreen?
|
||||||
fallback: true, // Fallback using full viewport/window
|
fallback: true, // Fallback using full viewport/window
|
||||||
iosNative: false, // Use the native fullscreen in iOS (disables custom controls)
|
iosNative: false, // Use the native fullscreen in iOS (disables custom controls)
|
||||||
|
// Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
|
||||||
|
// Non-ancestors of the player element will be ignored
|
||||||
|
// container: null, // defaults to the player element
|
||||||
},
|
},
|
||||||
|
|
||||||
// Local storage
|
// Local storage
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
import browser from './utils/browser';
|
import browser from './utils/browser';
|
||||||
import { getElements, hasClass, toggleClass } from './utils/elements';
|
import { getElements, hasClass, toggleClass, closest } from './utils/elements';
|
||||||
import { on, triggerEvent } from './utils/events';
|
import { on, triggerEvent } from './utils/events';
|
||||||
import is from './utils/is';
|
import is from './utils/is';
|
||||||
import { silencePromise } from './utils/promise';
|
import { silencePromise } from './utils/promise';
|
||||||
@ -25,6 +25,11 @@ class Fullscreen {
|
|||||||
// Force the use of 'full window/browser' rather than fullscreen
|
// Force the use of 'full window/browser' rather than fullscreen
|
||||||
this.forceFallback = player.config.fullscreen.fallback === 'force';
|
this.forceFallback = player.config.fullscreen.fallback === 'force';
|
||||||
|
|
||||||
|
// Get the fullscreen element
|
||||||
|
// Checks container is an ancestor, defaults to null
|
||||||
|
this.player.elements.fullscreen =
|
||||||
|
player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container);
|
||||||
|
|
||||||
// Register event listeners
|
// Register event listeners
|
||||||
// Handle event (incase user presses escape etc)
|
// Handle event (incase user presses escape etc)
|
||||||
on.call(
|
on.call(
|
||||||
@ -126,7 +131,7 @@ class Fullscreen {
|
|||||||
get target() {
|
get target() {
|
||||||
return browser.isIos && this.player.config.fullscreen.iosNative
|
return browser.isIos && this.player.config.fullscreen.iosNative
|
||||||
? this.player.media
|
? this.player.media
|
||||||
: this.player.elements.container;
|
: this.player.elements.fullscreen || this.player.elements.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange() {
|
onChange() {
|
||||||
|
@ -333,7 +333,6 @@ class Listeners {
|
|||||||
|
|
||||||
const resized = () => {
|
const resized = () => {
|
||||||
clearTimeout(timers.resized);
|
clearTimeout(timers.resized);
|
||||||
|
|
||||||
timers.resized = setTimeout(setPlayerSize, 50);
|
timers.resized = setTimeout(setPlayerSize, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -357,7 +356,7 @@ class Listeners {
|
|||||||
// Set Vimeo gutter
|
// Set Vimeo gutter
|
||||||
setGutter(ratio, padding, isEnter);
|
setGutter(ratio, padding, isEnter);
|
||||||
|
|
||||||
// If not using the native browser fullscreen API, we need to check for resizes of viewport
|
// If not using native browser fullscreen API, we need to check for resizes of viewport
|
||||||
if (!usingNative) {
|
if (!usingNative) {
|
||||||
if (isEnter) {
|
if (isEnter) {
|
||||||
on.call(player, window, 'resize', resized);
|
on.call(player, window, 'resize', resized);
|
||||||
@ -817,6 +816,17 @@ class Listeners {
|
|||||||
elements.controls.hover = !player.touch && event.type === 'mouseenter';
|
elements.controls.hover = !player.touch && event.type === 'mouseenter';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Also update controls.hover state for any non-player children of fullscreen element (as above)
|
||||||
|
if (elements.fullscreen) {
|
||||||
|
Array.from(elements.fullscreen.children)
|
||||||
|
.filter(c => !c.contains(elements.container))
|
||||||
|
.forEach(child => {
|
||||||
|
this.bind(child, 'mouseenter mouseleave', event => {
|
||||||
|
elements.controls.hover = !player.touch && event.type === 'mouseenter';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
|
// Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
|
||||||
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {
|
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {
|
||||||
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
|
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
|
||||||
|
@ -80,6 +80,7 @@ class Plyr {
|
|||||||
// Elements cache
|
// Elements cache
|
||||||
this.elements = {
|
this.elements = {
|
||||||
container: null,
|
container: null,
|
||||||
|
fullscreen: null,
|
||||||
captions: null,
|
captions: null,
|
||||||
buttons: {},
|
buttons: {},
|
||||||
display: {},
|
display: {},
|
||||||
@ -285,6 +286,9 @@ class Plyr {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup fullscreen
|
||||||
|
this.fullscreen = new Fullscreen(this);
|
||||||
|
|
||||||
// Setup interface
|
// Setup interface
|
||||||
// If embed but not fully supported, build interface now to avoid flash of controls
|
// If embed but not fully supported, build interface now to avoid flash of controls
|
||||||
if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {
|
if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {
|
||||||
@ -297,9 +301,6 @@ class Plyr {
|
|||||||
// Global listeners
|
// Global listeners
|
||||||
this.listeners.global();
|
this.listeners.global();
|
||||||
|
|
||||||
// Setup fullscreen
|
|
||||||
this.fullscreen = new Fullscreen(this);
|
|
||||||
|
|
||||||
// Setup ads if provided
|
// Setup ads if provided
|
||||||
if (this.config.ads.enabled) {
|
if (this.config.ads.enabled) {
|
||||||
this.ads = new Ads(this);
|
this.ads = new Ads(this);
|
||||||
|
@ -237,6 +237,26 @@ export function matches(element, selector) {
|
|||||||
return method.call(element, selector);
|
return method.call(element, selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Closest ancestor element matching selector (also tests element itself)
|
||||||
|
export function closest(element, selector) {
|
||||||
|
const { prototype } = Element;
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
|
||||||
|
function closestElement() {
|
||||||
|
let el = this;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (matches.matches(el, selector)) return el;
|
||||||
|
el = el.parentElement || el.parentNode;
|
||||||
|
} while (el !== null && el.nodeType === 1);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const method = prototype.closest || closestElement;
|
||||||
|
|
||||||
|
return method.call(element, selector);
|
||||||
|
}
|
||||||
|
|
||||||
// Find all elements
|
// Find all elements
|
||||||
export function getElements(selector) {
|
export function getElements(selector) {
|
||||||
return this.elements.container.querySelectorAll(selector);
|
return this.elements.container.querySelectorAll(selector);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user