commit
95092edc93
19
.eslintrc
19
.eslintrc
@ -11,24 +11,7 @@
|
|||||||
"jQuery": false
|
"jQuery": false
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"import/no-cycle": 1,
|
"import/no-cycle": "warn",
|
||||||
"no-const-assign": 1,
|
|
||||||
"no-shadow": 0,
|
|
||||||
"no-this-before-super": 1,
|
|
||||||
"no-undef": 1,
|
|
||||||
"no-unreachable": 1,
|
|
||||||
"no-unused-vars": 1,
|
|
||||||
"constructor-super": 1,
|
|
||||||
"valid-typeof": 1,
|
|
||||||
"indent": [2, 4, { "SwitchCase": 1 }],
|
|
||||||
"quotes": [2, "single", "avoid-escape"],
|
|
||||||
"semi": [2, "always"],
|
|
||||||
"eqeqeq": [2, "always"],
|
|
||||||
"one-var": [2, "never"],
|
|
||||||
"comma-dangle": [2, "always-multiline"],
|
|
||||||
"spaced-comment": [2, "always"],
|
|
||||||
"no-restricted-globals": 2,
|
|
||||||
"no-param-reassign": [2, { "props": false }],
|
|
||||||
"padding-line-between-statements": [
|
"padding-line-between-statements": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,9 +3,7 @@ node_modules
|
|||||||
credentials.json
|
credentials.json
|
||||||
*.mp4
|
*.mp4
|
||||||
!dist/blank.mp4
|
!dist/blank.mp4
|
||||||
index-*.html
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
package-lock.json
|
|
||||||
*.webm
|
*.webm
|
||||||
.idea/
|
.idea/
|
||||||
|
@ -10,13 +10,15 @@
|
|||||||
"src": "./src/js/plyr.polyfilled.js",
|
"src": "./src/js/plyr.polyfilled.js",
|
||||||
"dist": "./dist/",
|
"dist": "./dist/",
|
||||||
"formats": ["es", "umd"],
|
"formats": ["es", "umd"],
|
||||||
"namespace": "Plyr"
|
"namespace": "Plyr",
|
||||||
|
"polyfill": true
|
||||||
},
|
},
|
||||||
"demo.js": {
|
"demo.js": {
|
||||||
"src": "./demo/src/js/demo.js",
|
"src": "./demo/src/js/demo.js",
|
||||||
"dist": "./demo/dist/",
|
"dist": "./demo/dist/",
|
||||||
"formats": ["iife"],
|
"formats": ["iife"],
|
||||||
"namespace": "Demo"
|
"namespace": "Demo",
|
||||||
|
"polyfill": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"css": {
|
"css": {
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
## v3.5.5
|
||||||
|
|
||||||
|
- YouTube fix for when there are other embeds on the page (thanks @aFarkas)
|
||||||
|
- Separated demo dependencies into their own package.json
|
||||||
|
- Fix for Edge controls flexbox issue when resizing the player (thanks Nick Hawk via Slack)
|
||||||
|
- More aspect ratio fixes
|
||||||
|
|
||||||
## v3.5.4
|
## v3.5.4
|
||||||
|
|
||||||
- Added: Set download URL via new setter
|
- Added: Set download URL via new setter
|
||||||
|
2
demo/dist/demo.css
vendored
2
demo/dist/demo.css
vendored
File diff suppressed because one or more lines are too long
13376
demo/dist/demo.js
vendored
13376
demo/dist/demo.js
vendored
File diff suppressed because it is too large
Load Diff
2
demo/dist/demo.min.js
vendored
2
demo/dist/demo.min.js
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js.map
vendored
2
demo/dist/demo.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/error.css
vendored
2
demo/dist/error.css
vendored
File diff suppressed because one or more lines are too long
@ -17,7 +17,7 @@
|
|||||||
<link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/16x16.png" sizes="16x16" />
|
<link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/16x16.png" sizes="16x16" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.plyr.io/static/icons/180x180.png" />
|
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.plyr.io/static/icons/180x180.png" />
|
||||||
|
|
||||||
<!-- Opengraph -->
|
<!-- Open Graph -->
|
||||||
<meta
|
<meta
|
||||||
property="og:title"
|
property="og:title"
|
||||||
content="Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player"
|
content="Plyr - A simple, customizable HTML5 Video, Audio, YouTube and Vimeo player"
|
||||||
@ -50,12 +50,23 @@
|
|||||||
type="font/woff2"
|
type="font/woff2"
|
||||||
href="https://cdn.plyr.io/static/fonts/gordita-bold.woff2"
|
href="https://cdn.plyr.io/static/fonts/gordita-bold.woff2"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- Google Analytics-->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-132699580-1"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag() {
|
||||||
|
dataLayer.push(arguments);
|
||||||
|
}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', 'UA-132699580-1');
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<header>
|
<header>
|
||||||
<h1>Plyr</h1>
|
<h1>Pl<span>a</span>y<span>e</span>r</h1>
|
||||||
<p>
|
<p>
|
||||||
A simple, accessible and customisable media player for
|
A simple, accessible and customisable media player for
|
||||||
<button type="button" class="faux-link" data-source="video">
|
<button type="button" class="faux-link" data-source="video">
|
||||||
@ -106,8 +117,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="call-to-action">
|
<div class="call-to-action">
|
||||||
<span class="button--with-count">
|
<a href="https://github.com/sampotts/plyr" target="_blank" class="button js-shr">
|
||||||
<a href="https://github.com/sampotts/plyr" target="_blank" class="button js-shr-button">
|
|
||||||
<svg class="icon" role="presentation">
|
<svg class="icon" role="presentation">
|
||||||
<title>GitHub</title>
|
<title>GitHub</title>
|
||||||
<path
|
<path
|
||||||
@ -121,7 +131,6 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Download on GitHub
|
Download on GitHub
|
||||||
</a>
|
</a>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@ -256,23 +265,13 @@
|
|||||||
<a
|
<a
|
||||||
href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts"
|
href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="js-shr-button"
|
class="js-shr"
|
||||||
>tweet it</a
|
>tweet it</a
|
||||||
>
|
>
|
||||||
👍
|
👍
|
||||||
</p>
|
</p>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<script
|
|
||||||
src="https://cdn.polyfill.io/v3/polyfill.min.js?features=es6,Array.prototype.includes,CustomEvent,Object.entries,Object.values,URL,Math.trunc&flags=gated"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
></script>
|
|
||||||
|
|
||||||
<!-- Sharing libary (https://shr.one) -->
|
|
||||||
<script src="https://cdn.shr.one/2.0.0-beta.2/shr.js" crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
<!-- Docs script -->
|
|
||||||
<script src="dist/demo.js" crossorigin="anonymous"></script>
|
<script src="dist/demo.js" crossorigin="anonymous"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
14
demo/package.json
Normal file
14
demo/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "plyr-demo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Demo for Plyr",
|
||||||
|
"homepage": "https://plyr.io",
|
||||||
|
"author": "Sam Potts <sam@potts.es>",
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^3.1.3",
|
||||||
|
"custom-event-polyfill": "^1.0.7",
|
||||||
|
"raven-js": "^3.27.1",
|
||||||
|
"shr-buttons": "2.0.2",
|
||||||
|
"url-polyfill": "^1.1.5"
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,16 @@
|
|||||||
// Please see readme.md in the root or github.com/sampotts/plyr
|
// Please see readme.md in the root or github.com/sampotts/plyr
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
import './tab-focus';
|
||||||
|
import 'custom-event-polyfill';
|
||||||
|
import 'url-polyfill';
|
||||||
|
|
||||||
import Raven from 'raven-js';
|
import Raven from 'raven-js';
|
||||||
|
import Shr from 'shr-buttons';
|
||||||
|
|
||||||
import Plyr from '../../../src/js/plyr';
|
import Plyr from '../../../src/js/plyr';
|
||||||
|
import sources from './sources';
|
||||||
|
import toggleClass from './toggle-class';
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
const { host } = window.location;
|
const { host } = window.location;
|
||||||
@ -17,45 +25,15 @@ import Plyr from '../../../src/js/plyr';
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
Raven.context(() => {
|
Raven.context(() => {
|
||||||
const selector = '#player';
|
const selector = '#player';
|
||||||
const container = document.getElementById('container');
|
|
||||||
|
|
||||||
if (window.Shr) {
|
// Setup share buttons
|
||||||
window.Shr.setup('.js-shr-button', {
|
Shr.setup('.js-shr', {
|
||||||
count: {
|
count: {
|
||||||
classname: 'button__count',
|
className: 'button__count',
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
className: 'button--with-count',
|
||||||
},
|
},
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup tab focus
|
|
||||||
const tabClassName = 'tab-focus';
|
|
||||||
|
|
||||||
// Remove class on blur
|
|
||||||
document.addEventListener('focusout', event => {
|
|
||||||
if (!event.target.classList || container.contains(event.target)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.target.classList.remove(tabClassName);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add classname to tabbed elements
|
|
||||||
document.addEventListener('keydown', event => {
|
|
||||||
if (event.keyCode !== 9) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delay the adding of classname until the focus has changed
|
|
||||||
// This event fires before the focusin event
|
|
||||||
setTimeout(() => {
|
|
||||||
const focused = document.activeElement;
|
|
||||||
|
|
||||||
if (!focused || !focused.classList || container.contains(focused)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
focused.classList.add(tabClassName);
|
|
||||||
}, 10);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Setup the player
|
// Setup the player
|
||||||
@ -93,131 +71,12 @@ import Plyr from '../../../src/js/plyr';
|
|||||||
|
|
||||||
// Setup type toggle
|
// Setup type toggle
|
||||||
const buttons = document.querySelectorAll('[data-source]');
|
const buttons = document.querySelectorAll('[data-source]');
|
||||||
const types = {
|
const types = Object.keys(sources);
|
||||||
video: 'video',
|
const historySupport = Boolean(window.history && window.history.pushState);
|
||||||
audio: 'audio',
|
let currentType = window.location.hash.substring(1);
|
||||||
youtube: 'youtube',
|
const hasCurrentType = !currentType.length;
|
||||||
vimeo: 'vimeo',
|
|
||||||
};
|
|
||||||
let currentType = window.location.hash.replace('#', '');
|
|
||||||
const historySupport = window.history && window.history.pushState;
|
|
||||||
|
|
||||||
// Toggle class on an element
|
|
||||||
function toggleClass(element, className, state) {
|
|
||||||
if (element) {
|
|
||||||
element.classList[state ? 'add' : 'remove'](className);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a new source
|
|
||||||
function newSource(type, init) {
|
|
||||||
// Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video
|
|
||||||
if (
|
|
||||||
!(type in types) ||
|
|
||||||
(!init && type === currentType) ||
|
|
||||||
(!currentType.length && type === types.video)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case types.video:
|
|
||||||
player.source = {
|
|
||||||
type: 'video',
|
|
||||||
title: 'View From A Blue Moon',
|
|
||||||
sources: [
|
|
||||||
{
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4',
|
|
||||||
type: 'video/mp4',
|
|
||||||
size: 576,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4',
|
|
||||||
type: 'video/mp4',
|
|
||||||
size: 720,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4',
|
|
||||||
type: 'video/mp4',
|
|
||||||
size: 1080,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4',
|
|
||||||
type: 'video/mp4',
|
|
||||||
size: 1440,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg',
|
|
||||||
tracks: [
|
|
||||||
{
|
|
||||||
kind: 'captions',
|
|
||||||
label: 'English',
|
|
||||||
srclang: 'en',
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: 'captions',
|
|
||||||
label: 'French',
|
|
||||||
srclang: 'fr',
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case types.audio:
|
|
||||||
player.source = {
|
|
||||||
type: 'audio',
|
|
||||||
title: 'Kishi Bashi – “It All Began With A Burst”',
|
|
||||||
sources: [
|
|
||||||
{
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3',
|
|
||||||
type: 'audio/mp3',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg',
|
|
||||||
type: 'audio/ogg',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case types.youtube:
|
|
||||||
player.source = {
|
|
||||||
type: 'video',
|
|
||||||
sources: [
|
|
||||||
{
|
|
||||||
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
|
|
||||||
provider: 'youtube',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case types.vimeo:
|
|
||||||
player.source = {
|
|
||||||
type: 'video',
|
|
||||||
sources: [
|
|
||||||
{
|
|
||||||
src: 'https://vimeo.com/76979871',
|
|
||||||
provider: 'vimeo',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the current type for next time
|
|
||||||
currentType = type;
|
|
||||||
|
|
||||||
|
function render(type) {
|
||||||
// Remove active classes
|
// Remove active classes
|
||||||
Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false));
|
Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false));
|
||||||
|
|
||||||
@ -226,9 +85,31 @@ import Plyr from '../../../src/js/plyr';
|
|||||||
|
|
||||||
// Show cite
|
// Show cite
|
||||||
Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => {
|
Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => {
|
||||||
cite.setAttribute('hidden', '');
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
cite.hidden = true;
|
||||||
});
|
});
|
||||||
document.querySelector(`.plyr__cite--${type}`).removeAttribute('hidden');
|
|
||||||
|
document.querySelector(`.plyr__cite--${type}`).hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a new source
|
||||||
|
function setSource(type, init) {
|
||||||
|
// Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video
|
||||||
|
if (
|
||||||
|
!types.includes(type) ||
|
||||||
|
(!init && type === currentType) ||
|
||||||
|
(!currentType.length && type === 'video')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new source
|
||||||
|
player.source = sources[type];
|
||||||
|
|
||||||
|
// Set the current type for next time
|
||||||
|
currentType = type;
|
||||||
|
|
||||||
|
render(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind to each button
|
// Bind to each button
|
||||||
@ -236,7 +117,7 @@ import Plyr from '../../../src/js/plyr';
|
|||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
const type = button.getAttribute('data-source');
|
const type = button.getAttribute('data-source');
|
||||||
|
|
||||||
newSource(type);
|
setSource(type);
|
||||||
|
|
||||||
if (historySupport) {
|
if (historySupport) {
|
||||||
window.history.pushState({ type }, '', `#${type}`);
|
window.history.pushState({ type }, '', `#${type}`);
|
||||||
@ -246,36 +127,27 @@ import Plyr from '../../../src/js/plyr';
|
|||||||
|
|
||||||
// List for backwards/forwards
|
// List for backwards/forwards
|
||||||
window.addEventListener('popstate', event => {
|
window.addEventListener('popstate', event => {
|
||||||
if (event.state && 'type' in event.state) {
|
if (event.state && Object.keys(event.state).includes('type')) {
|
||||||
newSource(event.state.type);
|
setSource(event.state.type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// On load
|
|
||||||
if (historySupport) {
|
|
||||||
const video = !currentType.length;
|
|
||||||
|
|
||||||
// If there's no current type set, assume video
|
// If there's no current type set, assume video
|
||||||
if (video) {
|
if (hasCurrentType) {
|
||||||
currentType = types.video;
|
currentType = 'video';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace current history state
|
// Replace current history state
|
||||||
if (currentType in types) {
|
if (historySupport && types.includes(currentType)) {
|
||||||
window.history.replaceState(
|
window.history.replaceState({ type: currentType }, '', hasCurrentType ? '' : `#${currentType}`);
|
||||||
{
|
|
||||||
type: currentType,
|
|
||||||
},
|
|
||||||
'',
|
|
||||||
video ? '' : `#${currentType}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's not video, load the source
|
// If it's not video, load the source
|
||||||
if (currentType !== types.video) {
|
if (currentType !== 'video') {
|
||||||
newSource(currentType, true);
|
setSource(currentType, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render(currentType);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
78
demo/src/js/sources.js
Normal file
78
demo/src/js/sources.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const sources = {
|
||||||
|
video: {
|
||||||
|
type: 'video',
|
||||||
|
title: 'View From A Blue Moon',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4',
|
||||||
|
type: 'video/mp4',
|
||||||
|
size: 576,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4',
|
||||||
|
type: 'video/mp4',
|
||||||
|
size: 720,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4',
|
||||||
|
type: 'video/mp4',
|
||||||
|
size: 1080,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4',
|
||||||
|
type: 'video/mp4',
|
||||||
|
size: 1440,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
poster: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg',
|
||||||
|
tracks: [
|
||||||
|
{
|
||||||
|
kind: 'captions',
|
||||||
|
label: 'English',
|
||||||
|
srclang: 'en',
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'captions',
|
||||||
|
label: 'French',
|
||||||
|
srclang: 'fr',
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
audio: {
|
||||||
|
type: 'audio',
|
||||||
|
title: 'Kishi Bashi – “It All Began With A Burst”',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3',
|
||||||
|
type: 'audio/mp3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg',
|
||||||
|
type: 'audio/ogg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
youtube: {
|
||||||
|
type: 'video',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
|
||||||
|
provider: 'youtube',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
vimeo: {
|
||||||
|
type: 'video',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
src: 'https://vimeo.com/76979871',
|
||||||
|
provider: 'vimeo',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default sources;
|
31
demo/src/js/tab-focus.js
Normal file
31
demo/src/js/tab-focus.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Setup tab focus
|
||||||
|
const container = document.getElementById('container');
|
||||||
|
const tabClassName = 'tab-focus';
|
||||||
|
|
||||||
|
// Remove class on blur
|
||||||
|
document.addEventListener('focusout', event => {
|
||||||
|
if (!event.target.classList || container.contains(event.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.target.classList.remove(tabClassName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add classname to tabbed elements
|
||||||
|
document.addEventListener('keydown', event => {
|
||||||
|
if (event.keyCode !== 9) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay the adding of classname until the focus has changed
|
||||||
|
// This event fires before the focusin event
|
||||||
|
setTimeout(() => {
|
||||||
|
const focused = document.activeElement;
|
||||||
|
|
||||||
|
if (!focused || !focused.classList || container.contains(focused)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
focused.classList.add(tabClassName);
|
||||||
|
}, 10);
|
||||||
|
});
|
5
demo/src/js/toggle-class.js
Normal file
5
demo/src/js/toggle-class.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Toggle class on an element
|
||||||
|
const toggleClass = (element, className = '', toggle = false) =>
|
||||||
|
element && element.classList[toggle ? 'add' : 'remove'](className);
|
||||||
|
|
||||||
|
export default toggleClass;
|
@ -6,11 +6,9 @@
|
|||||||
.button,
|
.button,
|
||||||
.button__count {
|
.button__count {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: $color-button-background;
|
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: $border-radius-base;
|
border-radius: $border-radius-base;
|
||||||
box-shadow: 0 1px 1px rgba(#000, 0.1);
|
box-shadow: 0 1px 1px rgba(#000, 0.1);
|
||||||
color: $color-button-text;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
padding: ($spacing-base * 0.75);
|
padding: ($spacing-base * 0.75);
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -21,14 +19,16 @@
|
|||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
.button {
|
.button {
|
||||||
|
background: $color-button-background;
|
||||||
|
color: $color-button-text;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
padding-left: $spacing-base;
|
padding-left: ($spacing-base * 1.25);
|
||||||
padding-right: $spacing-base;
|
padding-right: ($spacing-base * 1.25);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
color: $gray-dark;
|
background: $color-button-background-hover;
|
||||||
|
|
||||||
// Remove the underline/border
|
// Remove the underline/border
|
||||||
&::after {
|
&::after {
|
||||||
@ -38,7 +38,6 @@
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 2px 2px rgba(#000, 0.1);
|
box-shadow: 0 2px 2px rgba(#000, 0.1);
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
@ -50,7 +49,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
transform: translateY(1px);
|
top: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,12 +65,14 @@
|
|||||||
// Count bubble
|
// Count bubble
|
||||||
.button__count {
|
.button__count {
|
||||||
animation: fadein 0.2s ease;
|
animation: fadein 0.2s ease;
|
||||||
margin-left: ($spacing-base / 2);
|
background: $color-button-count-background;
|
||||||
|
color: $color-button-count-text;
|
||||||
|
margin-left: ($spacing-base * 0.75);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
border: $arrow-size solid transparent;
|
border: $arrow-size solid transparent;
|
||||||
border-left-width: 0;
|
border-left-width: 0;
|
||||||
border-right-color: $color-button-background;
|
border-right-color: $color-button-count-background;
|
||||||
content: '';
|
content: '';
|
||||||
height: 0;
|
height: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -6,6 +6,13 @@ header {
|
|||||||
padding-bottom: $spacing-base;
|
padding-bottom: $spacing-base;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
h1 span {
|
||||||
|
animation: shrinkHide 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) 2s forwards;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: $font-weight-light;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
.call-to-action {
|
.call-to-action {
|
||||||
margin-top: ($spacing-base * 1.5);
|
margin-top: ($spacing-base * 1.5);
|
||||||
}
|
}
|
||||||
@ -15,5 +22,9 @@ header {
|
|||||||
max-width: 360px;
|
max-width: 360px;
|
||||||
padding-bottom: ($spacing-base * 2);
|
padding-bottom: ($spacing-base * 2);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
|
p:first-of-type {
|
||||||
|
@include font-size($font-size-base + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,5 +19,5 @@ label svg {
|
|||||||
|
|
||||||
a .icon,
|
a .icon,
|
||||||
.btn .icon {
|
.btn .icon {
|
||||||
margin-right: floor($spacing-base / 3);
|
margin-right: ($spacing-base / 2);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ button.faux-link {
|
|||||||
a {
|
a {
|
||||||
border-bottom: 1px dotted currentColor;
|
border-bottom: 1px dotted currentColor;
|
||||||
color: $color-link;
|
color: $color-link;
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
@ -2,16 +2,10 @@
|
|||||||
// Examples
|
// Examples
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
// For non supported browsers
|
|
||||||
video {
|
|
||||||
max-width: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example players
|
// Example players
|
||||||
.plyr {
|
.plyr {
|
||||||
border-radius: $border-radius-base;
|
border-radius: $border-radius-base;
|
||||||
box-shadow: 0 2px 5px rgba(#000, 0.2);
|
box-shadow: 0 2px 15px rgba(#000, 0.1);
|
||||||
margin: $spacing-base auto;
|
margin: $spacing-base auto;
|
||||||
|
|
||||||
&.plyr--audio {
|
&.plyr--audio {
|
||||||
@ -34,17 +28,9 @@ video {
|
|||||||
|
|
||||||
// Style full supported player
|
// Style full supported player
|
||||||
.plyr__cite {
|
.plyr__cite {
|
||||||
display: none;
|
color: $color-gray-5;
|
||||||
margin-top: $spacing-base;
|
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
margin-right: ceil($spacing-base / 6);
|
margin-right: ceil($spacing-base / 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr--video:not(.plyr--youtube):not(.plyr--vimeo) ~ ul .plyr__cite--video,
|
|
||||||
.plyr--audio ~ ul .plyr__cite--audio,
|
|
||||||
.plyr--youtube ~ ul .plyr__cite--youtube,
|
|
||||||
.plyr--vimeo ~ ul .plyr__cite--vimeo {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
@ -35,11 +35,10 @@ main {
|
|||||||
aside {
|
aside {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: $gray;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: ($spacing-base * 0.75);
|
padding: $spacing-base;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
|
@ -11,3 +11,17 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes shrinkHide {
|
||||||
|
0% {
|
||||||
|
opacity: 0.5;
|
||||||
|
width: 38px;
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
width: 45px;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
@return #{$rem}rem;
|
@return #{$rem}rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin font-size($size: 16) {
|
@mixin font-size($size: $font-size-base) {
|
||||||
font-size: $size * 1px; // Fallback in px
|
font-size: $size * 1px; // Fallback in px
|
||||||
font-size: calculate-rem($size);
|
font-size: calculate-rem($size);
|
||||||
}
|
}
|
||||||
|
@ -2,31 +2,41 @@
|
|||||||
// Colors
|
// Colors
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
// Greyscale
|
// Grayscale
|
||||||
$gray-dark: #343f4a;
|
$color-gray-9: hsl(210, 15%, 16%);
|
||||||
$gray: #55646b;
|
$color-gray-8: lighten($color-gray-9, 9%);
|
||||||
$gray-light: #cbd0d3;
|
$color-gray-7: lighten($color-gray-8, 9%);
|
||||||
$gray-lighter: #dbe3e8;
|
$color-gray-6: lighten($color-gray-7, 9%);
|
||||||
$off-white: #f2f5f7;
|
$color-gray-5: lighten($color-gray-6, 9%);
|
||||||
|
$color-gray-4: lighten($color-gray-5, 9%);
|
||||||
|
$color-gray-3: lighten($color-gray-4, 9%);
|
||||||
|
$color-gray-2: lighten($color-gray-3, 9%);
|
||||||
|
$color-gray-1: lighten($color-gray-2, 9%);
|
||||||
|
$color-gray-0: lighten($color-gray-1, 9%);
|
||||||
|
|
||||||
|
// Branding
|
||||||
|
$color-brand-primary: hsl(198, 100%, 50%);
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
$color-text: #fff;
|
$color-text: $color-gray-7;
|
||||||
|
$color-headings: $color-brand-primary;
|
||||||
// Plyr
|
|
||||||
$color-brand-primary: #1aafff;
|
|
||||||
|
|
||||||
// Brands
|
// Brands
|
||||||
$color-twitter: #4baaf4;
|
$color-twitter: #4baaf4;
|
||||||
$color-youtube: #cc181e;
|
|
||||||
$color-vimeo: #19b7ed;
|
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
$color-link: #fff;
|
$color-link: $color-brand-primary;
|
||||||
$color-background: $color-brand-primary;
|
|
||||||
|
// Background
|
||||||
|
$color-background-from: hsl(198, 100%, 94%);
|
||||||
|
$color-background-to: hsl(198, 100%, 98%);
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
$color-button-background: #fff;
|
$color-button-background: $color-brand-primary;
|
||||||
$color-button-text: $gray;
|
$color-button-text: #fff;
|
||||||
|
$color-button-background-hover: hsl(198, 100%, 55%);
|
||||||
|
$color-button-count-background: #fff;
|
||||||
|
$color-button-count-text: $color-gray-6;
|
||||||
|
|
||||||
// Focus
|
// Focus
|
||||||
$tab-focus-default-color: #fff;
|
$tab-focus-default-color: #fff;
|
||||||
|
@ -9,4 +9,4 @@ $arrow-size: 5px;
|
|||||||
$border-radius-base: 4px;
|
$border-radius-base: 4px;
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
$page-background: linear-gradient(to left top, lighten($color-background, 10%), darken($color-background, 20%));
|
$page-background: linear-gradient(to left top, $color-background-from, $color-background-to);
|
||||||
|
@ -14,6 +14,9 @@ $plyr-font-size-badges: 9px;
|
|||||||
// Other
|
// Other
|
||||||
$plyr-font-smoothing: true;
|
$plyr-font-smoothing: true;
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
$plyr-color-main: $color-brand-primary;
|
||||||
|
|
||||||
// Captions
|
// Captions
|
||||||
$plyr-font-size-captions-base: $plyr-font-size-base;
|
$plyr-font-size-captions-base: $plyr-font-size-base;
|
||||||
$plyr-font-size-captions-small: $plyr-font-size-small;
|
$plyr-font-size-captions-small: $plyr-font-size-small;
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
// Colors
|
// Colors
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$spacing-base: 20px;
|
$spacing-base: 16px;
|
||||||
|
@ -14,7 +14,6 @@ body {
|
|||||||
font-family: $font-sans-serif;
|
font-family: $font-sans-serif;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
line-height: $line-height-base;
|
line-height: $line-height-base;
|
||||||
text-shadow: 0 1px 1px rgba(#000, 0.15);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
@ -26,7 +25,7 @@ textarea {
|
|||||||
|
|
||||||
p,
|
p,
|
||||||
small {
|
small {
|
||||||
margin: 0 0 $spacing-base;
|
margin: 0 0 ($spacing-base * 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
small {
|
small {
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@include font-size($font-size-h1);
|
@include font-size($font-size-h1);
|
||||||
|
color: $color-headings;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
letter-spacing: $letter-spacing-headings;
|
letter-spacing: $letter-spacing-headings;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
margin: 0 0 $spacing-base;
|
margin: 0 0 ($spacing-base * 1.5);
|
||||||
}
|
}
|
||||||
|
28
demo/yarn.lock
Normal file
28
demo/yarn.lock
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
core-js@^3.1.3:
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.3.tgz#95700bca5f248f5f78c0ec63e784eca663ec4138"
|
||||||
|
integrity sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA==
|
||||||
|
|
||||||
|
custom-event-polyfill@^1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz#9bc993ddda937c1a30ccd335614c6c58c4f87aee"
|
||||||
|
integrity sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==
|
||||||
|
|
||||||
|
raven-js@^3.27.1:
|
||||||
|
version "3.27.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.27.1.tgz#e187a12982061908ccbf935af0640c9043d7d666"
|
||||||
|
integrity sha512-r/9CwSbaGfBFjo4hGR45DAmrukUKkQ4HdMu80PlVLDY1t8f9b4aaZzTsFegaafu7EGhEYougWDJ9/IcTdYdLXQ==
|
||||||
|
|
||||||
|
shr-buttons@2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/shr-buttons/-/shr-buttons-2.0.2.tgz#a3c11b36067b8902afbff9845d0e023f9f76865f"
|
||||||
|
integrity sha512-UYaZjF5FK1NZrXjQF8YkWOzxM7Z210lv3TDsFMTTp7hbJrdybNPF4WX4k5a+dW25R97FMBZaSnMWvI9TpuCCoA==
|
||||||
|
|
||||||
|
url-polyfill@^1.1.5:
|
||||||
|
version "1.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/url-polyfill/-/url-polyfill-1.1.5.tgz#bec79b72b5407dba6d8cced2e32e4ab273aa9fb1"
|
||||||
|
integrity sha512-9XjIJ6nwrU+nGd8t90Ze0Zs7t8A+SU0gqsqPttj6j3zAVe5q0HFcuv37nDBdVSPpi4aTHTfbUF/i+ZVD+o2EbA==
|
2
dist/plyr.css
vendored
2
dist/plyr.css
vendored
File diff suppressed because one or more lines are too long
312
dist/plyr.js
vendored
312
dist/plyr.js
vendored
@ -540,6 +540,49 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
empty: isEmpty$1
|
empty: isEmpty$1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
var transitionEndEvent = function () {
|
||||||
|
var element = document.createElement('span');
|
||||||
|
var events = {
|
||||||
|
WebkitTransition: 'webkitTransitionEnd',
|
||||||
|
MozTransition: 'transitionend',
|
||||||
|
OTransition: 'oTransitionEnd otransitionend',
|
||||||
|
transition: 'transitionend'
|
||||||
|
};
|
||||||
|
var type = Object.keys(events).find(function (event) {
|
||||||
|
return element.style[event] !== undefined;
|
||||||
|
});
|
||||||
|
return is$1.string(type) ? events[type] : false;
|
||||||
|
}(); // Force repaint of element
|
||||||
|
|
||||||
|
function repaint(element, delay) {
|
||||||
|
setTimeout(function () {
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
element.hidden = true; // eslint-disable-next-line no-unused-expressions
|
||||||
|
|
||||||
|
element.offsetHeight; // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
|
element.hidden = false;
|
||||||
|
} catch (e) {// Do nothing
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Browser sniffing
|
||||||
|
// Unfortunately, due to mixed support, UA sniffing is required
|
||||||
|
// ==========================================================================
|
||||||
|
var browser = {
|
||||||
|
isIE:
|
||||||
|
/* @cc_on!@ */
|
||||||
|
!!document.documentMode,
|
||||||
|
isEdge: window.navigator.userAgent.includes('Edge'),
|
||||||
|
isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
|
||||||
|
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
|
||||||
|
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform)
|
||||||
|
};
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
||||||
// https://www.youtube.com/watch?v=NPM6172J22g
|
// https://www.youtube.com/watch?v=NPM6172J22g
|
||||||
@ -903,13 +946,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
if (!is$1.boolean(hide)) {
|
if (!is$1.boolean(hide)) {
|
||||||
hide = !element.hidden;
|
hide = !element.hidden;
|
||||||
}
|
} // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
if (hide) {
|
|
||||||
element.setAttribute('hidden', '');
|
element.hidden = hide;
|
||||||
} else {
|
|
||||||
element.removeAttribute('hidden');
|
|
||||||
}
|
|
||||||
} // Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
} // Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
||||||
|
|
||||||
function toggleClass(element, className, force) {
|
function toggleClass(element, className, force) {
|
||||||
@ -943,8 +983,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return Array.from(document.querySelectorAll(selector)).includes(this);
|
return Array.from(document.querySelectorAll(selector)).includes(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = match;
|
var method = match;
|
||||||
return matches.call(element, selector);
|
return method.call(element, selector);
|
||||||
} // Find all elements
|
} // Find all elements
|
||||||
|
|
||||||
function getElements(selector) {
|
function getElements(selector) {
|
||||||
@ -1008,47 +1048,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
|
||||||
var transitionEndEvent = function () {
|
|
||||||
var element = document.createElement('span');
|
|
||||||
var events = {
|
|
||||||
WebkitTransition: 'webkitTransitionEnd',
|
|
||||||
MozTransition: 'transitionend',
|
|
||||||
OTransition: 'oTransitionEnd otransitionend',
|
|
||||||
transition: 'transitionend'
|
|
||||||
};
|
|
||||||
var type = Object.keys(events).find(function (event) {
|
|
||||||
return element.style[event] !== undefined;
|
|
||||||
});
|
|
||||||
return is$1.string(type) ? events[type] : false;
|
|
||||||
}(); // Force repaint of element
|
|
||||||
|
|
||||||
function repaint(element) {
|
|
||||||
setTimeout(function () {
|
|
||||||
try {
|
|
||||||
toggleHidden(element, true);
|
|
||||||
element.offsetHeight; // eslint-disable-line
|
|
||||||
|
|
||||||
toggleHidden(element, false);
|
|
||||||
} catch (e) {// Do nothing
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================================
|
|
||||||
// Browser sniffing
|
|
||||||
// Unfortunately, due to mixed support, UA sniffing is required
|
|
||||||
// ==========================================================================
|
|
||||||
var browser = {
|
|
||||||
isIE:
|
|
||||||
/* @cc_on!@ */
|
|
||||||
!!document.documentMode,
|
|
||||||
isEdge: window.navigator.userAgent.includes('Edge'),
|
|
||||||
isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
|
|
||||||
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
|
|
||||||
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform)
|
|
||||||
};
|
|
||||||
|
|
||||||
var defaultCodecs = {
|
var defaultCodecs = {
|
||||||
'audio/ogg': 'vorbis',
|
'audio/ogg': 'vorbis',
|
||||||
'audio/wav': '1',
|
'audio/wav': '1',
|
||||||
@ -1172,12 +1171,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
function getAspectRatio(input) {
|
function getAspectRatio(input) {
|
||||||
var parse = function parse(ratio) {
|
var parse = function parse(ratio) {
|
||||||
if (!validateRatio(ratio)) {
|
return validateRatio(ratio) ? ratio.split(':').map(Number) : null;
|
||||||
return null;
|
}; // Try provided ratio
|
||||||
}
|
|
||||||
|
|
||||||
return ratio.split(':').map(Number);
|
|
||||||
}; // Provided ratio
|
|
||||||
|
|
||||||
|
|
||||||
var ratio = parse(input); // Get from config
|
var ratio = parse(input); // Get from config
|
||||||
@ -1264,16 +1259,19 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var player = this; // Set aspect ratio if set
|
var player = this; // Set aspect ratio if fixed
|
||||||
|
|
||||||
|
if (!is$1.empty(this.config.ratio)) {
|
||||||
|
setAspectRatio.call(player);
|
||||||
|
} // Quality
|
||||||
|
|
||||||
setAspectRatio.call(player); // Quality
|
|
||||||
|
|
||||||
Object.defineProperty(player.media, 'quality', {
|
Object.defineProperty(player.media, 'quality', {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
// Get sources
|
// Get sources
|
||||||
var sources = html5.getSources.call(player);
|
var sources = html5.getSources.call(player);
|
||||||
var source = sources.find(function (source) {
|
var source = sources.find(function (s) {
|
||||||
return source.getAttribute('src') === player.source;
|
return s.getAttribute('src') === player.source;
|
||||||
}); // Return size, if match is found
|
}); // Return size, if match is found
|
||||||
|
|
||||||
return source && Number(source.getAttribute('size'));
|
return source && Number(source.getAttribute('size'));
|
||||||
@ -1282,8 +1280,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Get sources
|
// Get sources
|
||||||
var sources = html5.getSources.call(player); // Get first match for requested size
|
var sources = html5.getSources.call(player); // Get first match for requested size
|
||||||
|
|
||||||
var source = sources.find(function (source) {
|
var source = sources.find(function (s) {
|
||||||
return Number(source.getAttribute('size')) === input;
|
return Number(s.getAttribute('size')) === input;
|
||||||
}); // No matching source found
|
}); // No matching source found
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
@ -1473,10 +1471,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
};
|
};
|
||||||
Object.entries(replace).forEach(function (_ref) {
|
Object.entries(replace).forEach(function (_ref) {
|
||||||
var _ref2 = _slicedToArray(_ref, 2),
|
var _ref2 = _slicedToArray(_ref, 2),
|
||||||
key = _ref2[0],
|
k = _ref2[0],
|
||||||
value = _ref2[1];
|
v = _ref2[1];
|
||||||
|
|
||||||
string = replaceAll(string, key, value);
|
string = replaceAll(string, k, v);
|
||||||
});
|
});
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
@ -1611,6 +1609,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var update = function update(container, data) {
|
var update = function update(container, data) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
container.innerHTML = data; // Check again incase of race condition
|
container.innerHTML = data; // Check again incase of race condition
|
||||||
|
|
||||||
if (hasId && exists()) {
|
if (hasId && exists()) {
|
||||||
@ -2085,9 +2084,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
get: function get() {
|
get: function get() {
|
||||||
return menuItem.getAttribute('aria-checked') === 'true';
|
return menuItem.getAttribute('aria-checked') === 'true';
|
||||||
},
|
},
|
||||||
set: function set(checked) {
|
set: function set(check) {
|
||||||
// Ensure exclusivity
|
// Ensure exclusivity
|
||||||
if (checked) {
|
if (check) {
|
||||||
Array.from(menuItem.parentNode.children).filter(function (node) {
|
Array.from(menuItem.parentNode.children).filter(function (node) {
|
||||||
return matches$1(node, '[role="menuitemradio"]');
|
return matches$1(node, '[role="menuitemradio"]');
|
||||||
}).forEach(function (node) {
|
}).forEach(function (node) {
|
||||||
@ -2095,7 +2094,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');
|
menuItem.setAttribute('aria-checked', check ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.listeners.bind(menuItem, 'click keyup', function (event) {
|
this.listeners.bind(menuItem, 'click keyup', function (event) {
|
||||||
@ -2197,16 +2196,16 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var value = 0;
|
var value = 0;
|
||||||
|
|
||||||
var setProgress = function setProgress(target, input) {
|
var setProgress = function setProgress(target, input) {
|
||||||
var value = is$1.number(input) ? input : 0;
|
var val = is$1.number(input) ? input : 0;
|
||||||
var progress = is$1.element(target) ? target : _this4.elements.display.buffer; // Update value and label
|
var progress = is$1.element(target) ? target : _this4.elements.display.buffer; // Update value and label
|
||||||
|
|
||||||
if (is$1.element(progress)) {
|
if (is$1.element(progress)) {
|
||||||
progress.value = value; // Update text label inside
|
progress.value = val; // Update text label inside
|
||||||
|
|
||||||
var label = progress.getElementsByTagName('span')[0];
|
var label = progress.getElementsByTagName('span')[0];
|
||||||
|
|
||||||
if (is$1.element(label)) {
|
if (is$1.element(label)) {
|
||||||
label.childNodes[0].nodeValue = value;
|
label.childNodes[0].nodeValue = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2275,15 +2274,12 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
// Bail if setting not true
|
// Bail if setting not true
|
||||||
if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) {
|
if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) {
|
||||||
return;
|
return;
|
||||||
} // Calculate percentage
|
}
|
||||||
|
|
||||||
|
|
||||||
var percent = 0;
|
|
||||||
var clientRect = this.elements.progress.getBoundingClientRect();
|
|
||||||
var visible = "".concat(this.config.classNames.tooltip, "--visible");
|
var visible = "".concat(this.config.classNames.tooltip, "--visible");
|
||||||
|
|
||||||
var toggle = function toggle(_toggle) {
|
var toggle = function toggle(show) {
|
||||||
toggleClass(_this5.elements.display.seekTooltip, visible, _toggle);
|
return toggleClass(_this5.elements.display.seekTooltip, visible, show);
|
||||||
}; // Hide on touch
|
}; // Hide on touch
|
||||||
|
|
||||||
|
|
||||||
@ -2293,6 +2289,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
} // Determine percentage, if already visible
|
} // Determine percentage, if already visible
|
||||||
|
|
||||||
|
|
||||||
|
var percent = 0;
|
||||||
|
var clientRect = this.elements.progress.getBoundingClientRect();
|
||||||
|
|
||||||
if (is$1.event(event)) {
|
if (is$1.event(event)) {
|
||||||
percent = 100 / clientRect.width * (event.pageX - clientRect.left);
|
percent = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
||||||
@ -2653,8 +2652,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var target = pane;
|
var target = pane;
|
||||||
|
|
||||||
if (!is$1.element(target)) {
|
if (!is$1.element(target)) {
|
||||||
target = Object.values(this.elements.settings.panels).find(function (pane) {
|
target = Object.values(this.elements.settings.panels).find(function (p) {
|
||||||
return !pane.hidden;
|
return !p.hidden;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2909,17 +2908,15 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
if (control === 'settings' && !is$1.empty(_this10.config.settings)) {
|
if (control === 'settings' && !is$1.empty(_this10.config.settings)) {
|
||||||
var _control = createElement('div', extend({}, defaultAttributes, {
|
var wrapper = createElement('div', extend({}, defaultAttributes, {
|
||||||
class: "".concat(defaultAttributes.class, " plyr__menu").trim(),
|
class: "".concat(defaultAttributes.class, " plyr__menu").trim(),
|
||||||
hidden: ''
|
hidden: ''
|
||||||
}));
|
}));
|
||||||
|
wrapper.appendChild(createButton.call(_this10, 'settings', {
|
||||||
_control.appendChild(createButton.call(_this10, 'settings', {
|
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
'aria-controls': "plyr-settings-".concat(data.id),
|
'aria-controls': "plyr-settings-".concat(data.id),
|
||||||
'aria-expanded': false
|
'aria-expanded': false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var popup = createElement('div', {
|
var popup = createElement('div', {
|
||||||
class: 'plyr__menu__container',
|
class: 'plyr__menu__container',
|
||||||
id: "plyr-settings-".concat(data.id),
|
id: "plyr-settings-".concat(data.id),
|
||||||
@ -3008,12 +3005,10 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
popup.appendChild(inner);
|
popup.appendChild(inner);
|
||||||
|
wrapper.appendChild(popup);
|
||||||
_control.appendChild(popup);
|
container.appendChild(wrapper);
|
||||||
|
|
||||||
container.appendChild(_control);
|
|
||||||
_this10.elements.settings.popup = popup;
|
_this10.elements.settings.popup = popup;
|
||||||
_this10.elements.settings.menu = _control;
|
_this10.elements.settings.menu = wrapper;
|
||||||
} // Picture in picture button
|
} // Picture in picture button
|
||||||
|
|
||||||
|
|
||||||
@ -3344,6 +3339,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
meta.set(track, {
|
meta.set(track, {
|
||||||
default: track.mode === 'showing'
|
default: track.mode === 'showing'
|
||||||
}); // Turn off native caption rendering to avoid double captions
|
}); // Turn off native caption rendering to avoid double captions
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
track.mode = 'hidden'; // Add event listener for cue changes
|
track.mode = 'hidden'; // Add event listener for cue changes
|
||||||
|
|
||||||
@ -3525,8 +3521,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
var track;
|
var track;
|
||||||
languages.every(function (language) {
|
languages.every(function (language) {
|
||||||
track = sorted.find(function (track) {
|
track = sorted.find(function (t) {
|
||||||
return track.language === language;
|
return t.language === language;
|
||||||
});
|
});
|
||||||
return !track; // Break iteration if there is a match
|
return !track; // Break iteration if there is a match
|
||||||
}); // If no match is found but is required, get first
|
}); // If no match is found but is required, get first
|
||||||
@ -3705,7 +3701,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
controls: ['play-large', // 'restart',
|
controls: ['play-large', // 'restart',
|
||||||
// 'rewind',
|
// 'rewind',
|
||||||
'play', // 'fast-forward',
|
'play', // 'fast-forward',
|
||||||
'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download',
|
'progress', 'current-time', // 'duration',
|
||||||
|
'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download',
|
||||||
'fullscreen'],
|
'fullscreen'],
|
||||||
settings: ['captions', 'quality', 'speed'],
|
settings: ['captions', 'quality', 'speed'],
|
||||||
// Localisation
|
// Localisation
|
||||||
@ -3763,8 +3760,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
},
|
},
|
||||||
youtube: {
|
youtube: {
|
||||||
sdk: 'https://www.youtube.com/iframe_api',
|
sdk: 'https://www.youtube.com/iframe_api',
|
||||||
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}' // 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title),fileDetails)&part=snippet',
|
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}'
|
||||||
|
|
||||||
},
|
},
|
||||||
googleIMA: {
|
googleIMA: {
|
||||||
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'
|
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'
|
||||||
@ -4049,8 +4045,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleFallback() {
|
function toggleFallback() {
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
||||||
|
|
||||||
// Store or restore scroll position
|
// Store or restore scroll position
|
||||||
@ -4090,12 +4084,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
viewport.content = viewport.content.split(',').filter(function (part) {
|
viewport.content = viewport.content.split(',').filter(function (part) {
|
||||||
return part.trim() !== property;
|
return part.trim() !== property;
|
||||||
}).join(',');
|
}).join(',');
|
||||||
} // Force a repaint as sometimes Safari doesn't want to fill the screen
|
}
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
return repaint(_this.target);
|
|
||||||
}, 100);
|
|
||||||
} // Toggle button and fire events
|
} // Toggle button and fire events
|
||||||
|
|
||||||
|
|
||||||
@ -4106,7 +4095,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
function () {
|
function () {
|
||||||
function Fullscreen(player) {
|
function Fullscreen(player) {
|
||||||
var _this2 = this;
|
var _this = this;
|
||||||
|
|
||||||
_classCallCheck(this, Fullscreen);
|
_classCallCheck(this, Fullscreen);
|
||||||
|
|
||||||
@ -4126,16 +4115,16 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
|
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
|
||||||
// TODO: Filter for target??
|
// TODO: Filter for target??
|
||||||
onChange.call(_this2);
|
onChange.call(_this);
|
||||||
}); // Fullscreen toggle on double click
|
}); // Fullscreen toggle on double click
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.container, 'dblclick', function (event) {
|
on.call(this.player, this.player.elements.container, 'dblclick', function (event) {
|
||||||
// Ignore double click in controls
|
// Ignore double click in controls
|
||||||
if (is$1.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) {
|
if (is$1.element(_this.player.elements.controls) && _this.player.elements.controls.contains(event.target)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_this2.toggle();
|
_this.toggle();
|
||||||
}); // Update the UI
|
}); // Update the UI
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
@ -4483,7 +4472,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state
|
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state
|
||||||
|
|
||||||
Array.from(this.elements.buttons.play || []).forEach(function (target) {
|
Array.from(this.elements.buttons.play || []).forEach(function (target) {
|
||||||
target.pressed = _this3.playing;
|
Object.assign(target, {
|
||||||
|
pressed: _this3.playing
|
||||||
|
});
|
||||||
}); // Only update controls on non timeupdate events
|
}); // Only update controls on non timeupdate events
|
||||||
|
|
||||||
if (is$1.event(event) && event.type === 'timeupdate') {
|
if (is$1.event(event) && event.type === 'timeupdate') {
|
||||||
@ -4510,13 +4501,13 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
},
|
},
|
||||||
// Toggle controls based on state and `force` argument
|
// Toggle controls based on state and `force` argument
|
||||||
toggleControls: function toggleControls(force) {
|
toggleControls: function toggleControls(force) {
|
||||||
var controls = this.elements.controls;
|
var controlsElement = this.elements.controls;
|
||||||
|
|
||||||
if (controls && this.config.hideControls) {
|
if (controlsElement && this.config.hideControls) {
|
||||||
// Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)
|
// Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)
|
||||||
var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide
|
var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide
|
||||||
|
|
||||||
this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));
|
this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -4784,11 +4775,11 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
|
|
||||||
on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) {
|
on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) {
|
||||||
var controls = elements.controls; // Remove button states for fullscreen
|
var controlsElement = elements.controls; // Remove button states for fullscreen
|
||||||
|
|
||||||
if (controls && event.type === 'enterfullscreen') {
|
if (controlsElement && event.type === 'enterfullscreen') {
|
||||||
controls.pressed = false;
|
controlsElement.pressed = false;
|
||||||
controls.hover = false;
|
controlsElement.hover = false;
|
||||||
} // Show, then hide after a timeout unless another control event occurs
|
} // Show, then hide after a timeout unless another control event occurs
|
||||||
|
|
||||||
|
|
||||||
@ -4807,15 +4798,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
timers.controls = setTimeout(function () {
|
timers.controls = setTimeout(function () {
|
||||||
return ui.toggleControls.call(player, false);
|
return ui.toggleControls.call(player, false);
|
||||||
}, delay);
|
}, delay);
|
||||||
}); // Force edge to repaint on exit fullscreen
|
}); // Set a gutter for Vimeo
|
||||||
// TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen
|
|
||||||
|
|
||||||
/* if (browser.isEdge) {
|
|
||||||
on.call(player, elements.container, 'exitfullscreen', () => {
|
|
||||||
setTimeout(() => repaint(elements.container), 100);
|
|
||||||
});
|
|
||||||
} */
|
|
||||||
// Set a gutter for Vimeo
|
|
||||||
|
|
||||||
var setGutter = function setGutter(ratio, padding, toggle) {
|
var setGutter = function setGutter(ratio, padding, toggle) {
|
||||||
if (!player.isVimeo) {
|
if (!player.isVimeo) {
|
||||||
@ -4850,16 +4833,21 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var resized = function resized() {
|
var resized = function resized() {
|
||||||
window.clearTimeout(timers.resized);
|
clearTimeout(timers.resized);
|
||||||
timers.resized = window.setTimeout(setPlayerSize, 50);
|
timers.resized = setTimeout(setPlayerSize, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) {
|
on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) {
|
||||||
var _player$fullscreen = player.fullscreen,
|
var _player$fullscreen = player.fullscreen,
|
||||||
target = _player$fullscreen.target,
|
target = _player$fullscreen.target,
|
||||||
usingNative = _player$fullscreen.usingNative; // Ignore for iOS native
|
usingNative = _player$fullscreen.usingNative; // Ignore events not from target
|
||||||
|
|
||||||
if (!player.isEmbed || target !== elements.container) {
|
if (target !== elements.container) {
|
||||||
|
return;
|
||||||
|
} // If it's not an embed and no ratio specified
|
||||||
|
|
||||||
|
|
||||||
|
if (!player.isEmbed && is$1.empty(player.config.ratio)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5253,7 +5241,6 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
|
|
||||||
this.bind(elements.controls, 'focusin', function () {
|
this.bind(elements.controls, 'focusin', function () {
|
||||||
var config = player.config,
|
var config = player.config,
|
||||||
elements = player.elements,
|
|
||||||
timers = player.timers; // Skip transition to prevent focus from scrolling the parent element
|
timers = player.timers; // Skip transition to prevent focus from scrolling the parent element
|
||||||
|
|
||||||
toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle
|
toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle
|
||||||
@ -5995,23 +5982,22 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
if (is$1.object(window.YT) && is$1.function(window.YT.Player)) {
|
if (is$1.object(window.YT) && is$1.function(window.YT.Player)) {
|
||||||
youtube.ready.call(this);
|
youtube.ready.call(this);
|
||||||
} else {
|
} else {
|
||||||
// Load the API
|
// Reference current global callback
|
||||||
loadScript(this.config.urls.youtube.sdk).catch(function (error) {
|
var callback = window.onYouTubeIframeAPIReady; // Set callback to process queue
|
||||||
_this.debug.warn('YouTube API failed to load', error);
|
|
||||||
}); // Setup callback for the API
|
|
||||||
// YouTube has it's own system of course...
|
|
||||||
|
|
||||||
window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue
|
|
||||||
|
|
||||||
window.onYouTubeReadyCallbacks.push(function () {
|
|
||||||
youtube.ready.call(_this);
|
|
||||||
}); // Set callback to process queue
|
|
||||||
|
|
||||||
window.onYouTubeIframeAPIReady = function () {
|
window.onYouTubeIframeAPIReady = function () {
|
||||||
window.onYouTubeReadyCallbacks.forEach(function (callback) {
|
// Call global callback if set
|
||||||
|
if (is$1.function(callback)) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
youtube.ready.call(_this);
|
||||||
|
}; // Load the SDK
|
||||||
|
|
||||||
|
|
||||||
|
loadScript(this.config.urls.youtube.sdk).catch(function (error) {
|
||||||
|
_this.debug.warn('YouTube API failed to load', error);
|
||||||
});
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Get the media title
|
// Get the media title
|
||||||
@ -6041,7 +6027,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
ready: function ready() {
|
ready: function ready() {
|
||||||
var player = this; // Ignore already setup (race condition)
|
var player = this; // Ignore already setup (race condition)
|
||||||
|
|
||||||
var currentId = player.media.getAttribute('id');
|
var currentId = player.media && player.media.getAttribute('id');
|
||||||
|
|
||||||
if (!is$1.empty(currentId) && currentId.startsWith('youtube-')) {
|
if (!is$1.empty(currentId) && currentId.startsWith('youtube-')) {
|
||||||
return;
|
return;
|
||||||
@ -6066,8 +6052,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
});
|
});
|
||||||
player.media = replaceElement(container, player.media); // Id to poster wrapper
|
player.media = replaceElement(container, player.media); // Id to poster wrapper
|
||||||
|
|
||||||
var posterSrc = function posterSrc(format) {
|
var posterSrc = function posterSrc(s) {
|
||||||
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(format, "default.jpg");
|
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
|
||||||
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
|
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
|
||||||
|
|
||||||
|
|
||||||
@ -6080,9 +6066,9 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}) // 360p padded 4:3. Always exists
|
}) // 360p padded 4:3. Always exists
|
||||||
.then(function (image) {
|
.then(function (image) {
|
||||||
return ui.setPoster.call(player, image.src);
|
return ui.setPoster.call(player, image.src);
|
||||||
}).then(function (posterSrc) {
|
}).then(function (src) {
|
||||||
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
|
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
|
||||||
if (!posterSrc.includes('maxres')) {
|
if (!src.includes('maxres')) {
|
||||||
player.elements.poster.style.backgroundSize = 'cover';
|
player.elements.poster.style.backgroundSize = 'cover';
|
||||||
}
|
}
|
||||||
}).catch(function () {});
|
}).catch(function () {});
|
||||||
@ -6623,8 +6609,8 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}); // Advertisement regular events
|
}); // Advertisement regular events
|
||||||
|
|
||||||
Object.keys(google.ima.AdEvent.Type).forEach(function (type) {
|
Object.keys(google.ima.AdEvent.Type).forEach(function (type) {
|
||||||
_this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) {
|
_this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (e) {
|
||||||
return _this6.onAdEvent(event);
|
return _this6.onAdEvent(e);
|
||||||
});
|
});
|
||||||
}); // Resolve our adsManager
|
}); // Resolve our adsManager
|
||||||
|
|
||||||
@ -6672,8 +6658,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
var adData = event.getAdData(); // Proxy event
|
var adData = event.getAdData(); // Proxy event
|
||||||
|
|
||||||
var dispatchEvent = function dispatchEvent(type) {
|
var dispatchEvent = function dispatchEvent(type) {
|
||||||
var event = "ads".concat(type.replace(/_/g, '').toLowerCase());
|
triggerEvent.call(_this8.player, _this8.player.media, "ads".concat(type.replace(/_/g, '').toLowerCase()));
|
||||||
triggerEvent.call(_this8.player, _this8.player.media, event);
|
|
||||||
}; // Bubble the event
|
}; // Bubble the event
|
||||||
|
|
||||||
|
|
||||||
@ -7129,7 +7114,11 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Render DOM elements
|
if (!_this.enabled) {
|
||||||
|
return;
|
||||||
|
} // Render DOM elements
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
@ -7464,6 +7453,7 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this8.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
@ -7642,10 +7632,14 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
} // Find difference between height and preview container height
|
} // Find difference between height and preview container height
|
||||||
|
|
||||||
|
|
||||||
var multiplier = this.thumbContainerHeight / frame.h;
|
var multiplier = this.thumbContainerHeight / frame.h; // eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px");
|
|
||||||
previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px");
|
previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); // eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.left = "-".concat(frame.x * multiplier, "px");
|
|
||||||
|
previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
|
previewImage.style.left = "-".concat(frame.x * multiplier, "px"); // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
previewImage.style.top = "-".concat(frame.y * multiplier, "px");
|
previewImage.style.top = "-".concat(frame.y * multiplier, "px");
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -8477,32 +8471,32 @@ typeof navigator === "object" && (function (global, factory) {
|
|||||||
}, {
|
}, {
|
||||||
key: "isHTML5",
|
key: "isHTML5",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.provider === providers.html5);
|
return this.provider === providers.html5;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isEmbed",
|
key: "isEmbed",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.isYouTube || this.isVimeo);
|
return this.isYouTube || this.isVimeo;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isYouTube",
|
key: "isYouTube",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.provider === providers.youtube);
|
return this.provider === providers.youtube;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isVimeo",
|
key: "isVimeo",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.provider === providers.vimeo);
|
return this.provider === providers.vimeo;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isVideo",
|
key: "isVideo",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.type === types.video);
|
return this.type === types.video;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isAudio",
|
key: "isAudio",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.type === types.audio);
|
return this.type === types.audio;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "playing",
|
key: "playing",
|
||||||
|
2
dist/plyr.min.js
vendored
2
dist/plyr.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js.map
vendored
2
dist/plyr.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.mjs
vendored
2
dist/plyr.min.mjs
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.mjs.map
vendored
2
dist/plyr.min.mjs.map
vendored
File diff suppressed because one or more lines are too long
312
dist/plyr.mjs
vendored
312
dist/plyr.mjs
vendored
@ -534,6 +534,49 @@ var is$1 = {
|
|||||||
empty: isEmpty$1
|
empty: isEmpty$1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
var transitionEndEvent = function () {
|
||||||
|
var element = document.createElement('span');
|
||||||
|
var events = {
|
||||||
|
WebkitTransition: 'webkitTransitionEnd',
|
||||||
|
MozTransition: 'transitionend',
|
||||||
|
OTransition: 'oTransitionEnd otransitionend',
|
||||||
|
transition: 'transitionend'
|
||||||
|
};
|
||||||
|
var type = Object.keys(events).find(function (event) {
|
||||||
|
return element.style[event] !== undefined;
|
||||||
|
});
|
||||||
|
return is$1.string(type) ? events[type] : false;
|
||||||
|
}(); // Force repaint of element
|
||||||
|
|
||||||
|
function repaint(element, delay) {
|
||||||
|
setTimeout(function () {
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
element.hidden = true; // eslint-disable-next-line no-unused-expressions
|
||||||
|
|
||||||
|
element.offsetHeight; // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
|
element.hidden = false;
|
||||||
|
} catch (e) {// Do nothing
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Browser sniffing
|
||||||
|
// Unfortunately, due to mixed support, UA sniffing is required
|
||||||
|
// ==========================================================================
|
||||||
|
var browser = {
|
||||||
|
isIE:
|
||||||
|
/* @cc_on!@ */
|
||||||
|
!!document.documentMode,
|
||||||
|
isEdge: window.navigator.userAgent.includes('Edge'),
|
||||||
|
isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
|
||||||
|
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
|
||||||
|
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform)
|
||||||
|
};
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
||||||
// https://www.youtube.com/watch?v=NPM6172J22g
|
// https://www.youtube.com/watch?v=NPM6172J22g
|
||||||
@ -897,13 +940,10 @@ function toggleHidden(element, hidden) {
|
|||||||
|
|
||||||
if (!is$1.boolean(hide)) {
|
if (!is$1.boolean(hide)) {
|
||||||
hide = !element.hidden;
|
hide = !element.hidden;
|
||||||
}
|
} // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
if (hide) {
|
|
||||||
element.setAttribute('hidden', '');
|
element.hidden = hide;
|
||||||
} else {
|
|
||||||
element.removeAttribute('hidden');
|
|
||||||
}
|
|
||||||
} // Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
} // Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
||||||
|
|
||||||
function toggleClass(element, className, force) {
|
function toggleClass(element, className, force) {
|
||||||
@ -937,8 +977,8 @@ function matches$1(element, selector) {
|
|||||||
return Array.from(document.querySelectorAll(selector)).includes(this);
|
return Array.from(document.querySelectorAll(selector)).includes(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = match;
|
var method = match;
|
||||||
return matches.call(element, selector);
|
return method.call(element, selector);
|
||||||
} // Find all elements
|
} // Find all elements
|
||||||
|
|
||||||
function getElements(selector) {
|
function getElements(selector) {
|
||||||
@ -1002,47 +1042,6 @@ function setFocus() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
|
||||||
var transitionEndEvent = function () {
|
|
||||||
var element = document.createElement('span');
|
|
||||||
var events = {
|
|
||||||
WebkitTransition: 'webkitTransitionEnd',
|
|
||||||
MozTransition: 'transitionend',
|
|
||||||
OTransition: 'oTransitionEnd otransitionend',
|
|
||||||
transition: 'transitionend'
|
|
||||||
};
|
|
||||||
var type = Object.keys(events).find(function (event) {
|
|
||||||
return element.style[event] !== undefined;
|
|
||||||
});
|
|
||||||
return is$1.string(type) ? events[type] : false;
|
|
||||||
}(); // Force repaint of element
|
|
||||||
|
|
||||||
function repaint(element) {
|
|
||||||
setTimeout(function () {
|
|
||||||
try {
|
|
||||||
toggleHidden(element, true);
|
|
||||||
element.offsetHeight; // eslint-disable-line
|
|
||||||
|
|
||||||
toggleHidden(element, false);
|
|
||||||
} catch (e) {// Do nothing
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================================
|
|
||||||
// Browser sniffing
|
|
||||||
// Unfortunately, due to mixed support, UA sniffing is required
|
|
||||||
// ==========================================================================
|
|
||||||
var browser = {
|
|
||||||
isIE:
|
|
||||||
/* @cc_on!@ */
|
|
||||||
!!document.documentMode,
|
|
||||||
isEdge: window.navigator.userAgent.includes('Edge'),
|
|
||||||
isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
|
|
||||||
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
|
|
||||||
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform)
|
|
||||||
};
|
|
||||||
|
|
||||||
var defaultCodecs = {
|
var defaultCodecs = {
|
||||||
'audio/ogg': 'vorbis',
|
'audio/ogg': 'vorbis',
|
||||||
'audio/wav': '1',
|
'audio/wav': '1',
|
||||||
@ -1166,12 +1165,8 @@ function reduceAspectRatio(ratio) {
|
|||||||
}
|
}
|
||||||
function getAspectRatio(input) {
|
function getAspectRatio(input) {
|
||||||
var parse = function parse(ratio) {
|
var parse = function parse(ratio) {
|
||||||
if (!validateRatio(ratio)) {
|
return validateRatio(ratio) ? ratio.split(':').map(Number) : null;
|
||||||
return null;
|
}; // Try provided ratio
|
||||||
}
|
|
||||||
|
|
||||||
return ratio.split(':').map(Number);
|
|
||||||
}; // Provided ratio
|
|
||||||
|
|
||||||
|
|
||||||
var ratio = parse(input); // Get from config
|
var ratio = parse(input); // Get from config
|
||||||
@ -1258,16 +1253,19 @@ var html5 = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var player = this; // Set aspect ratio if set
|
var player = this; // Set aspect ratio if fixed
|
||||||
|
|
||||||
|
if (!is$1.empty(this.config.ratio)) {
|
||||||
|
setAspectRatio.call(player);
|
||||||
|
} // Quality
|
||||||
|
|
||||||
setAspectRatio.call(player); // Quality
|
|
||||||
|
|
||||||
Object.defineProperty(player.media, 'quality', {
|
Object.defineProperty(player.media, 'quality', {
|
||||||
get: function get() {
|
get: function get() {
|
||||||
// Get sources
|
// Get sources
|
||||||
var sources = html5.getSources.call(player);
|
var sources = html5.getSources.call(player);
|
||||||
var source = sources.find(function (source) {
|
var source = sources.find(function (s) {
|
||||||
return source.getAttribute('src') === player.source;
|
return s.getAttribute('src') === player.source;
|
||||||
}); // Return size, if match is found
|
}); // Return size, if match is found
|
||||||
|
|
||||||
return source && Number(source.getAttribute('size'));
|
return source && Number(source.getAttribute('size'));
|
||||||
@ -1276,8 +1274,8 @@ var html5 = {
|
|||||||
// Get sources
|
// Get sources
|
||||||
var sources = html5.getSources.call(player); // Get first match for requested size
|
var sources = html5.getSources.call(player); // Get first match for requested size
|
||||||
|
|
||||||
var source = sources.find(function (source) {
|
var source = sources.find(function (s) {
|
||||||
return Number(source.getAttribute('size')) === input;
|
return Number(s.getAttribute('size')) === input;
|
||||||
}); // No matching source found
|
}); // No matching source found
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
@ -1467,10 +1465,10 @@ var i18n = {
|
|||||||
};
|
};
|
||||||
Object.entries(replace).forEach(function (_ref) {
|
Object.entries(replace).forEach(function (_ref) {
|
||||||
var _ref2 = _slicedToArray(_ref, 2),
|
var _ref2 = _slicedToArray(_ref, 2),
|
||||||
key = _ref2[0],
|
k = _ref2[0],
|
||||||
value = _ref2[1];
|
v = _ref2[1];
|
||||||
|
|
||||||
string = replaceAll(string, key, value);
|
string = replaceAll(string, k, v);
|
||||||
});
|
});
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
@ -1605,6 +1603,7 @@ function loadSprite(url, id) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var update = function update(container, data) {
|
var update = function update(container, data) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
container.innerHTML = data; // Check again incase of race condition
|
container.innerHTML = data; // Check again incase of race condition
|
||||||
|
|
||||||
if (hasId && exists()) {
|
if (hasId && exists()) {
|
||||||
@ -2079,9 +2078,9 @@ var controls = {
|
|||||||
get: function get() {
|
get: function get() {
|
||||||
return menuItem.getAttribute('aria-checked') === 'true';
|
return menuItem.getAttribute('aria-checked') === 'true';
|
||||||
},
|
},
|
||||||
set: function set(checked) {
|
set: function set(check) {
|
||||||
// Ensure exclusivity
|
// Ensure exclusivity
|
||||||
if (checked) {
|
if (check) {
|
||||||
Array.from(menuItem.parentNode.children).filter(function (node) {
|
Array.from(menuItem.parentNode.children).filter(function (node) {
|
||||||
return matches$1(node, '[role="menuitemradio"]');
|
return matches$1(node, '[role="menuitemradio"]');
|
||||||
}).forEach(function (node) {
|
}).forEach(function (node) {
|
||||||
@ -2089,7 +2088,7 @@ var controls = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');
|
menuItem.setAttribute('aria-checked', check ? 'true' : 'false');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.listeners.bind(menuItem, 'click keyup', function (event) {
|
this.listeners.bind(menuItem, 'click keyup', function (event) {
|
||||||
@ -2191,16 +2190,16 @@ var controls = {
|
|||||||
var value = 0;
|
var value = 0;
|
||||||
|
|
||||||
var setProgress = function setProgress(target, input) {
|
var setProgress = function setProgress(target, input) {
|
||||||
var value = is$1.number(input) ? input : 0;
|
var val = is$1.number(input) ? input : 0;
|
||||||
var progress = is$1.element(target) ? target : _this4.elements.display.buffer; // Update value and label
|
var progress = is$1.element(target) ? target : _this4.elements.display.buffer; // Update value and label
|
||||||
|
|
||||||
if (is$1.element(progress)) {
|
if (is$1.element(progress)) {
|
||||||
progress.value = value; // Update text label inside
|
progress.value = val; // Update text label inside
|
||||||
|
|
||||||
var label = progress.getElementsByTagName('span')[0];
|
var label = progress.getElementsByTagName('span')[0];
|
||||||
|
|
||||||
if (is$1.element(label)) {
|
if (is$1.element(label)) {
|
||||||
label.childNodes[0].nodeValue = value;
|
label.childNodes[0].nodeValue = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2269,15 +2268,12 @@ var controls = {
|
|||||||
// Bail if setting not true
|
// Bail if setting not true
|
||||||
if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) {
|
if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) {
|
||||||
return;
|
return;
|
||||||
} // Calculate percentage
|
}
|
||||||
|
|
||||||
|
|
||||||
var percent = 0;
|
|
||||||
var clientRect = this.elements.progress.getBoundingClientRect();
|
|
||||||
var visible = "".concat(this.config.classNames.tooltip, "--visible");
|
var visible = "".concat(this.config.classNames.tooltip, "--visible");
|
||||||
|
|
||||||
var toggle = function toggle(_toggle) {
|
var toggle = function toggle(show) {
|
||||||
toggleClass(_this5.elements.display.seekTooltip, visible, _toggle);
|
return toggleClass(_this5.elements.display.seekTooltip, visible, show);
|
||||||
}; // Hide on touch
|
}; // Hide on touch
|
||||||
|
|
||||||
|
|
||||||
@ -2287,6 +2283,9 @@ var controls = {
|
|||||||
} // Determine percentage, if already visible
|
} // Determine percentage, if already visible
|
||||||
|
|
||||||
|
|
||||||
|
var percent = 0;
|
||||||
|
var clientRect = this.elements.progress.getBoundingClientRect();
|
||||||
|
|
||||||
if (is$1.event(event)) {
|
if (is$1.event(event)) {
|
||||||
percent = 100 / clientRect.width * (event.pageX - clientRect.left);
|
percent = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||||
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
||||||
@ -2647,8 +2646,8 @@ var controls = {
|
|||||||
var target = pane;
|
var target = pane;
|
||||||
|
|
||||||
if (!is$1.element(target)) {
|
if (!is$1.element(target)) {
|
||||||
target = Object.values(this.elements.settings.panels).find(function (pane) {
|
target = Object.values(this.elements.settings.panels).find(function (p) {
|
||||||
return !pane.hidden;
|
return !p.hidden;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2903,17 +2902,15 @@ var controls = {
|
|||||||
|
|
||||||
|
|
||||||
if (control === 'settings' && !is$1.empty(_this10.config.settings)) {
|
if (control === 'settings' && !is$1.empty(_this10.config.settings)) {
|
||||||
var _control = createElement('div', extend({}, defaultAttributes, {
|
var wrapper = createElement('div', extend({}, defaultAttributes, {
|
||||||
class: "".concat(defaultAttributes.class, " plyr__menu").trim(),
|
class: "".concat(defaultAttributes.class, " plyr__menu").trim(),
|
||||||
hidden: ''
|
hidden: ''
|
||||||
}));
|
}));
|
||||||
|
wrapper.appendChild(createButton.call(_this10, 'settings', {
|
||||||
_control.appendChild(createButton.call(_this10, 'settings', {
|
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
'aria-controls': "plyr-settings-".concat(data.id),
|
'aria-controls': "plyr-settings-".concat(data.id),
|
||||||
'aria-expanded': false
|
'aria-expanded': false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var popup = createElement('div', {
|
var popup = createElement('div', {
|
||||||
class: 'plyr__menu__container',
|
class: 'plyr__menu__container',
|
||||||
id: "plyr-settings-".concat(data.id),
|
id: "plyr-settings-".concat(data.id),
|
||||||
@ -3002,12 +2999,10 @@ var controls = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
popup.appendChild(inner);
|
popup.appendChild(inner);
|
||||||
|
wrapper.appendChild(popup);
|
||||||
_control.appendChild(popup);
|
container.appendChild(wrapper);
|
||||||
|
|
||||||
container.appendChild(_control);
|
|
||||||
_this10.elements.settings.popup = popup;
|
_this10.elements.settings.popup = popup;
|
||||||
_this10.elements.settings.menu = _control;
|
_this10.elements.settings.menu = wrapper;
|
||||||
} // Picture in picture button
|
} // Picture in picture button
|
||||||
|
|
||||||
|
|
||||||
@ -3338,6 +3333,7 @@ var captions = {
|
|||||||
meta.set(track, {
|
meta.set(track, {
|
||||||
default: track.mode === 'showing'
|
default: track.mode === 'showing'
|
||||||
}); // Turn off native caption rendering to avoid double captions
|
}); // Turn off native caption rendering to avoid double captions
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
track.mode = 'hidden'; // Add event listener for cue changes
|
track.mode = 'hidden'; // Add event listener for cue changes
|
||||||
|
|
||||||
@ -3519,8 +3515,8 @@ var captions = {
|
|||||||
});
|
});
|
||||||
var track;
|
var track;
|
||||||
languages.every(function (language) {
|
languages.every(function (language) {
|
||||||
track = sorted.find(function (track) {
|
track = sorted.find(function (t) {
|
||||||
return track.language === language;
|
return t.language === language;
|
||||||
});
|
});
|
||||||
return !track; // Break iteration if there is a match
|
return !track; // Break iteration if there is a match
|
||||||
}); // If no match is found but is required, get first
|
}); // If no match is found but is required, get first
|
||||||
@ -3699,7 +3695,8 @@ var defaults$1 = {
|
|||||||
controls: ['play-large', // 'restart',
|
controls: ['play-large', // 'restart',
|
||||||
// 'rewind',
|
// 'rewind',
|
||||||
'play', // 'fast-forward',
|
'play', // 'fast-forward',
|
||||||
'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download',
|
'progress', 'current-time', // 'duration',
|
||||||
|
'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', // 'download',
|
||||||
'fullscreen'],
|
'fullscreen'],
|
||||||
settings: ['captions', 'quality', 'speed'],
|
settings: ['captions', 'quality', 'speed'],
|
||||||
// Localisation
|
// Localisation
|
||||||
@ -3757,8 +3754,7 @@ var defaults$1 = {
|
|||||||
},
|
},
|
||||||
youtube: {
|
youtube: {
|
||||||
sdk: 'https://www.youtube.com/iframe_api',
|
sdk: 'https://www.youtube.com/iframe_api',
|
||||||
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}' // 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title),fileDetails)&part=snippet',
|
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}'
|
||||||
|
|
||||||
},
|
},
|
||||||
googleIMA: {
|
googleIMA: {
|
||||||
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'
|
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'
|
||||||
@ -4043,8 +4039,6 @@ function onChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleFallback() {
|
function toggleFallback() {
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
||||||
|
|
||||||
// Store or restore scroll position
|
// Store or restore scroll position
|
||||||
@ -4084,12 +4078,7 @@ function toggleFallback() {
|
|||||||
viewport.content = viewport.content.split(',').filter(function (part) {
|
viewport.content = viewport.content.split(',').filter(function (part) {
|
||||||
return part.trim() !== property;
|
return part.trim() !== property;
|
||||||
}).join(',');
|
}).join(',');
|
||||||
} // Force a repaint as sometimes Safari doesn't want to fill the screen
|
}
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
return repaint(_this.target);
|
|
||||||
}, 100);
|
|
||||||
} // Toggle button and fire events
|
} // Toggle button and fire events
|
||||||
|
|
||||||
|
|
||||||
@ -4100,7 +4089,7 @@ var Fullscreen =
|
|||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
function () {
|
function () {
|
||||||
function Fullscreen(player) {
|
function Fullscreen(player) {
|
||||||
var _this2 = this;
|
var _this = this;
|
||||||
|
|
||||||
_classCallCheck(this, Fullscreen);
|
_classCallCheck(this, Fullscreen);
|
||||||
|
|
||||||
@ -4120,16 +4109,16 @@ function () {
|
|||||||
|
|
||||||
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
|
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
|
||||||
// TODO: Filter for target??
|
// TODO: Filter for target??
|
||||||
onChange.call(_this2);
|
onChange.call(_this);
|
||||||
}); // Fullscreen toggle on double click
|
}); // Fullscreen toggle on double click
|
||||||
|
|
||||||
on.call(this.player, this.player.elements.container, 'dblclick', function (event) {
|
on.call(this.player, this.player.elements.container, 'dblclick', function (event) {
|
||||||
// Ignore double click in controls
|
// Ignore double click in controls
|
||||||
if (is$1.element(_this2.player.elements.controls) && _this2.player.elements.controls.contains(event.target)) {
|
if (is$1.element(_this.player.elements.controls) && _this.player.elements.controls.contains(event.target)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_this2.toggle();
|
_this.toggle();
|
||||||
}); // Update the UI
|
}); // Update the UI
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
@ -4477,7 +4466,9 @@ var ui = {
|
|||||||
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state
|
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state
|
||||||
|
|
||||||
Array.from(this.elements.buttons.play || []).forEach(function (target) {
|
Array.from(this.elements.buttons.play || []).forEach(function (target) {
|
||||||
target.pressed = _this3.playing;
|
Object.assign(target, {
|
||||||
|
pressed: _this3.playing
|
||||||
|
});
|
||||||
}); // Only update controls on non timeupdate events
|
}); // Only update controls on non timeupdate events
|
||||||
|
|
||||||
if (is$1.event(event) && event.type === 'timeupdate') {
|
if (is$1.event(event) && event.type === 'timeupdate') {
|
||||||
@ -4504,13 +4495,13 @@ var ui = {
|
|||||||
},
|
},
|
||||||
// Toggle controls based on state and `force` argument
|
// Toggle controls based on state and `force` argument
|
||||||
toggleControls: function toggleControls(force) {
|
toggleControls: function toggleControls(force) {
|
||||||
var controls = this.elements.controls;
|
var controlsElement = this.elements.controls;
|
||||||
|
|
||||||
if (controls && this.config.hideControls) {
|
if (controlsElement && this.config.hideControls) {
|
||||||
// Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)
|
// Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)
|
||||||
var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide
|
var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide
|
||||||
|
|
||||||
this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek));
|
this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -4778,11 +4769,11 @@ function () {
|
|||||||
|
|
||||||
|
|
||||||
on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) {
|
on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) {
|
||||||
var controls = elements.controls; // Remove button states for fullscreen
|
var controlsElement = elements.controls; // Remove button states for fullscreen
|
||||||
|
|
||||||
if (controls && event.type === 'enterfullscreen') {
|
if (controlsElement && event.type === 'enterfullscreen') {
|
||||||
controls.pressed = false;
|
controlsElement.pressed = false;
|
||||||
controls.hover = false;
|
controlsElement.hover = false;
|
||||||
} // Show, then hide after a timeout unless another control event occurs
|
} // Show, then hide after a timeout unless another control event occurs
|
||||||
|
|
||||||
|
|
||||||
@ -4801,15 +4792,7 @@ function () {
|
|||||||
timers.controls = setTimeout(function () {
|
timers.controls = setTimeout(function () {
|
||||||
return ui.toggleControls.call(player, false);
|
return ui.toggleControls.call(player, false);
|
||||||
}, delay);
|
}, delay);
|
||||||
}); // Force edge to repaint on exit fullscreen
|
}); // Set a gutter for Vimeo
|
||||||
// TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen
|
|
||||||
|
|
||||||
/* if (browser.isEdge) {
|
|
||||||
on.call(player, elements.container, 'exitfullscreen', () => {
|
|
||||||
setTimeout(() => repaint(elements.container), 100);
|
|
||||||
});
|
|
||||||
} */
|
|
||||||
// Set a gutter for Vimeo
|
|
||||||
|
|
||||||
var setGutter = function setGutter(ratio, padding, toggle) {
|
var setGutter = function setGutter(ratio, padding, toggle) {
|
||||||
if (!player.isVimeo) {
|
if (!player.isVimeo) {
|
||||||
@ -4844,16 +4827,21 @@ function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var resized = function resized() {
|
var resized = function resized() {
|
||||||
window.clearTimeout(timers.resized);
|
clearTimeout(timers.resized);
|
||||||
timers.resized = window.setTimeout(setPlayerSize, 50);
|
timers.resized = setTimeout(setPlayerSize, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) {
|
on.call(player, elements.container, 'enterfullscreen exitfullscreen', function (event) {
|
||||||
var _player$fullscreen = player.fullscreen,
|
var _player$fullscreen = player.fullscreen,
|
||||||
target = _player$fullscreen.target,
|
target = _player$fullscreen.target,
|
||||||
usingNative = _player$fullscreen.usingNative; // Ignore for iOS native
|
usingNative = _player$fullscreen.usingNative; // Ignore events not from target
|
||||||
|
|
||||||
if (!player.isEmbed || target !== elements.container) {
|
if (target !== elements.container) {
|
||||||
|
return;
|
||||||
|
} // If it's not an embed and no ratio specified
|
||||||
|
|
||||||
|
|
||||||
|
if (!player.isEmbed && is$1.empty(player.config.ratio)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5247,7 +5235,6 @@ function () {
|
|||||||
|
|
||||||
this.bind(elements.controls, 'focusin', function () {
|
this.bind(elements.controls, 'focusin', function () {
|
||||||
var config = player.config,
|
var config = player.config,
|
||||||
elements = player.elements,
|
|
||||||
timers = player.timers; // Skip transition to prevent focus from scrolling the parent element
|
timers = player.timers; // Skip transition to prevent focus from scrolling the parent element
|
||||||
|
|
||||||
toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle
|
toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle
|
||||||
@ -5989,23 +5976,22 @@ var youtube = {
|
|||||||
if (is$1.object(window.YT) && is$1.function(window.YT.Player)) {
|
if (is$1.object(window.YT) && is$1.function(window.YT.Player)) {
|
||||||
youtube.ready.call(this);
|
youtube.ready.call(this);
|
||||||
} else {
|
} else {
|
||||||
// Load the API
|
// Reference current global callback
|
||||||
loadScript(this.config.urls.youtube.sdk).catch(function (error) {
|
var callback = window.onYouTubeIframeAPIReady; // Set callback to process queue
|
||||||
_this.debug.warn('YouTube API failed to load', error);
|
|
||||||
}); // Setup callback for the API
|
|
||||||
// YouTube has it's own system of course...
|
|
||||||
|
|
||||||
window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || []; // Add to queue
|
|
||||||
|
|
||||||
window.onYouTubeReadyCallbacks.push(function () {
|
|
||||||
youtube.ready.call(_this);
|
|
||||||
}); // Set callback to process queue
|
|
||||||
|
|
||||||
window.onYouTubeIframeAPIReady = function () {
|
window.onYouTubeIframeAPIReady = function () {
|
||||||
window.onYouTubeReadyCallbacks.forEach(function (callback) {
|
// Call global callback if set
|
||||||
|
if (is$1.function(callback)) {
|
||||||
callback();
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
youtube.ready.call(_this);
|
||||||
|
}; // Load the SDK
|
||||||
|
|
||||||
|
|
||||||
|
loadScript(this.config.urls.youtube.sdk).catch(function (error) {
|
||||||
|
_this.debug.warn('YouTube API failed to load', error);
|
||||||
});
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Get the media title
|
// Get the media title
|
||||||
@ -6035,7 +6021,7 @@ var youtube = {
|
|||||||
ready: function ready() {
|
ready: function ready() {
|
||||||
var player = this; // Ignore already setup (race condition)
|
var player = this; // Ignore already setup (race condition)
|
||||||
|
|
||||||
var currentId = player.media.getAttribute('id');
|
var currentId = player.media && player.media.getAttribute('id');
|
||||||
|
|
||||||
if (!is$1.empty(currentId) && currentId.startsWith('youtube-')) {
|
if (!is$1.empty(currentId) && currentId.startsWith('youtube-')) {
|
||||||
return;
|
return;
|
||||||
@ -6060,8 +6046,8 @@ var youtube = {
|
|||||||
});
|
});
|
||||||
player.media = replaceElement(container, player.media); // Id to poster wrapper
|
player.media = replaceElement(container, player.media); // Id to poster wrapper
|
||||||
|
|
||||||
var posterSrc = function posterSrc(format) {
|
var posterSrc = function posterSrc(s) {
|
||||||
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(format, "default.jpg");
|
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
|
||||||
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
|
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
|
||||||
|
|
||||||
|
|
||||||
@ -6074,9 +6060,9 @@ var youtube = {
|
|||||||
}) // 360p padded 4:3. Always exists
|
}) // 360p padded 4:3. Always exists
|
||||||
.then(function (image) {
|
.then(function (image) {
|
||||||
return ui.setPoster.call(player, image.src);
|
return ui.setPoster.call(player, image.src);
|
||||||
}).then(function (posterSrc) {
|
}).then(function (src) {
|
||||||
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
|
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
|
||||||
if (!posterSrc.includes('maxres')) {
|
if (!src.includes('maxres')) {
|
||||||
player.elements.poster.style.backgroundSize = 'cover';
|
player.elements.poster.style.backgroundSize = 'cover';
|
||||||
}
|
}
|
||||||
}).catch(function () {});
|
}).catch(function () {});
|
||||||
@ -6617,8 +6603,8 @@ function () {
|
|||||||
}); // Advertisement regular events
|
}); // Advertisement regular events
|
||||||
|
|
||||||
Object.keys(google.ima.AdEvent.Type).forEach(function (type) {
|
Object.keys(google.ima.AdEvent.Type).forEach(function (type) {
|
||||||
_this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) {
|
_this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (e) {
|
||||||
return _this6.onAdEvent(event);
|
return _this6.onAdEvent(e);
|
||||||
});
|
});
|
||||||
}); // Resolve our adsManager
|
}); // Resolve our adsManager
|
||||||
|
|
||||||
@ -6666,8 +6652,7 @@ function () {
|
|||||||
var adData = event.getAdData(); // Proxy event
|
var adData = event.getAdData(); // Proxy event
|
||||||
|
|
||||||
var dispatchEvent = function dispatchEvent(type) {
|
var dispatchEvent = function dispatchEvent(type) {
|
||||||
var event = "ads".concat(type.replace(/_/g, '').toLowerCase());
|
triggerEvent.call(_this8.player, _this8.player.media, "ads".concat(type.replace(/_/g, '').toLowerCase()));
|
||||||
triggerEvent.call(_this8.player, _this8.player.media, event);
|
|
||||||
}; // Bubble the event
|
}; // Bubble the event
|
||||||
|
|
||||||
|
|
||||||
@ -7123,7 +7108,11 @@ function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(function () {
|
this.getThumbnails().then(function () {
|
||||||
// Render DOM elements
|
if (!_this.enabled) {
|
||||||
|
return;
|
||||||
|
} // Render DOM elements
|
||||||
|
|
||||||
|
|
||||||
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
_this.render(); // Check to see if thumb container size was specified manually in CSS
|
||||||
|
|
||||||
|
|
||||||
@ -7458,6 +7447,7 @@ function () {
|
|||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
|
|
||||||
var currentImageContainer = _this8.currentImageContainer;
|
var currentImageContainer = _this8.currentImageContainer;
|
||||||
@ -7636,10 +7626,14 @@ function () {
|
|||||||
} // Find difference between height and preview container height
|
} // Find difference between height and preview container height
|
||||||
|
|
||||||
|
|
||||||
var multiplier = this.thumbContainerHeight / frame.h;
|
var multiplier = this.thumbContainerHeight / frame.h; // eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px");
|
|
||||||
previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px");
|
previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); // eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.left = "-".concat(frame.x * multiplier, "px");
|
|
||||||
|
previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
|
previewImage.style.left = "-".concat(frame.x * multiplier, "px"); // eslint-disable-next-line no-param-reassign
|
||||||
|
|
||||||
previewImage.style.top = "-".concat(frame.y * multiplier, "px");
|
previewImage.style.top = "-".concat(frame.y * multiplier, "px");
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -8471,32 +8465,32 @@ function () {
|
|||||||
}, {
|
}, {
|
||||||
key: "isHTML5",
|
key: "isHTML5",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.provider === providers.html5);
|
return this.provider === providers.html5;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isEmbed",
|
key: "isEmbed",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.isYouTube || this.isVimeo);
|
return this.isYouTube || this.isVimeo;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isYouTube",
|
key: "isYouTube",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.provider === providers.youtube);
|
return this.provider === providers.youtube;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isVimeo",
|
key: "isVimeo",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.provider === providers.vimeo);
|
return this.provider === providers.vimeo;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isVideo",
|
key: "isVideo",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.type === types.video);
|
return this.type === types.video;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "isAudio",
|
key: "isAudio",
|
||||||
get: function get() {
|
get: function get() {
|
||||||
return Boolean(this.type === types.audio);
|
return this.type === types.audio;
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "playing",
|
key: "playing",
|
||||||
|
2173
dist/plyr.polyfilled.js
vendored
2173
dist/plyr.polyfilled.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/plyr.polyfilled.min.js
vendored
2
dist/plyr.polyfilled.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js.map
vendored
2
dist/plyr.polyfilled.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.mjs
vendored
2
dist/plyr.polyfilled.min.mjs
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.mjs.map
vendored
2
dist/plyr.polyfilled.min.mjs.map
vendored
File diff suppressed because one or more lines are too long
2175
dist/plyr.polyfilled.mjs
vendored
2175
dist/plyr.polyfilled.mjs
vendored
File diff suppressed because it is too large
Load Diff
49
gulpfile.js
49
gulpfile.js
@ -6,24 +6,28 @@
|
|||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
|
// ------------------------------------
|
||||||
// JavaScript
|
// JavaScript
|
||||||
|
// ------------------------------------
|
||||||
const terser = require('gulp-terser');
|
const terser = require('gulp-terser');
|
||||||
const rollup = require('gulp-better-rollup');
|
const rollup = require('gulp-better-rollup');
|
||||||
const babel = require('rollup-plugin-babel');
|
const babel = require('rollup-plugin-babel');
|
||||||
const commonjs = require('rollup-plugin-commonjs');
|
const commonjs = require('rollup-plugin-commonjs');
|
||||||
const resolve = require('rollup-plugin-node-resolve');
|
const resolve = require('rollup-plugin-node-resolve');
|
||||||
|
// ------------------------------------
|
||||||
// CSS
|
// CSS
|
||||||
|
// ------------------------------------
|
||||||
const sass = require('gulp-sass');
|
const sass = require('gulp-sass');
|
||||||
const clean = require('gulp-clean-css');
|
const clean = require('gulp-clean-css');
|
||||||
const prefix = require('gulp-autoprefixer');
|
const prefix = require('gulp-autoprefixer');
|
||||||
|
// ------------------------------------
|
||||||
// Images
|
// Images
|
||||||
|
// ------------------------------------
|
||||||
const svgstore = require('gulp-svgstore');
|
const svgstore = require('gulp-svgstore');
|
||||||
const imagemin = require('gulp-imagemin');
|
const imagemin = require('gulp-imagemin');
|
||||||
|
// ------------------------------------
|
||||||
// Utils
|
// Utils
|
||||||
|
// ------------------------------------
|
||||||
const del = require('del');
|
const del = require('del');
|
||||||
const filter = require('gulp-filter');
|
const filter = require('gulp-filter');
|
||||||
const header = require('gulp-header');
|
const header = require('gulp-header');
|
||||||
@ -37,18 +41,22 @@ const plumber = require('gulp-plumber');
|
|||||||
const size = require('gulp-size');
|
const size = require('gulp-size');
|
||||||
const sourcemaps = require('gulp-sourcemaps');
|
const sourcemaps = require('gulp-sourcemaps');
|
||||||
const through = require('through2');
|
const through = require('through2');
|
||||||
|
// ------------------------------------
|
||||||
// Deployment
|
// Deployment
|
||||||
|
// ------------------------------------
|
||||||
const aws = require('aws-sdk');
|
const aws = require('aws-sdk');
|
||||||
const publish = require('gulp-awspublish');
|
const publish = require('gulp-awspublish');
|
||||||
const FastlyPurge = require('fastly-purge');
|
const FastlyPurge = require('fastly-purge');
|
||||||
|
// ------------------------------------
|
||||||
|
// Configs
|
||||||
|
// ------------------------------------
|
||||||
const pkg = require('./package.json');
|
const pkg = require('./package.json');
|
||||||
const build = require('./build.json');
|
const build = require('./build.json');
|
||||||
const deploy = require('./deploy.json');
|
const deploy = require('./deploy.json');
|
||||||
|
// ------------------------------------
|
||||||
|
// Info from package
|
||||||
|
// ------------------------------------
|
||||||
const { browserslist: browsers, version } = pkg;
|
const { browserslist: browsers, version } = pkg;
|
||||||
|
|
||||||
const minSuffix = '.min';
|
const minSuffix = '.min';
|
||||||
|
|
||||||
// Get AWS config
|
// Get AWS config
|
||||||
@ -125,15 +133,16 @@ gulp.task(tasks.clean, done => {
|
|||||||
|
|
||||||
// JavaScript
|
// JavaScript
|
||||||
Object.entries(build.js).forEach(([filename, entry]) => {
|
Object.entries(build.js).forEach(([filename, entry]) => {
|
||||||
entry.formats.forEach(format => {
|
const { dist, formats, namespace, polyfill, src } = entry;
|
||||||
|
|
||||||
|
formats.forEach(format => {
|
||||||
const name = `js:${filename}:${format}`;
|
const name = `js:${filename}:${format}`;
|
||||||
tasks.js.push(name);
|
|
||||||
const polyfill = filename.includes('polyfilled');
|
|
||||||
const extension = format === 'es' ? 'mjs' : 'js';
|
const extension = format === 'es' ? 'mjs' : 'js';
|
||||||
|
tasks.js.push(name);
|
||||||
|
|
||||||
gulp.task(name, () =>
|
gulp.task(name, () =>
|
||||||
gulp
|
gulp
|
||||||
.src(entry.src)
|
.src(src)
|
||||||
.pipe(plumber())
|
.pipe(plumber())
|
||||||
.pipe(sourcemaps.init())
|
.pipe(sourcemaps.init())
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -159,7 +168,7 @@ Object.entries(build.js).forEach(([filename, entry]) => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: entry.namespace,
|
name: namespace,
|
||||||
format,
|
format,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -170,25 +179,26 @@ Object.entries(build.js).forEach(([filename, entry]) => {
|
|||||||
extname: `.${extension}`,
|
extname: `.${extension}`,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.pipe(gulp.dest(entry.dist))
|
.pipe(gulp.dest(dist))
|
||||||
.pipe(filter(`**/*.${extension}`))
|
.pipe(filter(`**/*.${extension}`))
|
||||||
.pipe(terser())
|
.pipe(terser())
|
||||||
.pipe(rename({ suffix: minSuffix }))
|
.pipe(rename({ suffix: minSuffix }))
|
||||||
.pipe(size(sizeOptions))
|
.pipe(size(sizeOptions))
|
||||||
.pipe(sourcemaps.write(''))
|
.pipe(sourcemaps.write(''))
|
||||||
.pipe(gulp.dest(entry.dist)),
|
.pipe(gulp.dest(dist)),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// CSS
|
// CSS
|
||||||
Object.entries(build.css).forEach(([filename, entry]) => {
|
Object.entries(build.css).forEach(([filename, entry]) => {
|
||||||
|
const { dist, src } = entry;
|
||||||
const name = `css:${filename}`;
|
const name = `css:${filename}`;
|
||||||
tasks.css.push(name);
|
tasks.css.push(name);
|
||||||
|
|
||||||
gulp.task(name, () =>
|
gulp.task(name, () =>
|
||||||
gulp
|
gulp
|
||||||
.src(entry.src)
|
.src(src)
|
||||||
.pipe(plumber())
|
.pipe(plumber())
|
||||||
.pipe(sass())
|
.pipe(sass())
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -198,24 +208,25 @@ Object.entries(build.css).forEach(([filename, entry]) => {
|
|||||||
)
|
)
|
||||||
.pipe(clean())
|
.pipe(clean())
|
||||||
.pipe(size(sizeOptions))
|
.pipe(size(sizeOptions))
|
||||||
.pipe(gulp.dest(entry.dist)),
|
.pipe(gulp.dest(dist)),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// SVG Sprites
|
// SVG Sprites
|
||||||
Object.entries(build.sprite).forEach(([filename, entry]) => {
|
Object.entries(build.sprite).forEach(([filename, entry]) => {
|
||||||
|
const { dist, src } = entry;
|
||||||
const name = `sprite:${filename}`;
|
const name = `sprite:${filename}`;
|
||||||
tasks.sprite.push(name);
|
tasks.sprite.push(name);
|
||||||
|
|
||||||
gulp.task(name, () =>
|
gulp.task(name, () =>
|
||||||
gulp
|
gulp
|
||||||
.src(entry.src)
|
.src(src)
|
||||||
.pipe(plumber())
|
.pipe(plumber())
|
||||||
.pipe(imagemin())
|
.pipe(imagemin())
|
||||||
.pipe(svgstore())
|
.pipe(svgstore())
|
||||||
.pipe(rename({ basename: path.parse(filename).name }))
|
.pipe(rename({ basename: path.parse(filename).name }))
|
||||||
.pipe(size(sizeOptions))
|
.pipe(size(sizeOptions))
|
||||||
.pipe(gulp.dest(entry.dist)),
|
.pipe(gulp.dest(dist)),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
47
package.json
47
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "plyr",
|
"name": "plyr",
|
||||||
"version": "3.5.4",
|
"version": "3.5.5",
|
||||||
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||||
"homepage": "https://plyr.io",
|
"homepage": "https://plyr.io",
|
||||||
"author": "Sam Potts <sam@potts.es>",
|
"author": "Sam Potts <sam@potts.es>",
|
||||||
@ -36,28 +36,28 @@
|
|||||||
"deploy": "yarn lint && gulp deploy"
|
"deploy": "yarn lint && gulp deploy"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ansi-colors": "^3.2.4",
|
"ansi-colors": "^4.0.1",
|
||||||
"aws-sdk": "^2.445.0",
|
"aws-sdk": "^2.478.0",
|
||||||
"@babel/core": "^7.4.4",
|
"@babel/core": "^7.4.5",
|
||||||
"@babel/preset-env": "^7.4.4",
|
"@babel/preset-env": "^7.4.5",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.2",
|
||||||
"del": "^4.1.1",
|
"del": "^4.1.1",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
"eslint-config-airbnb-base": "^13.1.0",
|
"eslint-config-airbnb-base": "^13.1.0",
|
||||||
"eslint-config-prettier": "^4.2.0",
|
"eslint-config-prettier": "^5.0.0",
|
||||||
"eslint-plugin-import": "^2.17.2",
|
"eslint-plugin-import": "^2.17.3",
|
||||||
"eslint-plugin-simple-import-sort": "^3.1.0",
|
"eslint-plugin-simple-import-sort": "^4.0.0",
|
||||||
"fancy-log": "^1.3.3",
|
"fancy-log": "^1.3.3",
|
||||||
"fastly-purge": "^1.0.1",
|
"fastly-purge": "^1.0.1",
|
||||||
"git-branch": "^2.0.1",
|
"git-branch": "^2.0.1",
|
||||||
"gulp": "^4.0.1",
|
"gulp": "^4.0.2",
|
||||||
"gulp-autoprefixer": "^6.1.0",
|
"gulp-autoprefixer": "^6.1.0",
|
||||||
"gulp-awspublish": "^4.0.0",
|
"gulp-awspublish": "^4.0.0",
|
||||||
"gulp-better-rollup": "^4.0.1",
|
"gulp-better-rollup": "^4.0.1",
|
||||||
"gulp-clean-css": "^4.2.0",
|
"gulp-clean-css": "^4.2.0",
|
||||||
"gulp-filter": "^5.1.0",
|
"gulp-filter": "^6.0.0",
|
||||||
"gulp-header": "^2.0.7",
|
"gulp-header": "^2.0.7",
|
||||||
"gulp-imagemin": "^5.0.3",
|
"gulp-imagemin": "^6.0.0",
|
||||||
"gulp-open": "^3.0.1",
|
"gulp-open": "^3.0.1",
|
||||||
"gulp-plumber": "^1.2.1",
|
"gulp-plumber": "^1.2.1",
|
||||||
"gulp-postcss": "^8.0.0",
|
"gulp-postcss": "^8.0.0",
|
||||||
@ -67,31 +67,30 @@
|
|||||||
"gulp-size": "^3.0.0",
|
"gulp-size": "^3.0.0",
|
||||||
"gulp-sourcemaps": "^2.6.5",
|
"gulp-sourcemaps": "^2.6.5",
|
||||||
"gulp-svgstore": "^7.0.1",
|
"gulp-svgstore": "^7.0.1",
|
||||||
"gulp-terser": "^1.1.7",
|
"gulp-terser": "^1.2.0",
|
||||||
"postcss-custom-properties": "^8.0.10",
|
"postcss-custom-properties": "^8.0.11",
|
||||||
"prettier-eslint": "^8.8.2",
|
"prettier-eslint": "^9.0.0",
|
||||||
"prettier-stylelint": "^0.4.2",
|
"prettier-stylelint": "^0.4.2",
|
||||||
"remark-cli": "^6.0.1",
|
"remark-cli": "^6.0.1",
|
||||||
"remark-validate-links": "^8.0.2",
|
"remark-validate-links": "^8.0.3",
|
||||||
"rollup": "^1.10.1",
|
"rollup": "^1.15.6",
|
||||||
"rollup-plugin-babel": "^4.3.2",
|
"rollup-plugin-babel": "^4.3.2",
|
||||||
"rollup-plugin-commonjs": "^9.3.4",
|
"rollup-plugin-commonjs": "^10.0.0",
|
||||||
"rollup-plugin-node-resolve": "^4.2.3",
|
"rollup-plugin-node-resolve": "^5.0.3",
|
||||||
"stylelint": "^10.0.1",
|
"stylelint": "^10.1.0",
|
||||||
"stylelint-config-prettier": "^5.1.0",
|
"stylelint-config-prettier": "^5.2.0",
|
||||||
"stylelint-config-recommended": "^2.2.0",
|
"stylelint-config-recommended": "^2.2.0",
|
||||||
"stylelint-config-sass-guidelines": "^6.0.0",
|
"stylelint-config-sass-guidelines": "^6.0.0",
|
||||||
"stylelint-order": "^3.0.0",
|
"stylelint-order": "^3.0.0",
|
||||||
"stylelint-scss": "^3.6.0",
|
"stylelint-scss": "^3.8.0",
|
||||||
"stylelint-selector-bem-pattern": "^2.1.0",
|
"stylelint-selector-bem-pattern": "^2.1.0",
|
||||||
"through2": "^3.0.1"
|
"through2": "^3.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.0.1",
|
"core-js": "^3.1.4",
|
||||||
"custom-event-polyfill": "^1.0.7",
|
"custom-event-polyfill": "^1.0.7",
|
||||||
"loadjs": "^3.6.1",
|
"loadjs": "^3.6.1",
|
||||||
"rangetouch": "^2.0.0",
|
"rangetouch": "^2.0.0",
|
||||||
"raven-js": "^3.27.0",
|
|
||||||
"url-polyfill": "^1.1.5"
|
"url-polyfill": "^1.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
"editor.tabSize": 4,
|
"editor.tabSize": 4,
|
||||||
"editor.insertSpaces": true,
|
"editor.insertSpaces": true,
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.codeActionsOnSave": {
|
|
||||||
"source.organizeImports": true
|
|
||||||
},
|
|
||||||
|
|
||||||
// Trim on save
|
// Trim on save
|
||||||
"files.trimTrailingWhitespace": true
|
"files.trimTrailingWhitespace": true
|
||||||
|
34
readme.md
34
readme.md
@ -6,13 +6,12 @@ Plyr is a simple, lightweight, accessible and customizable HTML5, YouTube and Vi
|
|||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
|
- 📼 **HTML Video & Audio, YouTube & Vimeo** - support for the major formats
|
||||||
- 💪 **Accessible** - full support for VTT captions and screen readers
|
- 💪 **Accessible** - full support for VTT captions and screen readers
|
||||||
- 🔧 **[Customisable](#html)** - make the player look how you want with the markup you want
|
- 🔧 **[Customisable](#html)** - make the player look how you want with the markup you want
|
||||||
- 😎 **Good HTML** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no
|
- 😎 **Clean HTML** - uses the _right_ elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no
|
||||||
`<span>` or `<a href="#">` button hacks
|
`<span>` or `<a href="#">` button hacks
|
||||||
- 📱 **Responsive** - works with any screen size
|
- 📱 **Responsive** - works with any screen size
|
||||||
- 📼 **HTML Video & Audio** - support for both formats
|
|
||||||
- 📺 **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback
|
|
||||||
- 💵 **[Monetization](#ads)** - make money from your videos
|
- 💵 **[Monetization](#ads)** - make money from your videos
|
||||||
- 📹 **[Streaming](#demos)** - support for hls.js, Shaka and dash.js streaming playback
|
- 📹 **[Streaming](#demos)** - support for hls.js, Shaka and dash.js streaming playback
|
||||||
- 🎛 **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API
|
- 🎛 **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API
|
||||||
@ -25,7 +24,7 @@ Plyr is a simple, lightweight, accessible and customizable HTML5, YouTube and Vi
|
|||||||
- 📖 **Multiple captions** - support for multiple caption tracks
|
- 📖 **Multiple captions** - support for multiple caption tracks
|
||||||
- 🌎 **i18n support** - support for internationalization of controls
|
- 🌎 **i18n support** - support for internationalization of controls
|
||||||
- 👌 **[Preview thumbnails](#preview-thumbnails)** - support for displaying preview thumbnails
|
- 👌 **[Preview thumbnails](#preview-thumbnails)** - support for displaying preview thumbnails
|
||||||
- 🤟 **No dependencies** - written in "vanilla" ES6 JavaScript, no jQuery required
|
- 🤟 **No frameworks** - written in "vanilla" ES6 JavaScript, no jQuery required
|
||||||
- 💁♀️ **SASS** - to include in your build processes
|
- 💁♀️ **SASS** - to include in your build processes
|
||||||
|
|
||||||
### Demos
|
### Demos
|
||||||
@ -109,7 +108,15 @@ Or the `<div>` non progressively enhanced method:
|
|||||||
|
|
||||||
## JavaScript
|
## JavaScript
|
||||||
|
|
||||||
Include the `plyr.js` script before the closing `</body>` tag and then in your JS create a new instance of Plyr as below.
|
You can use Plyr as an ES6 module as follows:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Plyr from 'plyr';
|
||||||
|
|
||||||
|
const player = new Plyr('#player');
|
||||||
|
```
|
||||||
|
|
||||||
|
Alertnatively you can include the `plyr.js` script before the closing `</body>` tag and then in your JS create a new instance of Plyr as below.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="path/to/plyr.js"></script>
|
<script src="path/to/plyr.js"></script>
|
||||||
@ -123,18 +130,18 @@ See [initialising](#initialising) for more information on advanced setups.
|
|||||||
You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build.
|
You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.plyr.io/3.5.3/plyr.js"></script>
|
<script src="https://cdn.plyr.io/3.5.4/plyr.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
...or...
|
...or...
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.plyr.io/3.5.3/plyr.polyfilled.js"></script>
|
<script src="https://cdn.plyr.io/3.5.4/plyr.polyfilled.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## CSS
|
## CSS
|
||||||
|
|
||||||
Include the `plyr.css` stylsheet into your `<head>`
|
Include the `plyr.css` stylsheet into your `<head>`.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<link rel="stylesheet" href="path/to/plyr.css" />
|
<link rel="stylesheet" href="path/to/plyr.css" />
|
||||||
@ -143,13 +150,13 @@ Include the `plyr.css` stylsheet into your `<head>`
|
|||||||
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
|
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.5.3/plyr.css" />
|
<link rel="stylesheet" href="https://cdn.plyr.io/3.5.4/plyr.css" />
|
||||||
```
|
```
|
||||||
|
|
||||||
## SVG Sprite
|
## SVG Sprite
|
||||||
|
|
||||||
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
|
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
|
||||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.5.3/plyr.svg`.
|
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.5.4/plyr.svg`.
|
||||||
|
|
||||||
# Ads
|
# Ads
|
||||||
|
|
||||||
@ -204,7 +211,7 @@ WebVTT captions are supported. To add a caption track, check the HTML example ab
|
|||||||
|
|
||||||
You can specify a range of arguments for the constructor to use:
|
You can specify a range of arguments for the constructor to use:
|
||||||
|
|
||||||
- A CSS string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
|
- A [CSS string selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors)
|
||||||
- A [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement)
|
- A [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement)
|
||||||
- A [jQuery](https://jquery.com) object
|
- A [jQuery](https://jquery.com) object
|
||||||
|
|
||||||
@ -238,7 +245,7 @@ You have two choices here. You can either use a simple array loop to map the con
|
|||||||
const players = Array.from(document.querySelectorAll('.js-player')).map(p => new Plyr(p));
|
const players = Array.from(document.querySelectorAll('.js-player')).map(p => new Plyr(p));
|
||||||
```
|
```
|
||||||
|
|
||||||
...or use a static method where you can pass a string selector that's compatible with [`querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector), a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList), an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement), or a [JQuery](https://jquery.com) object:
|
...or use a static method where you can pass a [CSS string selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors), a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList), an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement), or a [JQuery](https://jquery.com) object:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const players = Plyr.setup('.js-player');
|
const players = Plyr.setup('.js-player');
|
||||||
@ -703,6 +710,7 @@ Plyr costs money to run, not only my time. I donate my time for free as I enjoy
|
|||||||
- [HTML5 Weekly #177](http://html5weekly.com/issues/177)
|
- [HTML5 Weekly #177](http://html5weekly.com/issues/177)
|
||||||
- [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f)
|
- [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f)
|
||||||
- [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/)
|
- [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/)
|
||||||
|
- [Front End Focus #177](https://frontendfoc.us/issues/177)
|
||||||
- [Hacker News](https://news.ycombinator.com/item?id=9136774)
|
- [Hacker News](https://news.ycombinator.com/item?id=9136774)
|
||||||
- [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04)
|
- [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04)
|
||||||
- [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player)
|
- [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player)
|
||||||
@ -722,7 +730,7 @@ Plyr costs money to run, not only my time. I donate my time for free as I enjoy
|
|||||||
- [Sparkk TV](https://www.sparkktv.com/)
|
- [Sparkk TV](https://www.sparkktv.com/)
|
||||||
- [@halfhalftravel](https://www.halfhalftravel.com/)
|
- [@halfhalftravel](https://www.halfhalftravel.com/)
|
||||||
|
|
||||||
Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the above list. It'd be awesome to see how you're using Plyr :-)
|
If you want to be added to the list, open a pull request. It'd be awesome to see how you're using Plyr 😎
|
||||||
|
|
||||||
# Useful links and credits
|
# Useful links and credits
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ const captions = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Turn off native caption rendering to avoid double captions
|
// Turn off native caption rendering to avoid double captions
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
track.mode = 'hidden';
|
track.mode = 'hidden';
|
||||||
|
|
||||||
// Add event listener for cue changes
|
// Add event listener for cue changes
|
||||||
@ -302,7 +303,7 @@ const captions = {
|
|||||||
let track;
|
let track;
|
||||||
|
|
||||||
languages.every(language => {
|
languages.every(language => {
|
||||||
track = sorted.find(track => track.language === language);
|
track = sorted.find(t => t.language === language);
|
||||||
return !track; // Break iteration if there is a match
|
return !track; // Break iteration if there is a match
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@ const defaults = {
|
|||||||
// 'fast-forward',
|
// 'fast-forward',
|
||||||
'progress',
|
'progress',
|
||||||
'current-time',
|
'current-time',
|
||||||
|
// 'duration',
|
||||||
'mute',
|
'mute',
|
||||||
'volume',
|
'volume',
|
||||||
'captions',
|
'captions',
|
||||||
@ -195,7 +196,7 @@ const defaults = {
|
|||||||
},
|
},
|
||||||
youtube: {
|
youtube: {
|
||||||
sdk: 'https://www.youtube.com/iframe_api',
|
sdk: 'https://www.youtube.com/iframe_api',
|
||||||
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}', // 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title),fileDetails)&part=snippet',
|
api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}',
|
||||||
},
|
},
|
||||||
googleIMA: {
|
googleIMA: {
|
||||||
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
|
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
|
||||||
|
50
src/js/controls.js
vendored
50
src/js/controls.js
vendored
@ -11,7 +11,20 @@ import support from './support';
|
|||||||
import { repaint, transitionEndEvent } from './utils/animation';
|
import { repaint, transitionEndEvent } from './utils/animation';
|
||||||
import { dedupe } from './utils/arrays';
|
import { dedupe } from './utils/arrays';
|
||||||
import browser from './utils/browser';
|
import browser from './utils/browser';
|
||||||
import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, matches, removeElement, setAttributes, setFocus, toggleClass, toggleHidden } from './utils/elements';
|
import {
|
||||||
|
createElement,
|
||||||
|
emptyElement,
|
||||||
|
getAttributesFromSelector,
|
||||||
|
getElement,
|
||||||
|
getElements,
|
||||||
|
hasClass,
|
||||||
|
matches,
|
||||||
|
removeElement,
|
||||||
|
setAttributes,
|
||||||
|
setFocus,
|
||||||
|
toggleClass,
|
||||||
|
toggleHidden,
|
||||||
|
} from './utils/elements';
|
||||||
import { off, on } from './utils/events';
|
import { off, on } from './utils/events';
|
||||||
import i18n from './utils/i18n';
|
import i18n from './utils/i18n';
|
||||||
import is from './utils/is';
|
import is from './utils/is';
|
||||||
@ -480,15 +493,15 @@ const controls = {
|
|||||||
get() {
|
get() {
|
||||||
return menuItem.getAttribute('aria-checked') === 'true';
|
return menuItem.getAttribute('aria-checked') === 'true';
|
||||||
},
|
},
|
||||||
set(checked) {
|
set(check) {
|
||||||
// Ensure exclusivity
|
// Ensure exclusivity
|
||||||
if (checked) {
|
if (check) {
|
||||||
Array.from(menuItem.parentNode.children)
|
Array.from(menuItem.parentNode.children)
|
||||||
.filter(node => matches(node, '[role="menuitemradio"]'))
|
.filter(node => matches(node, '[role="menuitemradio"]'))
|
||||||
.forEach(node => node.setAttribute('aria-checked', 'false'));
|
.forEach(node => node.setAttribute('aria-checked', 'false'));
|
||||||
}
|
}
|
||||||
|
|
||||||
menuItem.setAttribute('aria-checked', checked ? 'true' : 'false');
|
menuItem.setAttribute('aria-checked', check ? 'true' : 'false');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -596,17 +609,17 @@ const controls = {
|
|||||||
let value = 0;
|
let value = 0;
|
||||||
|
|
||||||
const setProgress = (target, input) => {
|
const setProgress = (target, input) => {
|
||||||
const value = is.number(input) ? input : 0;
|
const val = is.number(input) ? input : 0;
|
||||||
const progress = is.element(target) ? target : this.elements.display.buffer;
|
const progress = is.element(target) ? target : this.elements.display.buffer;
|
||||||
|
|
||||||
// Update value and label
|
// Update value and label
|
||||||
if (is.element(progress)) {
|
if (is.element(progress)) {
|
||||||
progress.value = value;
|
progress.value = val;
|
||||||
|
|
||||||
// Update text label inside
|
// Update text label inside
|
||||||
const label = progress.getElementsByTagName('span')[0];
|
const label = progress.getElementsByTagName('span')[0];
|
||||||
if (is.element(label)) {
|
if (is.element(label)) {
|
||||||
label.childNodes[0].nodeValue = value;
|
label.childNodes[0].nodeValue = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -688,14 +701,8 @@ const controls = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate percentage
|
|
||||||
let percent = 0;
|
|
||||||
const clientRect = this.elements.progress.getBoundingClientRect();
|
|
||||||
const visible = `${this.config.classNames.tooltip}--visible`;
|
const visible = `${this.config.classNames.tooltip}--visible`;
|
||||||
|
const toggle = show => toggleClass(this.elements.display.seekTooltip, visible, show);
|
||||||
const toggle = toggle => {
|
|
||||||
toggleClass(this.elements.display.seekTooltip, visible, toggle);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Hide on touch
|
// Hide on touch
|
||||||
if (this.touch) {
|
if (this.touch) {
|
||||||
@ -704,6 +711,9 @@ const controls = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine percentage, if already visible
|
// Determine percentage, if already visible
|
||||||
|
let percent = 0;
|
||||||
|
const clientRect = this.elements.progress.getBoundingClientRect();
|
||||||
|
|
||||||
if (is.event(event)) {
|
if (is.event(event)) {
|
||||||
percent = (100 / clientRect.width) * (event.pageX - clientRect.left);
|
percent = (100 / clientRect.width) * (event.pageX - clientRect.left);
|
||||||
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
||||||
@ -1100,7 +1110,7 @@ const controls = {
|
|||||||
let target = pane;
|
let target = pane;
|
||||||
|
|
||||||
if (!is.element(target)) {
|
if (!is.element(target)) {
|
||||||
target = Object.values(this.elements.settings.panels).find(pane => !pane.hidden);
|
target = Object.values(this.elements.settings.panels).find(p => !p.hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstItem = target.querySelector('[role^="menuitem"]');
|
const firstItem = target.querySelector('[role^="menuitem"]');
|
||||||
@ -1398,7 +1408,7 @@ const controls = {
|
|||||||
|
|
||||||
// Settings button / menu
|
// Settings button / menu
|
||||||
if (control === 'settings' && !is.empty(this.config.settings)) {
|
if (control === 'settings' && !is.empty(this.config.settings)) {
|
||||||
const control = createElement(
|
const wrapper = createElement(
|
||||||
'div',
|
'div',
|
||||||
extend({}, defaultAttributes, {
|
extend({}, defaultAttributes, {
|
||||||
class: `${defaultAttributes.class} plyr__menu`.trim(),
|
class: `${defaultAttributes.class} plyr__menu`.trim(),
|
||||||
@ -1406,7 +1416,7 @@ const controls = {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
control.appendChild(
|
wrapper.appendChild(
|
||||||
createButton.call(this, 'settings', {
|
createButton.call(this, 'settings', {
|
||||||
'aria-haspopup': true,
|
'aria-haspopup': true,
|
||||||
'aria-controls': `plyr-settings-${data.id}`,
|
'aria-controls': `plyr-settings-${data.id}`,
|
||||||
@ -1546,11 +1556,11 @@ const controls = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
popup.appendChild(inner);
|
popup.appendChild(inner);
|
||||||
control.appendChild(popup);
|
wrapper.appendChild(popup);
|
||||||
container.appendChild(control);
|
container.appendChild(wrapper);
|
||||||
|
|
||||||
this.elements.settings.popup = popup;
|
this.elements.settings.popup = popup;
|
||||||
this.elements.settings.menu = control;
|
this.elements.settings.menu = wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Picture in picture button
|
// Picture in picture button
|
||||||
|
@ -73,9 +73,6 @@ function toggleFallback(toggle = false) {
|
|||||||
.filter(part => part.trim() !== property)
|
.filter(part => part.trim() !== property)
|
||||||
.join(',');
|
.join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force a repaint as sometimes Safari doesn't want to fill the screen
|
|
||||||
setTimeout(() => repaint(this.target), 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle button and fire events
|
// Toggle button and fire events
|
||||||
|
@ -44,15 +44,17 @@ const html5 = {
|
|||||||
|
|
||||||
const player = this;
|
const player = this;
|
||||||
|
|
||||||
// Set aspect ratio if set
|
// Set aspect ratio if fixed
|
||||||
|
if (!is.empty(this.config.ratio)) {
|
||||||
setAspectRatio.call(player);
|
setAspectRatio.call(player);
|
||||||
|
}
|
||||||
|
|
||||||
// Quality
|
// Quality
|
||||||
Object.defineProperty(player.media, 'quality', {
|
Object.defineProperty(player.media, 'quality', {
|
||||||
get() {
|
get() {
|
||||||
// Get sources
|
// Get sources
|
||||||
const sources = html5.getSources.call(player);
|
const sources = html5.getSources.call(player);
|
||||||
const source = sources.find(source => source.getAttribute('src') === player.source);
|
const source = sources.find(s => s.getAttribute('src') === player.source);
|
||||||
|
|
||||||
// Return size, if match is found
|
// Return size, if match is found
|
||||||
return source && Number(source.getAttribute('size'));
|
return source && Number(source.getAttribute('size'));
|
||||||
@ -61,7 +63,7 @@ const html5 = {
|
|||||||
// Get sources
|
// Get sources
|
||||||
const sources = html5.getSources.call(player);
|
const sources = html5.getSources.call(player);
|
||||||
// Get first match for requested size
|
// Get first match for requested size
|
||||||
const source = sources.find(source => Number(source.getAttribute('size')) === input);
|
const source = sources.find(s => Number(s.getAttribute('size')) === input);
|
||||||
|
|
||||||
// No matching source found
|
// No matching source found
|
||||||
if (!source) {
|
if (!source) {
|
||||||
|
@ -275,12 +275,12 @@ class Listeners {
|
|||||||
elements.container,
|
elements.container,
|
||||||
'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',
|
'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',
|
||||||
event => {
|
event => {
|
||||||
const { controls } = elements;
|
const { controls: controlsElement } = elements;
|
||||||
|
|
||||||
// Remove button states for fullscreen
|
// Remove button states for fullscreen
|
||||||
if (controls && event.type === 'enterfullscreen') {
|
if (controlsElement && event.type === 'enterfullscreen') {
|
||||||
controls.pressed = false;
|
controlsElement.pressed = false;
|
||||||
controls.hover = false;
|
controlsElement.hover = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show, then hide after a timeout unless another control event occurs
|
// Show, then hide after a timeout unless another control event occurs
|
||||||
@ -301,14 +301,6 @@ class Listeners {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Force edge to repaint on exit fullscreen
|
|
||||||
// TODO: Fix weird bug where Edge doesn't re-draw when exiting fullscreen
|
|
||||||
/* if (browser.isEdge) {
|
|
||||||
on.call(player, elements.container, 'exitfullscreen', () => {
|
|
||||||
setTimeout(() => repaint(elements.container), 100);
|
|
||||||
});
|
|
||||||
} */
|
|
||||||
|
|
||||||
// Set a gutter for Vimeo
|
// Set a gutter for Vimeo
|
||||||
const setGutter = (ratio, padding, toggle) => {
|
const setGutter = (ratio, padding, toggle) => {
|
||||||
if (!player.isVimeo) {
|
if (!player.isVimeo) {
|
||||||
@ -337,15 +329,20 @@ class Listeners {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resized = () => {
|
const resized = () => {
|
||||||
window.clearTimeout(timers.resized);
|
clearTimeout(timers.resized);
|
||||||
timers.resized = window.setTimeout(setPlayerSize, 50);
|
timers.resized = setTimeout(setPlayerSize, 50);
|
||||||
};
|
};
|
||||||
|
|
||||||
on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {
|
on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {
|
||||||
const { target, usingNative } = player.fullscreen;
|
const { target, usingNative } = player.fullscreen;
|
||||||
|
|
||||||
// Ignore for iOS native
|
// Ignore events not from target
|
||||||
if (!player.isEmbed || target !== elements.container) {
|
if (target !== elements.container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's not an embed and no ratio specified
|
||||||
|
if (!player.isEmbed && is.empty(player.config.ratio)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,7 +798,7 @@ class Listeners {
|
|||||||
|
|
||||||
// Show controls when they receive focus (e.g., when using keyboard tab key)
|
// Show controls when they receive focus (e.g., when using keyboard tab key)
|
||||||
this.bind(elements.controls, 'focusin', () => {
|
this.bind(elements.controls, 'focusin', () => {
|
||||||
const { config, elements, timers } = player;
|
const { config, timers } = player;
|
||||||
|
|
||||||
// Skip transition to prevent focus from scrolling the parent element
|
// Skip transition to prevent focus from scrolling the parent element
|
||||||
toggleClass(elements.controls, config.classNames.noTransition, true);
|
toggleClass(elements.controls, config.classNames.noTransition, true);
|
||||||
|
@ -267,7 +267,7 @@ class Ads {
|
|||||||
|
|
||||||
// Advertisement regular events
|
// Advertisement regular events
|
||||||
Object.keys(google.ima.AdEvent.Type).forEach(type => {
|
Object.keys(google.ima.AdEvent.Type).forEach(type => {
|
||||||
this.manager.addEventListener(google.ima.AdEvent.Type[type], event => this.onAdEvent(event));
|
this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Resolve our adsManager
|
// Resolve our adsManager
|
||||||
@ -310,8 +310,7 @@ class Ads {
|
|||||||
|
|
||||||
// Proxy event
|
// Proxy event
|
||||||
const dispatchEvent = type => {
|
const dispatchEvent = type => {
|
||||||
const event = `ads${type.replace(/_/g, '').toLowerCase()}`;
|
triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);
|
||||||
triggerEvent.call(this.player, this.player.media, event);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bubble the event
|
// Bubble the event
|
||||||
|
@ -2,6 +2,7 @@ import { createElement } from '../utils/elements';
|
|||||||
import { once } from '../utils/events';
|
import { once } from '../utils/events';
|
||||||
import fetch from '../utils/fetch';
|
import fetch from '../utils/fetch';
|
||||||
import is from '../utils/is';
|
import is from '../utils/is';
|
||||||
|
import { extend } from '../utils/objects';
|
||||||
import { formatTime } from '../utils/time';
|
import { formatTime } from '../utils/time';
|
||||||
|
|
||||||
// Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg"
|
// Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg"
|
||||||
@ -100,6 +101,10 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.getThumbnails().then(() => {
|
this.getThumbnails().then(() => {
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Render DOM elements
|
// Render DOM elements
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
@ -425,7 +430,9 @@ class PreviewThumbnails {
|
|||||||
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {
|
||||||
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
// Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients
|
||||||
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
// First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
image.dataset.deleting = true;
|
image.dataset.deleting = true;
|
||||||
|
|
||||||
// This has to be set before the timeout - to prevent issues switching between hover and scrub
|
// This has to be set before the timeout - to prevent issues switching between hover and scrub
|
||||||
const { currentImageContainer } = this;
|
const { currentImageContainer } = this;
|
||||||
|
|
||||||
@ -632,9 +639,13 @@ class PreviewThumbnails {
|
|||||||
// Find difference between height and preview container height
|
// Find difference between height and preview container height
|
||||||
const multiplier = this.thumbContainerHeight / frame.h;
|
const multiplier = this.thumbContainerHeight / frame.h;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;
|
previewImage.style.height = `${Math.floor(previewImage.naturalHeight * multiplier)}px`;
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;
|
previewImage.style.width = `${Math.floor(previewImage.naturalWidth * multiplier)}px`;
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.left = `-${frame.x * multiplier}px`;
|
previewImage.style.left = `-${frame.x * multiplier}px`;
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.top = `-${frame.y * multiplier}px`;
|
previewImage.style.top = `-${frame.y * multiplier}px`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,26 +56,23 @@ const youtube = {
|
|||||||
if (is.object(window.YT) && is.function(window.YT.Player)) {
|
if (is.object(window.YT) && is.function(window.YT.Player)) {
|
||||||
youtube.ready.call(this);
|
youtube.ready.call(this);
|
||||||
} else {
|
} else {
|
||||||
// Load the API
|
// Reference current global callback
|
||||||
loadScript(this.config.urls.youtube.sdk).catch(error => {
|
const callback = window.onYouTubeIframeAPIReady;
|
||||||
this.debug.warn('YouTube API failed to load', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setup callback for the API
|
|
||||||
// YouTube has it's own system of course...
|
|
||||||
window.onYouTubeReadyCallbacks = window.onYouTubeReadyCallbacks || [];
|
|
||||||
|
|
||||||
// Add to queue
|
|
||||||
window.onYouTubeReadyCallbacks.push(() => {
|
|
||||||
youtube.ready.call(this);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set callback to process queue
|
// Set callback to process queue
|
||||||
window.onYouTubeIframeAPIReady = () => {
|
window.onYouTubeIframeAPIReady = () => {
|
||||||
window.onYouTubeReadyCallbacks.forEach(callback => {
|
// Call global callback if set
|
||||||
|
if (is.function(callback)) {
|
||||||
callback();
|
callback();
|
||||||
});
|
}
|
||||||
|
|
||||||
|
youtube.ready.call(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Load the SDK
|
||||||
|
loadScript(this.config.urls.youtube.sdk).catch(error => {
|
||||||
|
this.debug.warn('YouTube API failed to load', error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -108,7 +105,7 @@ const youtube = {
|
|||||||
ready() {
|
ready() {
|
||||||
const player = this;
|
const player = this;
|
||||||
// Ignore already setup (race condition)
|
// Ignore already setup (race condition)
|
||||||
const currentId = player.media.getAttribute('id');
|
const currentId = player.media && player.media.getAttribute('id');
|
||||||
if (!is.empty(currentId) && currentId.startsWith('youtube-')) {
|
if (!is.empty(currentId) && currentId.startsWith('youtube-')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -131,16 +128,16 @@ const youtube = {
|
|||||||
player.media = replaceElement(container, player.media);
|
player.media = replaceElement(container, player.media);
|
||||||
|
|
||||||
// Id to poster wrapper
|
// Id to poster wrapper
|
||||||
const posterSrc = format => `https://i.ytimg.com/vi/${videoId}/${format}default.jpg`;
|
const posterSrc = s => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;
|
||||||
|
|
||||||
// Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
|
// Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
|
||||||
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
|
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
|
||||||
.catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3
|
.catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3
|
||||||
.catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists
|
.catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists
|
||||||
.then(image => ui.setPoster.call(player, image.src))
|
.then(image => ui.setPoster.call(player, image.src))
|
||||||
.then(posterSrc => {
|
.then(src => {
|
||||||
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
|
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
|
||||||
if (!posterSrc.includes('maxres')) {
|
if (!src.includes('maxres')) {
|
||||||
player.elements.poster.style.backgroundSize = 'cover';
|
player.elements.poster.style.backgroundSize = 'cover';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -323,27 +323,27 @@ class Plyr {
|
|||||||
* Types and provider helpers
|
* Types and provider helpers
|
||||||
*/
|
*/
|
||||||
get isHTML5() {
|
get isHTML5() {
|
||||||
return Boolean(this.provider === providers.html5);
|
return this.provider === providers.html5;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isEmbed() {
|
get isEmbed() {
|
||||||
return Boolean(this.isYouTube || this.isVimeo);
|
return this.isYouTube || this.isVimeo;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isYouTube() {
|
get isYouTube() {
|
||||||
return Boolean(this.provider === providers.youtube);
|
return this.provider === providers.youtube;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isVimeo() {
|
get isVimeo() {
|
||||||
return Boolean(this.provider === providers.vimeo);
|
return this.provider === providers.vimeo;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isVideo() {
|
get isVideo() {
|
||||||
return Boolean(this.type === types.video);
|
return this.type === types.video;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isAudio() {
|
get isAudio() {
|
||||||
return Boolean(this.type === types.audio);
|
return this.type === types.audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
15
src/js/ui.js
15
src/js/ui.js
@ -213,7 +213,7 @@ const ui = {
|
|||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
Array.from(this.elements.buttons.play || []).forEach(target => {
|
Array.from(this.elements.buttons.play || []).forEach(target => {
|
||||||
target.pressed = this.playing;
|
Object.assign(target, { pressed: this.playing });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only update controls on non timeupdate events
|
// Only update controls on non timeupdate events
|
||||||
@ -247,15 +247,22 @@ const ui = {
|
|||||||
|
|
||||||
// Toggle controls based on state and `force` argument
|
// Toggle controls based on state and `force` argument
|
||||||
toggleControls(force) {
|
toggleControls(force) {
|
||||||
const { controls } = this.elements;
|
const { controls: controlsElement } = this.elements;
|
||||||
|
|
||||||
if (controls && this.config.hideControls) {
|
if (controlsElement && this.config.hideControls) {
|
||||||
// Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)
|
// Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)
|
||||||
const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now();
|
const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now();
|
||||||
|
|
||||||
// Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide
|
// Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide
|
||||||
this.toggleControls(
|
this.toggleControls(
|
||||||
Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek),
|
Boolean(
|
||||||
|
force ||
|
||||||
|
this.loading ||
|
||||||
|
this.paused ||
|
||||||
|
controlsElement.pressed ||
|
||||||
|
controlsElement.hover ||
|
||||||
|
recentTouchSeek,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Animation utils
|
// Animation utils
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
import { toggleHidden } from './elements';
|
|
||||||
import is from './is';
|
import is from './is';
|
||||||
|
|
||||||
export const transitionEndEvent = (() => {
|
export const transitionEndEvent = (() => {
|
||||||
@ -21,14 +20,19 @@ export const transitionEndEvent = (() => {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
// Force repaint of element
|
// Force repaint of element
|
||||||
export function repaint(element) {
|
export function repaint(element, delay) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
toggleHidden(element, true);
|
// eslint-disable-next-line no-param-reassign
|
||||||
element.offsetHeight; // eslint-disable-line
|
element.hidden = true;
|
||||||
toggleHidden(element, false);
|
|
||||||
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
element.offsetHeight;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
element.hidden = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
}, 0);
|
}, delay);
|
||||||
}
|
}
|
||||||
|
@ -192,11 +192,8 @@ export function toggleHidden(element, hidden) {
|
|||||||
hide = !element.hidden;
|
hide = !element.hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hide) {
|
// eslint-disable-next-line no-param-reassign
|
||||||
element.setAttribute('hidden', '');
|
element.hidden = hide;
|
||||||
} else {
|
|
||||||
element.removeAttribute('hidden');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
// Mirror Element.classList.toggle, with IE compatibility for "force" argument
|
||||||
@ -231,14 +228,14 @@ export function matches(element, selector) {
|
|||||||
return Array.from(document.querySelectorAll(selector)).includes(this);
|
return Array.from(document.querySelectorAll(selector)).includes(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const matches =
|
const method =
|
||||||
prototype.matches ||
|
prototype.matches ||
|
||||||
prototype.webkitMatchesSelector ||
|
prototype.webkitMatchesSelector ||
|
||||||
prototype.mozMatchesSelector ||
|
prototype.mozMatchesSelector ||
|
||||||
prototype.msMatchesSelector ||
|
prototype.msMatchesSelector ||
|
||||||
match;
|
match;
|
||||||
|
|
||||||
return matches.call(element, selector);
|
return method.call(element, selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all elements
|
// Find all elements
|
||||||
|
@ -36,8 +36,8 @@ const i18n = {
|
|||||||
'{title}': config.title,
|
'{title}': config.title,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.entries(replace).forEach(([key, value]) => {
|
Object.entries(replace).forEach(([k, v]) => {
|
||||||
string = replaceAll(string, key, value);
|
string = replaceAll(string, k, v);
|
||||||
});
|
});
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
|
@ -18,6 +18,7 @@ export default function loadSprite(url, id) {
|
|||||||
const exists = () => document.getElementById(id) !== null;
|
const exists = () => document.getElementById(id) !== null;
|
||||||
|
|
||||||
const update = (container, data) => {
|
const update = (container, data) => {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
container.innerHTML = data;
|
container.innerHTML = data;
|
||||||
|
|
||||||
// Check again incase of race condition
|
// Check again incase of race condition
|
||||||
|
@ -27,15 +27,8 @@ export function reduceAspectRatio(ratio) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getAspectRatio(input) {
|
export function getAspectRatio(input) {
|
||||||
const parse = ratio => {
|
const parse = ratio => (validateRatio(ratio) ? ratio.split(':').map(Number) : null);
|
||||||
if (!validateRatio(ratio)) {
|
// Try provided ratio
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ratio.split(':').map(Number);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Provided ratio
|
|
||||||
let ratio = parse(input);
|
let ratio = parse(input);
|
||||||
|
|
||||||
// Get from config
|
// Get from config
|
||||||
|
@ -63,10 +63,6 @@ a.plyr__control {
|
|||||||
|
|
||||||
// Video control
|
// Video control
|
||||||
.plyr--video .plyr__control {
|
.plyr--video .plyr__control {
|
||||||
svg {
|
|
||||||
filter: drop-shadow(0 1px 1px rgba(#000, 0.15));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hover and tab focus
|
// Hover and tab focus
|
||||||
&.plyr__tab-focus,
|
&.plyr__tab-focus,
|
||||||
&:hover,
|
&:hover,
|
||||||
@ -81,7 +77,6 @@ a.plyr__control {
|
|||||||
background: rgba($plyr-video-control-bg-hover, 0.8);
|
background: rgba($plyr-video-control-bg-hover, 0.8);
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
box-shadow: 0 1px 1px rgba(#000, 0.15);
|
|
||||||
color: $plyr-video-control-color;
|
color: $plyr-video-control-color;
|
||||||
display: none;
|
display: none;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
min-width: 0; // Fix for Edge issue where content would overflow
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.plyr__progress__container {
|
.plyr__progress__container {
|
||||||
|
@ -62,12 +62,13 @@
|
|||||||
|
|
||||||
.plyr__video-wrapper {
|
.plyr__video-wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
position: static;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vimeo requires some different styling
|
// Vimeo requires some different styling
|
||||||
&.plyr--vimeo .plyr__video-wrapper {
|
&.plyr--vimeo .plyr__video-wrapper {
|
||||||
height: 0;
|
height: 0;
|
||||||
|
position: relative;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
// The countdown label
|
// The countdown label
|
||||||
&::after {
|
&::after {
|
||||||
background: rgba($plyr-color-gunmetal, 0.8);
|
background: rgba($plyr-color-gray-9, 0.8);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
bottom: $plyr-control-spacing;
|
bottom: $plyr-control-spacing;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
@ -7,7 +7,7 @@ $plyr-preview-bg: $plyr-tooltip-bg !default;
|
|||||||
$plyr-preview-radius: $plyr-tooltip-radius !default;
|
$plyr-preview-radius: $plyr-tooltip-radius !default;
|
||||||
$plyr-preview-shadow: $plyr-tooltip-shadow !default;
|
$plyr-preview-shadow: $plyr-tooltip-shadow !default;
|
||||||
$plyr-preview-arrow-size: $plyr-tooltip-arrow-size !default;
|
$plyr-preview-arrow-size: $plyr-tooltip-arrow-size !default;
|
||||||
$plyr-preview-image-bg: $plyr-color-heather !default;
|
$plyr-preview-image-bg: $plyr-color-gray-2 !default;
|
||||||
$plyr-preview-time-font-size: $plyr-font-size-time !default;
|
$plyr-preview-time-font-size: $plyr-font-size-time !default;
|
||||||
$plyr-preview-time-padding: 3px 6px !default;
|
$plyr-preview-time-padding: 3px 6px !default;
|
||||||
$plyr-preview-time-bg: rgba(0, 0, 0, 0.55);
|
$plyr-preview-time-bg: rgba(0, 0, 0, 0.55);
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
// Badges
|
// Badges
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$plyr-badge-bg: $plyr-color-fiord !default;
|
$plyr-badge-bg: $plyr-color-gray-7 !default;
|
||||||
$plyr-badge-color: #fff !default;
|
$plyr-badge-color: #fff !default;
|
||||||
|
@ -2,8 +2,16 @@
|
|||||||
// Colors
|
// Colors
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$plyr-color-main: #1aafff !default;
|
$plyr-color-main: hsl(198, 100%, 50%) !default;
|
||||||
$plyr-color-gunmetal: #2f343d !default;
|
|
||||||
$plyr-color-fiord: #4f5b5f !default;
|
// Grayscale
|
||||||
$plyr-color-lynch: #6b7d85 !default;
|
$plyr-color-gray-9: hsl(210, 15%, 16%);
|
||||||
$plyr-color-heather: #b7c5cd !default;
|
$plyr-color-gray-8: lighten($plyr-color-gray-9, 9%);
|
||||||
|
$plyr-color-gray-7: lighten($plyr-color-gray-8, 9%);
|
||||||
|
$plyr-color-gray-6: lighten($plyr-color-gray-7, 9%);
|
||||||
|
$plyr-color-gray-5: lighten($plyr-color-gray-6, 9%);
|
||||||
|
$plyr-color-gray-4: lighten($plyr-color-gray-5, 9%);
|
||||||
|
$plyr-color-gray-3: lighten($plyr-color-gray-4, 9%);
|
||||||
|
$plyr-color-gray-2: lighten($plyr-color-gray-3, 9%);
|
||||||
|
$plyr-color-gray-1: lighten($plyr-color-gray-2, 9%);
|
||||||
|
$plyr-color-gray-0: lighten($plyr-color-gray-1, 9%);
|
||||||
|
@ -13,6 +13,6 @@ $plyr-video-control-color-hover: #fff !default;
|
|||||||
$plyr-video-control-bg-hover: $plyr-color-main !default;
|
$plyr-video-control-bg-hover: $plyr-color-main !default;
|
||||||
|
|
||||||
$plyr-audio-controls-bg: #fff !default;
|
$plyr-audio-controls-bg: #fff !default;
|
||||||
$plyr-audio-control-color: $plyr-color-fiord !default;
|
$plyr-audio-control-color: $plyr-color-gray-7 !default;
|
||||||
$plyr-audio-control-color-hover: #fff !default;
|
$plyr-audio-control-color-hover: #fff !default;
|
||||||
$plyr-audio-control-bg-hover: $plyr-color-main !default;
|
$plyr-audio-control-bg-hover: $plyr-color-main !default;
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$plyr-menu-bg: rgba(#fff, 0.9) !default;
|
$plyr-menu-bg: rgba(#fff, 0.9) !default;
|
||||||
$plyr-menu-color: $plyr-color-fiord !default;
|
$plyr-menu-color: $plyr-color-gray-7 !default;
|
||||||
$plyr-menu-arrow-size: 6px !default;
|
$plyr-menu-arrow-size: 6px !default;
|
||||||
$plyr-menu-border-color: $plyr-color-heather !default;
|
$plyr-menu-border-color: $plyr-color-gray-2 !default;
|
||||||
$plyr-menu-border-shadow-color: #fff !default;
|
$plyr-menu-border-shadow-color: #fff !default;
|
||||||
$plyr-menu-shadow: 0 1px 2px rgba(#000, 0.15) !default;
|
$plyr-menu-shadow: 0 1px 2px rgba(#000, 0.15) !default;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
$plyr-progress-loading-size: 25px !default;
|
$plyr-progress-loading-size: 25px !default;
|
||||||
$plyr-progress-loading-bg: rgba($plyr-color-gunmetal, 0.6) !default;
|
$plyr-progress-loading-bg: rgba($plyr-color-gray-9, 0.6) !default;
|
||||||
|
|
||||||
// Buffered
|
// Buffered
|
||||||
$plyr-video-progress-buffered-bg: rgba(#fff, 0.25) !default;
|
$plyr-video-progress-buffered-bg: rgba(#fff, 0.25) !default;
|
||||||
$plyr-audio-progress-buffered-bg: rgba($plyr-color-heather, 0.66) !default;
|
$plyr-audio-progress-buffered-bg: rgba($plyr-color-gray-2, 0.66) !default;
|
||||||
|
@ -9,7 +9,7 @@ $plyr-range-thumb-active-shadow-width: 3px !default;
|
|||||||
$plyr-range-thumb-height: 13px !default;
|
$plyr-range-thumb-height: 13px !default;
|
||||||
$plyr-range-thumb-bg: #fff !default;
|
$plyr-range-thumb-bg: #fff !default;
|
||||||
$plyr-range-thumb-border: 2px solid transparent !default;
|
$plyr-range-thumb-border: 2px solid transparent !default;
|
||||||
$plyr-range-thumb-shadow: 0 1px 1px rgba(#000, 0.15), 0 0 0 1px rgba($plyr-color-gunmetal, 0.2) !default;
|
$plyr-range-thumb-shadow: 0 1px 1px rgba(#000, 0.15), 0 0 0 1px rgba($plyr-color-gray-9, 0.2) !default;
|
||||||
|
|
||||||
// Track
|
// Track
|
||||||
$plyr-range-track-height: 5px !default;
|
$plyr-range-track-height: 5px !default;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$plyr-tooltip-bg: rgba(#fff, 0.9) !default;
|
$plyr-tooltip-bg: rgba(#fff, 0.9) !default;
|
||||||
$plyr-tooltip-color: $plyr-color-fiord !default;
|
$plyr-tooltip-color: $plyr-color-gray-7 !default;
|
||||||
$plyr-tooltip-padding: ($plyr-control-spacing / 2) !default;
|
$plyr-tooltip-padding: ($plyr-control-spacing / 2) !default;
|
||||||
$plyr-tooltip-arrow-size: 4px !default;
|
$plyr-tooltip-arrow-size: 4px !default;
|
||||||
$plyr-tooltip-radius: 3px !default;
|
$plyr-tooltip-radius: 3px !default;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user