Compare commits
44 Commits
v3.1.0-beta.1
...
v3.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 27407ba021 | |||
| ef8e58ede4 | |||
| f1b275aedc | |||
| b647af256c | |||
| d2e9ed3467 | |||
| 5b39986835 | |||
| a97b08e8ea | |||
| 56d1be9447 | |||
| a241cb5215 | |||
| 042b1a8294 | |||
| 6d79b8cd4c | |||
| 88d766aeae | |||
| 119b471b84 | |||
| 7f079e0ec3 | |||
| 46fe3eecff | |||
| 3061a701d5 | |||
| e45109e1d7 | |||
| e138e6d51e | |||
| aef1363b04 | |||
| 766dd03d81 | |||
| ab393651ec | |||
| ffd265d0ae | |||
| 72155472dd | |||
| 9b7170834e | |||
| 3e57a87bf7 | |||
| a15d1c9f1c | |||
| a095a64f90 | |||
| 2374d6b1c4 | |||
| 5ed3ff9084 | |||
| 385be55510 | |||
| 3082d0d128 | |||
| f7e242f054 | |||
| 2874505004 | |||
| ed9e0c13d7 | |||
| 10be94fa99 | |||
| ee79c46145 | |||
| 384010a2c0 | |||
| 1e47019122 | |||
| 536c65e82c | |||
| cdf14932ec | |||
| 3b20dbd9fd | |||
| e4d975af00 | |||
| 2782a00e7c | |||
| 91d192dd7c |
+1
-1
@@ -11,7 +11,7 @@
|
||||
"demo": {
|
||||
"sass": {
|
||||
"demo.css": "demo/src/sass/bundles/demo.scss",
|
||||
"error.css": "demo/src/sass/bundles/error.csss"
|
||||
"error.css": "demo/src/sass/bundles/error.scss"
|
||||
},
|
||||
"js": {
|
||||
"demo.js": "demo/src/js/demo.js"
|
||||
|
||||
@@ -1,3 +1,36 @@
|
||||
## v3.2.2
|
||||
|
||||
* Fix for regression in 3.2.1 resulting in hidden buffer display
|
||||
* Cleaned up incorrect use of `aria-hidden` attribute
|
||||
|
||||
## v3.2.1
|
||||
|
||||
* Accessibility improvements for the controls (part of #905 fixes)
|
||||
* Fix for context menu showing on YouTube (thanks Anthony Recenello in Slack)
|
||||
* Vimeo fix for their API not returning the right duration until playback begins (fixes #891)
|
||||
|
||||
## v3.2.0
|
||||
|
||||
* Fullscreen fixes (thanks @friday)
|
||||
* Menu fix for if speed not in config
|
||||
* Menu z-index fix (thanks @danielsarin)
|
||||
* i18n fix for missing "Normal" string (thanks @danielsarin)
|
||||
* Safer check for active caption (thanks @Antonio-Laguna)
|
||||
* Add custom property fallback (thanks @friday)
|
||||
* Fixed bug for captions with no srclang and labels and improved logic (fixes #875)
|
||||
* Fix for `playing` false positive (fixes #898)
|
||||
* Fix for IE issue with navigator.language (thanks @nicolasthy) (fixes #893)
|
||||
* Fix for Vimeo controls missing on iOS (thanks @verde-io) (fixes #807)
|
||||
* Fix for double vimeo caption rendering (fixes #877)
|
||||
|
||||
## v3.1.0
|
||||
|
||||
* Styling fixes
|
||||
|
||||
## v3.1.0-beta.2
|
||||
|
||||
* YouTube playback speed fixes
|
||||
|
||||
## v3.1.0-beta.1
|
||||
|
||||
* HTML5 quality selection
|
||||
|
||||
@@ -59,6 +59,7 @@ i18n: {
|
||||
captions: 'Captions',
|
||||
settings: 'Settings',
|
||||
speed: 'Speed',
|
||||
normal: 'Normal',
|
||||
quality: 'Quality',
|
||||
loop: 'Loop',
|
||||
start: 'Start',
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
-1
@@ -4011,7 +4011,6 @@ singleton.Client = Client;
|
||||
case types.youtube:
|
||||
player.source = {
|
||||
type: 'video',
|
||||
title: 'View From A Blue Moon',
|
||||
sources: [{
|
||||
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
|
||||
provider: 'youtube'
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+7
-1
@@ -6,8 +6,14 @@
|
||||
<title>Doh. Looks like something went wrong.</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- Icons -->
|
||||
<link rel="icon" href="https://cdn.plyr.io/static/icons/favicon.ico">
|
||||
<link rel="icon" type="image/png" href="https://cdn.plyr.io/static/icons/32x32.png" sizes="32x32">
|
||||
<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">
|
||||
|
||||
<!-- Docs styles -->
|
||||
<link rel="stylesheet" href="dist/error.css">
|
||||
<link rel="stylesheet" href="dist/error.css?v=2">
|
||||
|
||||
<!-- Preload -->
|
||||
<link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-medium.woff2">
|
||||
|
||||
+3
-3
@@ -27,7 +27,7 @@
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
|
||||
<!-- Docs styles -->
|
||||
<link rel="stylesheet" href="dist/demo.css">
|
||||
<link rel="stylesheet" href="dist/demo.css?v=2">
|
||||
|
||||
<!-- Preload -->
|
||||
<link rel="preload" as="font" crossorigin type="font/woff2" href="https://cdn.plyr.io/static/fonts/gordita-medium.woff2">
|
||||
@@ -114,7 +114,7 @@
|
||||
<title>HTML5</title>
|
||||
<path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path>
|
||||
</svg>
|
||||
<a href="http://viewfromabluemoon.com/" target="_blank">View From A Blue Moon</a> © Brainfarm
|
||||
<a href="https://itunes.apple.com/au/movie/view-from-a-blue-moon/id1041586323" target="_blank">View From A Blue Moon</a> © Brainfarm
|
||||
</small>
|
||||
</li>
|
||||
<li class="plyr__cite plyr__cite--audio" hidden>
|
||||
@@ -141,7 +141,7 @@
|
||||
</li>
|
||||
<li class="plyr__cite plyr__cite--vimeo" hidden>
|
||||
<small>
|
||||
<a href="https://vimeo.com/ondemand/viewfromabluemoon4k" target="_blank">View From A Blue Moon</a> on
|
||||
<a href="https://vimeo.com/76979871" target="_blank">The New Vimeo Player</a> on
|
||||
<span class="color--vimeo">
|
||||
<svg class="icon" role="presentation">
|
||||
<title>Vimeo</title>
|
||||
|
||||
@@ -182,7 +182,6 @@ import Raven from 'raven-js';
|
||||
case types.youtube:
|
||||
player.source = {
|
||||
type: 'video',
|
||||
title: 'View From A Blue Moon',
|
||||
sources: [{
|
||||
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
|
||||
provider: 'youtube',
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
// ==========================================================================
|
||||
@charset 'UTF-8';
|
||||
|
||||
// Libs
|
||||
@import '../lib/fontface';
|
||||
@import '../lib/mixins';
|
||||
@import '../lib/normalize';
|
||||
@import '../lib/reset';
|
||||
|
||||
// Settings
|
||||
@import '../settings/colors';
|
||||
@import '../settings/cosmetic';
|
||||
@@ -17,6 +11,12 @@
|
||||
@import '../settings/spacing';
|
||||
@import '../settings/type';
|
||||
|
||||
// Libs
|
||||
@import '../lib/fontface';
|
||||
@import '../lib/mixins';
|
||||
@import '../lib/normalize';
|
||||
@import '../lib/reset';
|
||||
|
||||
// Layout
|
||||
@import '../layout/error';
|
||||
|
||||
|
||||
@@ -16,3 +16,4 @@ $plyr-font-size-captions-base: $plyr-font-size-base;
|
||||
$plyr-font-size-captions-small: $plyr-font-size-small;
|
||||
$plyr-font-size-captions-medium: 18px;
|
||||
$plyr-font-size-captions-large: 21px;
|
||||
$plyr-font-size-menu: $plyr-font-size-base;
|
||||
|
||||
@@ -6,5 +6,6 @@ h1 {
|
||||
@include font-size($font-size-h1);
|
||||
font-weight: $font-weight-bold;
|
||||
letter-spacing: $letter-spacing-headings;
|
||||
margin: 0 0 ($spacing-base / 2);
|
||||
line-height: 1.2;
|
||||
margin: 0 0 $spacing-base;
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+295
-170
@@ -77,14 +77,14 @@ var defaults = {
|
||||
// Sprite (for icons)
|
||||
loadSprite: true,
|
||||
iconPrefix: 'plyr',
|
||||
iconUrl: 'https://cdn.plyr.io/3.1.0-beta.1/plyr.svg',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.1/plyr.svg',
|
||||
|
||||
// Blank video (used to prevent errors on source change)
|
||||
blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
|
||||
|
||||
// Quality default
|
||||
quality: {
|
||||
default: 720,
|
||||
default: 576,
|
||||
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240, 'default']
|
||||
},
|
||||
|
||||
@@ -116,7 +116,7 @@ var defaults = {
|
||||
// Captions settings
|
||||
captions: {
|
||||
active: false,
|
||||
language: window.navigator.language.split('-')[0]
|
||||
language: (navigator.language || navigator.userLanguage).split('-')[0]
|
||||
},
|
||||
|
||||
// Fullscreen settings
|
||||
@@ -164,6 +164,7 @@ var defaults = {
|
||||
captions: 'Captions',
|
||||
settings: 'Settings',
|
||||
speed: 'Speed',
|
||||
normal: 'Normal',
|
||||
quality: 'Quality',
|
||||
loop: 'Loop',
|
||||
start: 'Start',
|
||||
@@ -171,6 +172,7 @@ var defaults = {
|
||||
all: 'All',
|
||||
reset: 'Reset',
|
||||
disabled: 'Disabled',
|
||||
enabled: 'Enabled',
|
||||
advertisement: 'Ad'
|
||||
},
|
||||
|
||||
@@ -1099,6 +1101,26 @@ var utils = {
|
||||
},
|
||||
|
||||
|
||||
// Toggle hidden
|
||||
toggleHidden: function toggleHidden(element, hidden) {
|
||||
if (!utils.is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var hide = hidden;
|
||||
|
||||
if (!utils.is.boolean(hide)) {
|
||||
hide = !element.hasAttribute('hidden');
|
||||
}
|
||||
|
||||
if (hide) {
|
||||
element.setAttribute('hidden', '');
|
||||
} else {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Toggle class on an element
|
||||
toggleClass: function toggleClass(element, className, toggle) {
|
||||
if (utils.is.element(element)) {
|
||||
@@ -1119,20 +1141,6 @@ var utils = {
|
||||
},
|
||||
|
||||
|
||||
// Toggle hidden attribute on an element
|
||||
toggleHidden: function toggleHidden(element, toggle) {
|
||||
if (!utils.is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
element.setAttribute('hidden', '');
|
||||
} else {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Element matches selector
|
||||
matches: function matches(element, selector) {
|
||||
var prototype = { Element: Element };
|
||||
@@ -1542,6 +1550,18 @@ var utils = {
|
||||
},
|
||||
|
||||
|
||||
// Get the closest value in an array
|
||||
closest: function closest(array, value) {
|
||||
if (!utils.is.array(array) || !array.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array.reduce(function (prev, curr) {
|
||||
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// Get the provider for a given URL
|
||||
getProviderByUrl: function getProviderByUrl(url) {
|
||||
// YouTube
|
||||
@@ -1690,16 +1710,16 @@ var support = {
|
||||
|
||||
// Check for support
|
||||
// Basic functionality vs full UI
|
||||
check: function check(type, provider, inline) {
|
||||
check: function check(type, provider, playsinline) {
|
||||
var api = false;
|
||||
var ui = false;
|
||||
var browser = utils.getBrowser();
|
||||
var playsInline = browser.isIPhone && inline && support.inline;
|
||||
var canPlayInline = browser.isIPhone && playsinline && support.playsinline;
|
||||
|
||||
switch (provider + ':' + type) {
|
||||
case 'html5:video':
|
||||
api = support.video;
|
||||
ui = api && support.rangeInput && (!browser.isIPhone || playsInline);
|
||||
ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);
|
||||
break;
|
||||
|
||||
case 'html5:audio':
|
||||
@@ -1710,7 +1730,7 @@ var support = {
|
||||
case 'youtube:video':
|
||||
case 'vimeo:video':
|
||||
api = true;
|
||||
ui = support.rangeInput && (!browser.isIPhone || playsInline);
|
||||
ui = support.rangeInput && (!browser.isIPhone || canPlayInline);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1738,7 +1758,7 @@ var support = {
|
||||
|
||||
// Inline playback support
|
||||
// https://webkit.org/blog/6784/new-video-policies-for-ios/
|
||||
inline: 'playsInline' in document.createElement('video'),
|
||||
playsinline: 'playsInline' in document.createElement('video'),
|
||||
|
||||
// Check for mime type support against a player instance
|
||||
// Credits: http://diveintohtml5.info/everything.html
|
||||
@@ -1951,13 +1971,13 @@ var Fullscreen = function () {
|
||||
});
|
||||
|
||||
// Fullscreen toggle on double click
|
||||
utils.on(this.player.elements.container, 'dblclick', function () {
|
||||
_this.toggle();
|
||||
});
|
||||
utils.on(this.player.elements.container, 'dblclick', function (event) {
|
||||
// Ignore double click in controls
|
||||
if (_this.player.elements.controls.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent double click on controls bubbling up
|
||||
utils.on(this.player.elements.controls, 'dblclick', function (event) {
|
||||
return event.stopPropagation();
|
||||
_this.toggle();
|
||||
});
|
||||
|
||||
// Update the UI
|
||||
@@ -2022,7 +2042,7 @@ var Fullscreen = function () {
|
||||
} else if (!Fullscreen.native) {
|
||||
toggleFallback.call(this, false);
|
||||
} else if (!this.prefix) {
|
||||
document.cancelFullScreen();
|
||||
(document.cancelFullScreen || document.exitFullscreen).call(document);
|
||||
} else if (!utils.is.empty(this.prefix)) {
|
||||
var action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
||||
document['' + this.prefix + action + this.name]();
|
||||
@@ -2088,7 +2108,7 @@ var Fullscreen = function () {
|
||||
get: function get$$1() {
|
||||
// No prefix
|
||||
if (utils.is.function(document.exitFullscreen)) {
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Check for fullscreen support by vendor prefix
|
||||
@@ -2117,6 +2137,36 @@ var Fullscreen = function () {
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var i18n = {
|
||||
get: function get$$1() {
|
||||
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
|
||||
if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var string = config.i18n[key];
|
||||
|
||||
var replace = {
|
||||
'{seektime}': config.seekTime,
|
||||
'{title}': config.title
|
||||
};
|
||||
|
||||
Object.entries(replace).forEach(function (_ref) {
|
||||
var _ref2 = slicedToArray(_ref, 2),
|
||||
key = _ref2[0],
|
||||
value = _ref2[1];
|
||||
|
||||
string = utils.replaceAll(string, key, value);
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var captions = {
|
||||
// Setup captions
|
||||
setup: function setup() {
|
||||
@@ -2156,6 +2206,7 @@ var captions = {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Inject the container
|
||||
if (!utils.is.element(this.elements.captions)) {
|
||||
this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));
|
||||
@@ -2260,9 +2311,54 @@ var captions = {
|
||||
getCurrentTrack: function getCurrentTrack() {
|
||||
var _this2 = this;
|
||||
|
||||
return captions.getTracks.call(this).find(function (track) {
|
||||
var tracks = captions.getTracks.call(this);
|
||||
|
||||
if (!tracks.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get track based on current language
|
||||
var track = tracks.find(function (track) {
|
||||
return track.language.toLowerCase() === _this2.language;
|
||||
});
|
||||
|
||||
// Get the <track> with default attribute
|
||||
if (!track) {
|
||||
track = utils.getElement.call(this, 'track[default]');
|
||||
}
|
||||
|
||||
// Get the first track
|
||||
if (!track) {
|
||||
var _tracks = slicedToArray(tracks, 1);
|
||||
|
||||
track = _tracks[0];
|
||||
}
|
||||
|
||||
return track;
|
||||
},
|
||||
|
||||
|
||||
// Get UI label for track
|
||||
getLabel: function getLabel(track) {
|
||||
var currentTrack = track;
|
||||
|
||||
if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {
|
||||
currentTrack = captions.getCurrentTrack.call(this);
|
||||
}
|
||||
|
||||
if (utils.is.track(currentTrack)) {
|
||||
if (!utils.is.empty(currentTrack.label)) {
|
||||
return currentTrack.label;
|
||||
}
|
||||
|
||||
if (!utils.is.empty(currentTrack.language)) {
|
||||
return track.language.toUpperCase();
|
||||
}
|
||||
|
||||
return i18n.get('enabled', this.config);
|
||||
}
|
||||
|
||||
return i18n.get('disabled', this.config);
|
||||
},
|
||||
|
||||
|
||||
@@ -2324,11 +2420,6 @@ var captions = {
|
||||
|
||||
// Display captions container and button (for initialization)
|
||||
show: function show() {
|
||||
// If there's no caption toggle, bail
|
||||
if (!utils.is.element(this.elements.buttons.captions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to load the value from storage
|
||||
var active = this.storage.get('captions');
|
||||
|
||||
@@ -2348,36 +2439,6 @@ var captions = {
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var i18n = {
|
||||
get: function get$$1() {
|
||||
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
|
||||
if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var string = config.i18n[key];
|
||||
|
||||
var replace = {
|
||||
'{seektime}': config.seekTime,
|
||||
'{title}': config.title
|
||||
};
|
||||
|
||||
Object.entries(replace).forEach(function (_ref) {
|
||||
var _ref2 = slicedToArray(_ref, 2),
|
||||
key = _ref2[0],
|
||||
value = _ref2[1];
|
||||
|
||||
string = utils.replaceAll(string, key, value);
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var ui = {
|
||||
addStyleHook: function addStyleHook() {
|
||||
utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);
|
||||
@@ -2880,11 +2941,6 @@ var browser$1 = utils.getBrowser();
|
||||
var controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill: function updateRangeFill(target) {
|
||||
// WebKit only
|
||||
if (!browser$1.isWebkit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get range from event if event passed
|
||||
var range = utils.is.event(target) ? target.target : target;
|
||||
|
||||
@@ -2893,6 +2949,14 @@ var controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set aria value for https://github.com/sampotts/plyr/issues/905
|
||||
range.setAttribute('aria-valuenow', range.value);
|
||||
|
||||
// WebKit only
|
||||
if (!browser$1.isWebkit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set CSS custom property
|
||||
range.style.setProperty('--value', range.value / range.max * 100 + '%');
|
||||
},
|
||||
@@ -2916,7 +2980,8 @@ var controls = {
|
||||
// Create <svg>
|
||||
var icon = document.createElementNS(namespace, 'svg');
|
||||
utils.setAttributes(icon, utils.extend(attributes, {
|
||||
role: 'presentation'
|
||||
role: 'presentation',
|
||||
focusable: 'false'
|
||||
}));
|
||||
|
||||
// Create the <use> to reference sprite
|
||||
@@ -3098,6 +3163,7 @@ var controls = {
|
||||
// Seek label
|
||||
var label = utils.createElement('label', {
|
||||
for: attributes.id,
|
||||
id: attributes.id + '-label',
|
||||
class: this.config.classNames.hidden
|
||||
}, i18n.get(type, this.config));
|
||||
|
||||
@@ -3108,7 +3174,13 @@ var controls = {
|
||||
max: 100,
|
||||
step: 0.01,
|
||||
value: 0,
|
||||
autocomplete: 'off'
|
||||
autocomplete: 'off',
|
||||
// A11y fixes for https://github.com/sampotts/plyr/issues/905
|
||||
role: 'slider',
|
||||
'aria-labelledby': attributes.id + '-label',
|
||||
'aria-valuemin': 0,
|
||||
'aria-valuemax': 100,
|
||||
'aria-valuenow': 0
|
||||
}, attributes));
|
||||
|
||||
this.elements.inputs[type] = input;
|
||||
@@ -3128,7 +3200,9 @@ var controls = {
|
||||
var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), {
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: 0
|
||||
value: 0,
|
||||
role: 'presentation',
|
||||
'aria-hidden': true
|
||||
}, attributes));
|
||||
|
||||
// Create the label inside
|
||||
@@ -3195,7 +3269,7 @@ var controls = {
|
||||
class: 'plyr__sr-only'
|
||||
}));
|
||||
|
||||
var faux = utils.createElement('span', { 'aria-hidden': true });
|
||||
var faux = utils.createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
@@ -3266,11 +3340,7 @@ var controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab: function toggleTab(setting, toggle) {
|
||||
var tab = this.elements.settings.tabs[setting];
|
||||
var pane = this.elements.settings.panes[setting];
|
||||
|
||||
utils.toggleHidden(tab, !toggle);
|
||||
utils.toggleHidden(pane, !toggle);
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
|
||||
@@ -3298,6 +3368,9 @@ var controls = {
|
||||
var toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
|
||||
// If we're hiding, nothing more to do
|
||||
if (!toggle) {
|
||||
return;
|
||||
@@ -3316,13 +3389,7 @@ var controls = {
|
||||
break;
|
||||
|
||||
case 1440:
|
||||
label = 'WQHD';
|
||||
break;
|
||||
|
||||
case 1080:
|
||||
label = 'HD';
|
||||
break;
|
||||
|
||||
case 720:
|
||||
label = 'HD';
|
||||
break;
|
||||
@@ -3360,16 +3427,17 @@ var controls = {
|
||||
getLabel: function getLabel(setting, value) {
|
||||
switch (setting) {
|
||||
case 'speed':
|
||||
return value === 1 ? 'Normal' : value + '×';
|
||||
return value === 1 ? i18n.get('normal', this.config) : value + '×';
|
||||
|
||||
case 'quality':
|
||||
if (utils.is.number(value)) {
|
||||
return value + 'p';
|
||||
}
|
||||
|
||||
return utils.toTitleCase(value);
|
||||
|
||||
case 'captions':
|
||||
return controls.getLanguage.call(this);
|
||||
return captions.getLabel.call(this);
|
||||
|
||||
default:
|
||||
return null;
|
||||
@@ -3385,7 +3453,18 @@ var controls = {
|
||||
|
||||
switch (setting) {
|
||||
case 'captions':
|
||||
value = this.captions.active ? this.captions.language : i18n.get('disabled', this.config);
|
||||
if (this.captions.active) {
|
||||
if (this.options.captions.length > 2 || !this.options.captions.some(function (lang) {
|
||||
return lang === 'enabled';
|
||||
})) {
|
||||
value = this.captions.language;
|
||||
} else {
|
||||
value = 'enabled';
|
||||
}
|
||||
} else {
|
||||
value = '';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -3416,17 +3495,19 @@ var controls = {
|
||||
list = pane && pane.querySelector('ul');
|
||||
}
|
||||
|
||||
// Update the label
|
||||
if (!utils.is.empty(value)) {
|
||||
var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
// If there's no list it means it's not been rendered...
|
||||
if (!utils.is.element(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the radio option
|
||||
// Update the label
|
||||
var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
|
||||
// Find the radio option and check it
|
||||
var target = list && list.querySelector('input[value="' + value + '"]');
|
||||
|
||||
if (utils.is.element(target)) {
|
||||
// Check it
|
||||
target.checked = true;
|
||||
}
|
||||
},
|
||||
@@ -3470,22 +3551,6 @@ var controls = {
|
||||
|
||||
// Get current selected caption language
|
||||
// TODO: rework this to user the getter in the API?
|
||||
getLanguage: function getLanguage() {
|
||||
if (!this.supported.ui) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (support.textTracks && captions.getTracks.call(this).length && this.captions.active) {
|
||||
var currentTrack = captions.getCurrentTrack.call(this);
|
||||
|
||||
if (utils.is.track(currentTrack)) {
|
||||
return currentTrack.label;
|
||||
}
|
||||
}
|
||||
|
||||
return i18n.get('disabled', this.config);
|
||||
},
|
||||
|
||||
|
||||
// Set a list of available captions languages
|
||||
setCaptionsMenu: function setCaptionsMenu() {
|
||||
@@ -3496,22 +3561,25 @@ var controls = {
|
||||
var list = this.elements.settings.panes.captions.querySelector('ul');
|
||||
|
||||
// Toggle the pane and tab
|
||||
var hasTracks = captions.getTracks.call(this).length;
|
||||
controls.toggleTab.call(this, type, hasTracks);
|
||||
var toggle = captions.getTracks.call(this).length;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
|
||||
// If there's no captions, bail
|
||||
if (!hasTracks) {
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-map the tracks into just the data we need
|
||||
var tracks = captions.getTracks.call(this).map(function (track) {
|
||||
return {
|
||||
language: track.language,
|
||||
label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase()
|
||||
language: !utils.is.empty(track.language) ? track.language : 'enabled',
|
||||
label: captions.getLabel.call(_this3, track)
|
||||
};
|
||||
});
|
||||
|
||||
@@ -3523,7 +3591,12 @@ var controls = {
|
||||
|
||||
// Generate options
|
||||
tracks.forEach(function (track) {
|
||||
controls.createMenuItem.call(_this3, track.language, list, 'language', track.label || track.language, controls.createBadge.call(_this3, track.language.toUpperCase()), track.language.toLowerCase() === _this3.captions.language.toLowerCase());
|
||||
controls.createMenuItem.call(_this3, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this3, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this3.captions.language.toLowerCase());
|
||||
});
|
||||
|
||||
// Store reference
|
||||
this.options.captions = tracks.map(function (track) {
|
||||
return track.language;
|
||||
});
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
@@ -3547,10 +3620,10 @@ var controls = {
|
||||
var type = 'speed';
|
||||
|
||||
// Set the speed options
|
||||
if (!utils.is.array(options)) {
|
||||
this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
||||
} else {
|
||||
if (utils.is.array(options)) {
|
||||
this.options.speed = options;
|
||||
} else if (this.isHTML5 || this.isVimeo) {
|
||||
this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
||||
}
|
||||
|
||||
// Set options if passed and filter based on config
|
||||
@@ -3559,7 +3632,7 @@ var controls = {
|
||||
});
|
||||
|
||||
// Toggle the pane and tab
|
||||
var toggle = !utils.is.empty(this.options.speed);
|
||||
var toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
@@ -3573,16 +3646,13 @@ var controls = {
|
||||
// Get the list to populate
|
||||
var list = this.elements.settings.panes.speed.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
utils.toggleHidden(this.elements.settings.tabs.speed, false);
|
||||
utils.toggleHidden(this.elements.settings.panes.speed, false);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
// Create items
|
||||
this.options.speed.forEach(function (speed) {
|
||||
return controls.createMenuItem.call(_this4, speed, list, type, controls.getLabel.call(_this4, 'speed', speed));
|
||||
var label = controls.getLabel.call(_this4, 'speed', speed);
|
||||
controls.createMenuItem.call(_this4, speed, list, type, label);
|
||||
});
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
@@ -3612,7 +3682,7 @@ var controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true';
|
||||
var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
|
||||
|
||||
if (utils.is.event(event)) {
|
||||
var isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
@@ -3637,7 +3707,7 @@ var controls = {
|
||||
}
|
||||
|
||||
if (utils.is.element(form)) {
|
||||
form.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(form, !show);
|
||||
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||
|
||||
if (show) {
|
||||
@@ -3654,7 +3724,7 @@ var controls = {
|
||||
var clone = tab.cloneNode(true);
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
|
||||
@@ -3700,7 +3770,7 @@ var controls = {
|
||||
|
||||
// Hide all other tabs
|
||||
// Get other tabs
|
||||
var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]');
|
||||
var current = menu.querySelector('[role="tabpanel"]:not([hidden])');
|
||||
var container = current.parentNode;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
@@ -3741,11 +3811,11 @@ var controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
current.setAttribute('aria-hidden', true);
|
||||
utils.toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
pane.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(pane, !show);
|
||||
tab.setAttribute('aria-expanded', show);
|
||||
pane.removeAttribute('tabindex');
|
||||
|
||||
@@ -3866,7 +3936,8 @@ var controls = {
|
||||
// Settings button / menu
|
||||
if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {
|
||||
var menu = utils.createElement('div', {
|
||||
class: 'plyr__menu'
|
||||
class: 'plyr__menu',
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
menu.appendChild(controls.createButton.call(this, 'settings', {
|
||||
@@ -3879,7 +3950,7 @@ var controls = {
|
||||
var form = utils.createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: 'plyr-settings-' + data.id,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tablist',
|
||||
tabindex: -1
|
||||
@@ -3889,7 +3960,6 @@ var controls = {
|
||||
|
||||
var home = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-home',
|
||||
'aria-hidden': false,
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tabpanel'
|
||||
});
|
||||
@@ -3936,11 +4006,10 @@ var controls = {
|
||||
this.config.settings.forEach(function (type) {
|
||||
var pane = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-' + type,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
role: 'tabpanel',
|
||||
tabindex: -1,
|
||||
hidden: ''
|
||||
tabindex: -1
|
||||
});
|
||||
|
||||
var back = utils.createElement('button', {
|
||||
@@ -3991,12 +4060,12 @@ var controls = {
|
||||
|
||||
this.elements.controls = container;
|
||||
|
||||
controls.setSpeedMenu.call(this);
|
||||
|
||||
if (this.isHTML5) {
|
||||
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
||||
}
|
||||
|
||||
controls.setSpeedMenu.call(this);
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
@@ -4040,7 +4109,7 @@ var controls = {
|
||||
seektime: this.config.seekTime,
|
||||
speed: this.speed,
|
||||
quality: this.quality,
|
||||
captions: controls.getLanguage.call(this)
|
||||
captions: captions.getLabel.call(this)
|
||||
// TODO: Looping
|
||||
// loop: 'None',
|
||||
});
|
||||
@@ -4062,7 +4131,7 @@ var controls = {
|
||||
// Inject controls HTML
|
||||
if (utils.is.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else {
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
|
||||
@@ -4394,6 +4463,10 @@ var Listeners = function () {
|
||||
// If autoplay, then load advertisement if required
|
||||
// TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows
|
||||
utils.on(this.player.media, 'playing', function () {
|
||||
if (!_this3.player.ads) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If ads are enabled, wait for them first
|
||||
if (_this3.player.ads.enabled && !_this3.player.ads.initialized) {
|
||||
// Wait for manager response
|
||||
@@ -4435,7 +4508,7 @@ var Listeners = function () {
|
||||
|
||||
// Disable right click
|
||||
if (this.player.supported.ui && this.player.config.disableContextMenu) {
|
||||
utils.on(this.player.media, 'contextmenu', function (event) {
|
||||
utils.on(this.player.elements.wrapper, 'contextmenu', function (event) {
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
@@ -5721,7 +5794,11 @@ var youtube = {
|
||||
return Number(instance.getCurrentTime());
|
||||
},
|
||||
set: function set(time) {
|
||||
// Vimeo will automatically play on seek
|
||||
var paused = player.media.paused;
|
||||
|
||||
// Set seeking flag
|
||||
|
||||
player.media.seeking = true;
|
||||
|
||||
// Trigger seeking
|
||||
@@ -5729,6 +5806,11 @@ var youtube = {
|
||||
|
||||
// Seek after events sent
|
||||
instance.seekTo(time);
|
||||
|
||||
// Restore pause state
|
||||
if (paused) {
|
||||
player.pause();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5804,8 +5886,7 @@ var youtube = {
|
||||
});
|
||||
|
||||
// Get available speeds
|
||||
var options = instance.getAvailablePlaybackRates();
|
||||
controls.setSpeedMenu.call(player, options);
|
||||
player.options.speed = instance.getAvailablePlaybackRates();
|
||||
|
||||
// Set the tabindex to avoid focus entering iframe
|
||||
if (player.supported.ui) {
|
||||
@@ -5967,10 +6048,14 @@ var vimeo = {
|
||||
setAspectRatio: function setAspectRatio(input) {
|
||||
var ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');
|
||||
var padding = 100 / ratio[0] * ratio[1];
|
||||
var height = 240;
|
||||
var offset = (height - padding) / (height / 50);
|
||||
this.elements.wrapper.style.paddingBottom = padding + '%';
|
||||
this.media.style.transform = 'translateY(-' + offset + '%)';
|
||||
|
||||
if (this.supported.ui) {
|
||||
var height = 240;
|
||||
var offset = (height - padding) / (height / 50);
|
||||
|
||||
this.media.style.transform = 'translateY(-' + offset + '%)';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -5989,7 +6074,8 @@ var vimeo = {
|
||||
title: false,
|
||||
speed: true,
|
||||
transparent: 0,
|
||||
gesture: 'media'
|
||||
gesture: 'media',
|
||||
playsinline: !this.config.fullscreen.iosNative
|
||||
};
|
||||
var params = utils.buildUrlParams(options);
|
||||
|
||||
@@ -6023,6 +6109,11 @@ var vimeo = {
|
||||
player.media.paused = true;
|
||||
player.media.currentTime = 0;
|
||||
|
||||
// Disable native text track rendering
|
||||
if (player.supported.ui) {
|
||||
player.embed.disableTextTrack();
|
||||
}
|
||||
|
||||
// Create a faux HTML5 API using the Vimeo API
|
||||
player.media.play = function () {
|
||||
player.embed.play().then(function () {
|
||||
@@ -6061,7 +6152,9 @@ var vimeo = {
|
||||
utils.dispatchEvent.call(player, player.media, 'seeking');
|
||||
|
||||
// Seek after events
|
||||
player.embed.setCurrentTime(time);
|
||||
player.embed.setCurrentTime(time).catch(function () {
|
||||
// Do nothing
|
||||
});
|
||||
|
||||
// Restore pause state
|
||||
if (paused) {
|
||||
@@ -6241,6 +6334,15 @@ var vimeo = {
|
||||
if (parseInt(data.percent, 10) === 1) {
|
||||
utils.dispatchEvent.call(player, player.media, 'canplaythrough');
|
||||
}
|
||||
|
||||
// Get duration as if we do it before load, it gives an incorrect value
|
||||
// https://github.com/sampotts/plyr/issues/891
|
||||
player.embed.getDuration().then(function (value) {
|
||||
if (value !== player.media.duration) {
|
||||
player.media.duration = value;
|
||||
utils.dispatchEvent.call(player, player.media, 'durationchange');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
player.embed.on('seeked', function () {
|
||||
@@ -6392,7 +6494,7 @@ var source = {
|
||||
_this2.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;
|
||||
|
||||
// Check for support
|
||||
_this2.supported = support.check(_this2.type, _this2.provider, _this2.config.inline);
|
||||
_this2.supported = support.check(_this2.type, _this2.provider, _this2.config.playsinline);
|
||||
|
||||
// Create new markup
|
||||
switch (_this2.provider + ':' + _this2.type) {
|
||||
@@ -6440,7 +6542,7 @@ var source = {
|
||||
if (_this2.config.muted) {
|
||||
_this2.media.setAttribute('muted', '');
|
||||
}
|
||||
if (_this2.config.inline) {
|
||||
if (_this2.config.playsinline) {
|
||||
_this2.media.setAttribute('playsinline', '');
|
||||
}
|
||||
}
|
||||
@@ -6521,7 +6623,7 @@ var Plyr = function () {
|
||||
}
|
||||
|
||||
// Set config
|
||||
this.config = utils.extend({}, defaults, options, function () {
|
||||
this.config = utils.extend({}, defaults, options || {}, function () {
|
||||
try {
|
||||
return JSON.parse(_this.media.getAttribute('data-plyr-config'));
|
||||
} catch (e) {
|
||||
@@ -6558,7 +6660,8 @@ var Plyr = function () {
|
||||
// Options
|
||||
this.options = {
|
||||
speed: [],
|
||||
quality: []
|
||||
quality: [],
|
||||
captions: []
|
||||
};
|
||||
|
||||
// Debugging
|
||||
@@ -6643,12 +6746,17 @@ var Plyr = function () {
|
||||
if (truthy.includes(params.autoplay)) {
|
||||
this.config.autoplay = true;
|
||||
}
|
||||
if (truthy.includes(params.playsinline)) {
|
||||
this.config.inline = true;
|
||||
}
|
||||
if (truthy.includes(params.loop)) {
|
||||
this.config.loop.active = true;
|
||||
}
|
||||
|
||||
// TODO: replace fullscreen.iosNative with this playsinline config option
|
||||
// YouTube requires the playsinline in the URL
|
||||
if (this.isYouTube) {
|
||||
this.config.playsinline = truthy.includes(params.playsinline);
|
||||
} else {
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// <div> with attributes
|
||||
@@ -6682,7 +6790,7 @@ var Plyr = function () {
|
||||
this.config.autoplay = true;
|
||||
}
|
||||
if (this.media.hasAttribute('playsinline')) {
|
||||
this.config.inline = true;
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
if (this.media.hasAttribute('muted')) {
|
||||
this.config.muted = true;
|
||||
@@ -6699,7 +6807,7 @@ var Plyr = function () {
|
||||
}
|
||||
|
||||
// Check for support again but with type
|
||||
this.supported = support.check(this.type, this.provider, this.config.inline);
|
||||
this.supported = support.check(this.type, this.provider, this.config.playsinline);
|
||||
|
||||
// If no support for even API, bail
|
||||
if (!this.supported.api) {
|
||||
@@ -6919,13 +7027,13 @@ var Plyr = function () {
|
||||
* @param {boolean} input - Whether to enable captions
|
||||
*/
|
||||
value: function toggleCaptions(input) {
|
||||
// If there's no full support, or there's no caption toggle
|
||||
if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) {
|
||||
// If there's no full support
|
||||
if (!this.supported.ui) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the method is called without parameter, toggle based on current value
|
||||
var show = utils.is.boolean(input) ? input : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;
|
||||
var show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);
|
||||
|
||||
// Nothing to change...
|
||||
if (this.captions.active === show) {
|
||||
@@ -7284,7 +7392,7 @@ var Plyr = function () {
|
||||
}, {
|
||||
key: 'playing',
|
||||
get: function get$$1() {
|
||||
return Boolean(!this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true));
|
||||
return Boolean(this.ready && !this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7313,7 +7421,7 @@ var Plyr = function () {
|
||||
}
|
||||
|
||||
// Set
|
||||
this.media.currentTime = parseFloat(targetTime.toFixed(4));
|
||||
this.media.currentTime = targetTime;
|
||||
|
||||
// Logging
|
||||
this.debug.log('Seeking to ' + this.currentTime + ' seconds');
|
||||
@@ -7370,7 +7478,7 @@ var Plyr = function () {
|
||||
key: 'duration',
|
||||
get: function get$$1() {
|
||||
// Faux duration set via config
|
||||
var fauxDuration = parseInt(this.config.duration, 10);
|
||||
var fauxDuration = parseFloat(this.config.duration);
|
||||
|
||||
// True duration
|
||||
var realDuration = this.media ? Number(this.media.duration) : 0;
|
||||
@@ -7560,11 +7668,16 @@ var Plyr = function () {
|
||||
quality = this.config.quality.default;
|
||||
}
|
||||
|
||||
if (!this.options.quality.includes(quality)) {
|
||||
this.debug.warn('Unsupported quality option (' + quality + ')');
|
||||
if (!this.options.quality.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.quality.includes(quality)) {
|
||||
var closest = utils.closest(this.options.quality, quality);
|
||||
this.debug.warn('Unsupported quality option: ' + quality + ', using ' + closest + ' instead');
|
||||
quality = closest;
|
||||
}
|
||||
|
||||
// Update config
|
||||
this.config.quality.selected = quality;
|
||||
|
||||
@@ -7716,17 +7829,29 @@ var Plyr = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle captions based on input
|
||||
this.toggleCaptions(!utils.is.empty(input));
|
||||
|
||||
// If empty string is passed, assume disable captions
|
||||
if (utils.is.empty(input)) {
|
||||
this.toggleCaptions(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize
|
||||
var language = input.toLowerCase();
|
||||
|
||||
// Check for support
|
||||
if (!this.options.captions.includes(language)) {
|
||||
this.debug.warn('Unsupported language option: ' + language);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure captions are enabled
|
||||
this.toggleCaptions(true);
|
||||
|
||||
// Enabled only
|
||||
if (language === 'enabled') {
|
||||
return;
|
||||
}
|
||||
|
||||
// If nothing to change, bail
|
||||
if (this.language === language) {
|
||||
return;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+295
-170
@@ -5117,14 +5117,14 @@ var defaults = {
|
||||
// Sprite (for icons)
|
||||
loadSprite: true,
|
||||
iconPrefix: 'plyr',
|
||||
iconUrl: 'https://cdn.plyr.io/3.1.0-beta.1/plyr.svg',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.2/plyr.svg',
|
||||
|
||||
// Blank video (used to prevent errors on source change)
|
||||
blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
|
||||
|
||||
// Quality default
|
||||
quality: {
|
||||
default: 720,
|
||||
default: 576,
|
||||
options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240, 'default']
|
||||
},
|
||||
|
||||
@@ -5156,7 +5156,7 @@ var defaults = {
|
||||
// Captions settings
|
||||
captions: {
|
||||
active: false,
|
||||
language: window.navigator.language.split('-')[0]
|
||||
language: (navigator.language || navigator.userLanguage).split('-')[0]
|
||||
},
|
||||
|
||||
// Fullscreen settings
|
||||
@@ -5204,6 +5204,7 @@ var defaults = {
|
||||
captions: 'Captions',
|
||||
settings: 'Settings',
|
||||
speed: 'Speed',
|
||||
normal: 'Normal',
|
||||
quality: 'Quality',
|
||||
loop: 'Loop',
|
||||
start: 'Start',
|
||||
@@ -5211,6 +5212,7 @@ var defaults = {
|
||||
all: 'All',
|
||||
reset: 'Reset',
|
||||
disabled: 'Disabled',
|
||||
enabled: 'Enabled',
|
||||
advertisement: 'Ad'
|
||||
},
|
||||
|
||||
@@ -6133,6 +6135,26 @@ var utils = {
|
||||
},
|
||||
|
||||
|
||||
// Toggle hidden
|
||||
toggleHidden: function toggleHidden(element, hidden) {
|
||||
if (!utils.is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var hide = hidden;
|
||||
|
||||
if (!utils.is.boolean(hide)) {
|
||||
hide = !element.hasAttribute('hidden');
|
||||
}
|
||||
|
||||
if (hide) {
|
||||
element.setAttribute('hidden', '');
|
||||
} else {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Toggle class on an element
|
||||
toggleClass: function toggleClass(element, className, toggle) {
|
||||
if (utils.is.element(element)) {
|
||||
@@ -6153,20 +6175,6 @@ var utils = {
|
||||
},
|
||||
|
||||
|
||||
// Toggle hidden attribute on an element
|
||||
toggleHidden: function toggleHidden(element, toggle) {
|
||||
if (!utils.is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
element.setAttribute('hidden', '');
|
||||
} else {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Element matches selector
|
||||
matches: function matches(element, selector) {
|
||||
var prototype = { Element: Element };
|
||||
@@ -6576,6 +6584,18 @@ var utils = {
|
||||
},
|
||||
|
||||
|
||||
// Get the closest value in an array
|
||||
closest: function closest(array, value) {
|
||||
if (!utils.is.array(array) || !array.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array.reduce(function (prev, curr) {
|
||||
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// Get the provider for a given URL
|
||||
getProviderByUrl: function getProviderByUrl(url) {
|
||||
// YouTube
|
||||
@@ -6724,16 +6744,16 @@ var support = {
|
||||
|
||||
// Check for support
|
||||
// Basic functionality vs full UI
|
||||
check: function check(type, provider, inline) {
|
||||
check: function check(type, provider, playsinline) {
|
||||
var api = false;
|
||||
var ui = false;
|
||||
var browser = utils.getBrowser();
|
||||
var playsInline = browser.isIPhone && inline && support.inline;
|
||||
var canPlayInline = browser.isIPhone && playsinline && support.playsinline;
|
||||
|
||||
switch (provider + ':' + type) {
|
||||
case 'html5:video':
|
||||
api = support.video;
|
||||
ui = api && support.rangeInput && (!browser.isIPhone || playsInline);
|
||||
ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);
|
||||
break;
|
||||
|
||||
case 'html5:audio':
|
||||
@@ -6744,7 +6764,7 @@ var support = {
|
||||
case 'youtube:video':
|
||||
case 'vimeo:video':
|
||||
api = true;
|
||||
ui = support.rangeInput && (!browser.isIPhone || playsInline);
|
||||
ui = support.rangeInput && (!browser.isIPhone || canPlayInline);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -6772,7 +6792,7 @@ var support = {
|
||||
|
||||
// Inline playback support
|
||||
// https://webkit.org/blog/6784/new-video-policies-for-ios/
|
||||
inline: 'playsInline' in document.createElement('video'),
|
||||
playsinline: 'playsInline' in document.createElement('video'),
|
||||
|
||||
// Check for mime type support against a player instance
|
||||
// Credits: http://diveintohtml5.info/everything.html
|
||||
@@ -6985,13 +7005,13 @@ var Fullscreen = function () {
|
||||
});
|
||||
|
||||
// Fullscreen toggle on double click
|
||||
utils.on(this.player.elements.container, 'dblclick', function () {
|
||||
_this.toggle();
|
||||
});
|
||||
utils.on(this.player.elements.container, 'dblclick', function (event) {
|
||||
// Ignore double click in controls
|
||||
if (_this.player.elements.controls.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent double click on controls bubbling up
|
||||
utils.on(this.player.elements.controls, 'dblclick', function (event) {
|
||||
return event.stopPropagation();
|
||||
_this.toggle();
|
||||
});
|
||||
|
||||
// Update the UI
|
||||
@@ -7056,7 +7076,7 @@ var Fullscreen = function () {
|
||||
} else if (!Fullscreen.native) {
|
||||
toggleFallback.call(this, false);
|
||||
} else if (!this.prefix) {
|
||||
document.cancelFullScreen();
|
||||
(document.cancelFullScreen || document.exitFullscreen).call(document);
|
||||
} else if (!utils.is.empty(this.prefix)) {
|
||||
var action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
||||
document['' + this.prefix + action + this.name]();
|
||||
@@ -7122,7 +7142,7 @@ var Fullscreen = function () {
|
||||
get: function get() {
|
||||
// No prefix
|
||||
if (utils.is.function(document.exitFullscreen)) {
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Check for fullscreen support by vendor prefix
|
||||
@@ -7151,6 +7171,36 @@ var Fullscreen = function () {
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var i18n = {
|
||||
get: function get() {
|
||||
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
|
||||
if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var string = config.i18n[key];
|
||||
|
||||
var replace = {
|
||||
'{seektime}': config.seekTime,
|
||||
'{title}': config.title
|
||||
};
|
||||
|
||||
Object.entries(replace).forEach(function (_ref) {
|
||||
var _ref2 = slicedToArray(_ref, 2),
|
||||
key = _ref2[0],
|
||||
value = _ref2[1];
|
||||
|
||||
string = utils.replaceAll(string, key, value);
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var captions = {
|
||||
// Setup captions
|
||||
setup: function setup() {
|
||||
@@ -7190,6 +7240,7 @@ var captions = {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Inject the container
|
||||
if (!utils.is.element(this.elements.captions)) {
|
||||
this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));
|
||||
@@ -7294,9 +7345,54 @@ var captions = {
|
||||
getCurrentTrack: function getCurrentTrack() {
|
||||
var _this2 = this;
|
||||
|
||||
return captions.getTracks.call(this).find(function (track) {
|
||||
var tracks = captions.getTracks.call(this);
|
||||
|
||||
if (!tracks.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get track based on current language
|
||||
var track = tracks.find(function (track) {
|
||||
return track.language.toLowerCase() === _this2.language;
|
||||
});
|
||||
|
||||
// Get the <track> with default attribute
|
||||
if (!track) {
|
||||
track = utils.getElement.call(this, 'track[default]');
|
||||
}
|
||||
|
||||
// Get the first track
|
||||
if (!track) {
|
||||
var _tracks = slicedToArray(tracks, 1);
|
||||
|
||||
track = _tracks[0];
|
||||
}
|
||||
|
||||
return track;
|
||||
},
|
||||
|
||||
|
||||
// Get UI label for track
|
||||
getLabel: function getLabel(track) {
|
||||
var currentTrack = track;
|
||||
|
||||
if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {
|
||||
currentTrack = captions.getCurrentTrack.call(this);
|
||||
}
|
||||
|
||||
if (utils.is.track(currentTrack)) {
|
||||
if (!utils.is.empty(currentTrack.label)) {
|
||||
return currentTrack.label;
|
||||
}
|
||||
|
||||
if (!utils.is.empty(currentTrack.language)) {
|
||||
return track.language.toUpperCase();
|
||||
}
|
||||
|
||||
return i18n.get('enabled', this.config);
|
||||
}
|
||||
|
||||
return i18n.get('disabled', this.config);
|
||||
},
|
||||
|
||||
|
||||
@@ -7358,11 +7454,6 @@ var captions = {
|
||||
|
||||
// Display captions container and button (for initialization)
|
||||
show: function show() {
|
||||
// If there's no caption toggle, bail
|
||||
if (!utils.is.element(this.elements.buttons.captions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to load the value from storage
|
||||
var active = this.storage.get('captions');
|
||||
|
||||
@@ -7382,36 +7473,6 @@ var captions = {
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var i18n = {
|
||||
get: function get() {
|
||||
var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
|
||||
if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var string = config.i18n[key];
|
||||
|
||||
var replace = {
|
||||
'{seektime}': config.seekTime,
|
||||
'{title}': config.title
|
||||
};
|
||||
|
||||
Object.entries(replace).forEach(function (_ref) {
|
||||
var _ref2 = slicedToArray(_ref, 2),
|
||||
key = _ref2[0],
|
||||
value = _ref2[1];
|
||||
|
||||
string = utils.replaceAll(string, key, value);
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
var ui = {
|
||||
addStyleHook: function addStyleHook() {
|
||||
utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);
|
||||
@@ -7914,11 +7975,6 @@ var browser$1 = utils.getBrowser();
|
||||
var controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill: function updateRangeFill(target) {
|
||||
// WebKit only
|
||||
if (!browser$1.isWebkit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get range from event if event passed
|
||||
var range = utils.is.event(target) ? target.target : target;
|
||||
|
||||
@@ -7927,6 +7983,14 @@ var controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set aria value for https://github.com/sampotts/plyr/issues/905
|
||||
range.setAttribute('aria-valuenow', range.value);
|
||||
|
||||
// WebKit only
|
||||
if (!browser$1.isWebkit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set CSS custom property
|
||||
range.style.setProperty('--value', range.value / range.max * 100 + '%');
|
||||
},
|
||||
@@ -7950,7 +8014,8 @@ var controls = {
|
||||
// Create <svg>
|
||||
var icon = document.createElementNS(namespace, 'svg');
|
||||
utils.setAttributes(icon, utils.extend(attributes, {
|
||||
role: 'presentation'
|
||||
role: 'presentation',
|
||||
focusable: 'false'
|
||||
}));
|
||||
|
||||
// Create the <use> to reference sprite
|
||||
@@ -8132,6 +8197,7 @@ var controls = {
|
||||
// Seek label
|
||||
var label = utils.createElement('label', {
|
||||
for: attributes.id,
|
||||
id: attributes.id + '-label',
|
||||
class: this.config.classNames.hidden
|
||||
}, i18n.get(type, this.config));
|
||||
|
||||
@@ -8142,7 +8208,13 @@ var controls = {
|
||||
max: 100,
|
||||
step: 0.01,
|
||||
value: 0,
|
||||
autocomplete: 'off'
|
||||
autocomplete: 'off',
|
||||
// A11y fixes for https://github.com/sampotts/plyr/issues/905
|
||||
role: 'slider',
|
||||
'aria-labelledby': attributes.id + '-label',
|
||||
'aria-valuemin': 0,
|
||||
'aria-valuemax': 100,
|
||||
'aria-valuenow': 0
|
||||
}, attributes));
|
||||
|
||||
this.elements.inputs[type] = input;
|
||||
@@ -8162,7 +8234,9 @@ var controls = {
|
||||
var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), {
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: 0
|
||||
value: 0,
|
||||
role: 'presentation',
|
||||
'aria-hidden': true
|
||||
}, attributes));
|
||||
|
||||
// Create the label inside
|
||||
@@ -8229,7 +8303,7 @@ var controls = {
|
||||
class: 'plyr__sr-only'
|
||||
}));
|
||||
|
||||
var faux = utils.createElement('span', { 'aria-hidden': true });
|
||||
var faux = utils.createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
@@ -8300,11 +8374,7 @@ var controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab: function toggleTab(setting, toggle) {
|
||||
var tab = this.elements.settings.tabs[setting];
|
||||
var pane = this.elements.settings.panes[setting];
|
||||
|
||||
utils.toggleHidden(tab, !toggle);
|
||||
utils.toggleHidden(pane, !toggle);
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
|
||||
@@ -8332,6 +8402,9 @@ var controls = {
|
||||
var toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
|
||||
// If we're hiding, nothing more to do
|
||||
if (!toggle) {
|
||||
return;
|
||||
@@ -8350,13 +8423,7 @@ var controls = {
|
||||
break;
|
||||
|
||||
case 1440:
|
||||
label = 'WQHD';
|
||||
break;
|
||||
|
||||
case 1080:
|
||||
label = 'HD';
|
||||
break;
|
||||
|
||||
case 720:
|
||||
label = 'HD';
|
||||
break;
|
||||
@@ -8394,16 +8461,17 @@ var controls = {
|
||||
getLabel: function getLabel(setting, value) {
|
||||
switch (setting) {
|
||||
case 'speed':
|
||||
return value === 1 ? 'Normal' : value + '×';
|
||||
return value === 1 ? i18n.get('normal', this.config) : value + '×';
|
||||
|
||||
case 'quality':
|
||||
if (utils.is.number(value)) {
|
||||
return value + 'p';
|
||||
}
|
||||
|
||||
return utils.toTitleCase(value);
|
||||
|
||||
case 'captions':
|
||||
return controls.getLanguage.call(this);
|
||||
return captions.getLabel.call(this);
|
||||
|
||||
default:
|
||||
return null;
|
||||
@@ -8419,7 +8487,18 @@ var controls = {
|
||||
|
||||
switch (setting) {
|
||||
case 'captions':
|
||||
value = this.captions.active ? this.captions.language : i18n.get('disabled', this.config);
|
||||
if (this.captions.active) {
|
||||
if (this.options.captions.length > 2 || !this.options.captions.some(function (lang) {
|
||||
return lang === 'enabled';
|
||||
})) {
|
||||
value = this.captions.language;
|
||||
} else {
|
||||
value = 'enabled';
|
||||
}
|
||||
} else {
|
||||
value = '';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -8450,17 +8529,19 @@ var controls = {
|
||||
list = pane && pane.querySelector('ul');
|
||||
}
|
||||
|
||||
// Update the label
|
||||
if (!utils.is.empty(value)) {
|
||||
var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
// If there's no list it means it's not been rendered...
|
||||
if (!utils.is.element(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the radio option
|
||||
// Update the label
|
||||
var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
|
||||
// Find the radio option and check it
|
||||
var target = list && list.querySelector('input[value="' + value + '"]');
|
||||
|
||||
if (utils.is.element(target)) {
|
||||
// Check it
|
||||
target.checked = true;
|
||||
}
|
||||
},
|
||||
@@ -8504,22 +8585,6 @@ var controls = {
|
||||
|
||||
// Get current selected caption language
|
||||
// TODO: rework this to user the getter in the API?
|
||||
getLanguage: function getLanguage() {
|
||||
if (!this.supported.ui) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (support.textTracks && captions.getTracks.call(this).length && this.captions.active) {
|
||||
var currentTrack = captions.getCurrentTrack.call(this);
|
||||
|
||||
if (utils.is.track(currentTrack)) {
|
||||
return currentTrack.label;
|
||||
}
|
||||
}
|
||||
|
||||
return i18n.get('disabled', this.config);
|
||||
},
|
||||
|
||||
|
||||
// Set a list of available captions languages
|
||||
setCaptionsMenu: function setCaptionsMenu() {
|
||||
@@ -8530,22 +8595,25 @@ var controls = {
|
||||
var list = this.elements.settings.panes.captions.querySelector('ul');
|
||||
|
||||
// Toggle the pane and tab
|
||||
var hasTracks = captions.getTracks.call(this).length;
|
||||
controls.toggleTab.call(this, type, hasTracks);
|
||||
var toggle = captions.getTracks.call(this).length;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
|
||||
// If there's no captions, bail
|
||||
if (!hasTracks) {
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-map the tracks into just the data we need
|
||||
var tracks = captions.getTracks.call(this).map(function (track) {
|
||||
return {
|
||||
language: track.language,
|
||||
label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase()
|
||||
language: !utils.is.empty(track.language) ? track.language : 'enabled',
|
||||
label: captions.getLabel.call(_this3, track)
|
||||
};
|
||||
});
|
||||
|
||||
@@ -8557,7 +8625,12 @@ var controls = {
|
||||
|
||||
// Generate options
|
||||
tracks.forEach(function (track) {
|
||||
controls.createMenuItem.call(_this3, track.language, list, 'language', track.label || track.language, controls.createBadge.call(_this3, track.language.toUpperCase()), track.language.toLowerCase() === _this3.captions.language.toLowerCase());
|
||||
controls.createMenuItem.call(_this3, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this3, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this3.captions.language.toLowerCase());
|
||||
});
|
||||
|
||||
// Store reference
|
||||
this.options.captions = tracks.map(function (track) {
|
||||
return track.language;
|
||||
});
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
@@ -8581,10 +8654,10 @@ var controls = {
|
||||
var type = 'speed';
|
||||
|
||||
// Set the speed options
|
||||
if (!utils.is.array(options)) {
|
||||
this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
||||
} else {
|
||||
if (utils.is.array(options)) {
|
||||
this.options.speed = options;
|
||||
} else if (this.isHTML5 || this.isVimeo) {
|
||||
this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
||||
}
|
||||
|
||||
// Set options if passed and filter based on config
|
||||
@@ -8593,7 +8666,7 @@ var controls = {
|
||||
});
|
||||
|
||||
// Toggle the pane and tab
|
||||
var toggle = !utils.is.empty(this.options.speed);
|
||||
var toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
@@ -8607,16 +8680,13 @@ var controls = {
|
||||
// Get the list to populate
|
||||
var list = this.elements.settings.panes.speed.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
utils.toggleHidden(this.elements.settings.tabs.speed, false);
|
||||
utils.toggleHidden(this.elements.settings.panes.speed, false);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
// Create items
|
||||
this.options.speed.forEach(function (speed) {
|
||||
return controls.createMenuItem.call(_this4, speed, list, type, controls.getLabel.call(_this4, 'speed', speed));
|
||||
var label = controls.getLabel.call(_this4, 'speed', speed);
|
||||
controls.createMenuItem.call(_this4, speed, list, type, label);
|
||||
});
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
@@ -8646,7 +8716,7 @@ var controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true';
|
||||
var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
|
||||
|
||||
if (utils.is.event(event)) {
|
||||
var isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
@@ -8671,7 +8741,7 @@ var controls = {
|
||||
}
|
||||
|
||||
if (utils.is.element(form)) {
|
||||
form.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(form, !show);
|
||||
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||
|
||||
if (show) {
|
||||
@@ -8688,7 +8758,7 @@ var controls = {
|
||||
var clone = tab.cloneNode(true);
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
|
||||
@@ -8734,7 +8804,7 @@ var controls = {
|
||||
|
||||
// Hide all other tabs
|
||||
// Get other tabs
|
||||
var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]');
|
||||
var current = menu.querySelector('[role="tabpanel"]:not([hidden])');
|
||||
var container = current.parentNode;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
@@ -8775,11 +8845,11 @@ var controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
current.setAttribute('aria-hidden', true);
|
||||
utils.toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
pane.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(pane, !show);
|
||||
tab.setAttribute('aria-expanded', show);
|
||||
pane.removeAttribute('tabindex');
|
||||
|
||||
@@ -8900,7 +8970,8 @@ var controls = {
|
||||
// Settings button / menu
|
||||
if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {
|
||||
var menu = utils.createElement('div', {
|
||||
class: 'plyr__menu'
|
||||
class: 'plyr__menu',
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
menu.appendChild(controls.createButton.call(this, 'settings', {
|
||||
@@ -8913,7 +8984,7 @@ var controls = {
|
||||
var form = utils.createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: 'plyr-settings-' + data.id,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tablist',
|
||||
tabindex: -1
|
||||
@@ -8923,7 +8994,6 @@ var controls = {
|
||||
|
||||
var home = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-home',
|
||||
'aria-hidden': false,
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tabpanel'
|
||||
});
|
||||
@@ -8970,11 +9040,10 @@ var controls = {
|
||||
this.config.settings.forEach(function (type) {
|
||||
var pane = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-' + type,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
role: 'tabpanel',
|
||||
tabindex: -1,
|
||||
hidden: ''
|
||||
tabindex: -1
|
||||
});
|
||||
|
||||
var back = utils.createElement('button', {
|
||||
@@ -9025,12 +9094,12 @@ var controls = {
|
||||
|
||||
this.elements.controls = container;
|
||||
|
||||
controls.setSpeedMenu.call(this);
|
||||
|
||||
if (this.isHTML5) {
|
||||
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
||||
}
|
||||
|
||||
controls.setSpeedMenu.call(this);
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
@@ -9074,7 +9143,7 @@ var controls = {
|
||||
seektime: this.config.seekTime,
|
||||
speed: this.speed,
|
||||
quality: this.quality,
|
||||
captions: controls.getLanguage.call(this)
|
||||
captions: captions.getLabel.call(this)
|
||||
// TODO: Looping
|
||||
// loop: 'None',
|
||||
});
|
||||
@@ -9096,7 +9165,7 @@ var controls = {
|
||||
// Inject controls HTML
|
||||
if (utils.is.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else {
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
|
||||
@@ -9428,6 +9497,10 @@ var Listeners = function () {
|
||||
// If autoplay, then load advertisement if required
|
||||
// TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows
|
||||
utils.on(this.player.media, 'playing', function () {
|
||||
if (!_this3.player.ads) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If ads are enabled, wait for them first
|
||||
if (_this3.player.ads.enabled && !_this3.player.ads.initialized) {
|
||||
// Wait for manager response
|
||||
@@ -9469,7 +9542,7 @@ var Listeners = function () {
|
||||
|
||||
// Disable right click
|
||||
if (this.player.supported.ui && this.player.config.disableContextMenu) {
|
||||
utils.on(this.player.media, 'contextmenu', function (event) {
|
||||
utils.on(this.player.elements.wrapper, 'contextmenu', function (event) {
|
||||
event.preventDefault();
|
||||
}, false);
|
||||
}
|
||||
@@ -10755,7 +10828,11 @@ var youtube = {
|
||||
return Number(instance.getCurrentTime());
|
||||
},
|
||||
set: function set(time) {
|
||||
// Vimeo will automatically play on seek
|
||||
var paused = player.media.paused;
|
||||
|
||||
// Set seeking flag
|
||||
|
||||
player.media.seeking = true;
|
||||
|
||||
// Trigger seeking
|
||||
@@ -10763,6 +10840,11 @@ var youtube = {
|
||||
|
||||
// Seek after events sent
|
||||
instance.seekTo(time);
|
||||
|
||||
// Restore pause state
|
||||
if (paused) {
|
||||
player.pause();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10838,8 +10920,7 @@ var youtube = {
|
||||
});
|
||||
|
||||
// Get available speeds
|
||||
var options = instance.getAvailablePlaybackRates();
|
||||
controls.setSpeedMenu.call(player, options);
|
||||
player.options.speed = instance.getAvailablePlaybackRates();
|
||||
|
||||
// Set the tabindex to avoid focus entering iframe
|
||||
if (player.supported.ui) {
|
||||
@@ -11001,10 +11082,14 @@ var vimeo = {
|
||||
setAspectRatio: function setAspectRatio(input) {
|
||||
var ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');
|
||||
var padding = 100 / ratio[0] * ratio[1];
|
||||
var height = 240;
|
||||
var offset = (height - padding) / (height / 50);
|
||||
this.elements.wrapper.style.paddingBottom = padding + '%';
|
||||
this.media.style.transform = 'translateY(-' + offset + '%)';
|
||||
|
||||
if (this.supported.ui) {
|
||||
var height = 240;
|
||||
var offset = (height - padding) / (height / 50);
|
||||
|
||||
this.media.style.transform = 'translateY(-' + offset + '%)';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -11023,7 +11108,8 @@ var vimeo = {
|
||||
title: false,
|
||||
speed: true,
|
||||
transparent: 0,
|
||||
gesture: 'media'
|
||||
gesture: 'media',
|
||||
playsinline: !this.config.fullscreen.iosNative
|
||||
};
|
||||
var params = utils.buildUrlParams(options);
|
||||
|
||||
@@ -11057,6 +11143,11 @@ var vimeo = {
|
||||
player.media.paused = true;
|
||||
player.media.currentTime = 0;
|
||||
|
||||
// Disable native text track rendering
|
||||
if (player.supported.ui) {
|
||||
player.embed.disableTextTrack();
|
||||
}
|
||||
|
||||
// Create a faux HTML5 API using the Vimeo API
|
||||
player.media.play = function () {
|
||||
player.embed.play().then(function () {
|
||||
@@ -11095,7 +11186,9 @@ var vimeo = {
|
||||
utils.dispatchEvent.call(player, player.media, 'seeking');
|
||||
|
||||
// Seek after events
|
||||
player.embed.setCurrentTime(time);
|
||||
player.embed.setCurrentTime(time).catch(function () {
|
||||
// Do nothing
|
||||
});
|
||||
|
||||
// Restore pause state
|
||||
if (paused) {
|
||||
@@ -11275,6 +11368,15 @@ var vimeo = {
|
||||
if (parseInt(data.percent, 10) === 1) {
|
||||
utils.dispatchEvent.call(player, player.media, 'canplaythrough');
|
||||
}
|
||||
|
||||
// Get duration as if we do it before load, it gives an incorrect value
|
||||
// https://github.com/sampotts/plyr/issues/891
|
||||
player.embed.getDuration().then(function (value) {
|
||||
if (value !== player.media.duration) {
|
||||
player.media.duration = value;
|
||||
utils.dispatchEvent.call(player, player.media, 'durationchange');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
player.embed.on('seeked', function () {
|
||||
@@ -11426,7 +11528,7 @@ var source = {
|
||||
_this2.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;
|
||||
|
||||
// Check for support
|
||||
_this2.supported = support.check(_this2.type, _this2.provider, _this2.config.inline);
|
||||
_this2.supported = support.check(_this2.type, _this2.provider, _this2.config.playsinline);
|
||||
|
||||
// Create new markup
|
||||
switch (_this2.provider + ':' + _this2.type) {
|
||||
@@ -11474,7 +11576,7 @@ var source = {
|
||||
if (_this2.config.muted) {
|
||||
_this2.media.setAttribute('muted', '');
|
||||
}
|
||||
if (_this2.config.inline) {
|
||||
if (_this2.config.playsinline) {
|
||||
_this2.media.setAttribute('playsinline', '');
|
||||
}
|
||||
}
|
||||
@@ -11555,7 +11657,7 @@ var Plyr = function () {
|
||||
}
|
||||
|
||||
// Set config
|
||||
this.config = utils.extend({}, defaults, options, function () {
|
||||
this.config = utils.extend({}, defaults, options || {}, function () {
|
||||
try {
|
||||
return JSON.parse(_this.media.getAttribute('data-plyr-config'));
|
||||
} catch (e) {
|
||||
@@ -11592,7 +11694,8 @@ var Plyr = function () {
|
||||
// Options
|
||||
this.options = {
|
||||
speed: [],
|
||||
quality: []
|
||||
quality: [],
|
||||
captions: []
|
||||
};
|
||||
|
||||
// Debugging
|
||||
@@ -11677,12 +11780,17 @@ var Plyr = function () {
|
||||
if (truthy.includes(params.autoplay)) {
|
||||
this.config.autoplay = true;
|
||||
}
|
||||
if (truthy.includes(params.playsinline)) {
|
||||
this.config.inline = true;
|
||||
}
|
||||
if (truthy.includes(params.loop)) {
|
||||
this.config.loop.active = true;
|
||||
}
|
||||
|
||||
// TODO: replace fullscreen.iosNative with this playsinline config option
|
||||
// YouTube requires the playsinline in the URL
|
||||
if (this.isYouTube) {
|
||||
this.config.playsinline = truthy.includes(params.playsinline);
|
||||
} else {
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// <div> with attributes
|
||||
@@ -11716,7 +11824,7 @@ var Plyr = function () {
|
||||
this.config.autoplay = true;
|
||||
}
|
||||
if (this.media.hasAttribute('playsinline')) {
|
||||
this.config.inline = true;
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
if (this.media.hasAttribute('muted')) {
|
||||
this.config.muted = true;
|
||||
@@ -11733,7 +11841,7 @@ var Plyr = function () {
|
||||
}
|
||||
|
||||
// Check for support again but with type
|
||||
this.supported = support.check(this.type, this.provider, this.config.inline);
|
||||
this.supported = support.check(this.type, this.provider, this.config.playsinline);
|
||||
|
||||
// If no support for even API, bail
|
||||
if (!this.supported.api) {
|
||||
@@ -11953,13 +12061,13 @@ var Plyr = function () {
|
||||
* @param {boolean} input - Whether to enable captions
|
||||
*/
|
||||
value: function toggleCaptions(input) {
|
||||
// If there's no full support, or there's no caption toggle
|
||||
if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) {
|
||||
// If there's no full support
|
||||
if (!this.supported.ui) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the method is called without parameter, toggle based on current value
|
||||
var show = utils.is.boolean(input) ? input : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;
|
||||
var show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);
|
||||
|
||||
// Nothing to change...
|
||||
if (this.captions.active === show) {
|
||||
@@ -12318,7 +12426,7 @@ var Plyr = function () {
|
||||
}, {
|
||||
key: 'playing',
|
||||
get: function get() {
|
||||
return Boolean(!this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true));
|
||||
return Boolean(this.ready && !this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -12347,7 +12455,7 @@ var Plyr = function () {
|
||||
}
|
||||
|
||||
// Set
|
||||
this.media.currentTime = parseFloat(targetTime.toFixed(4));
|
||||
this.media.currentTime = targetTime;
|
||||
|
||||
// Logging
|
||||
this.debug.log('Seeking to ' + this.currentTime + ' seconds');
|
||||
@@ -12404,7 +12512,7 @@ var Plyr = function () {
|
||||
key: 'duration',
|
||||
get: function get() {
|
||||
// Faux duration set via config
|
||||
var fauxDuration = parseInt(this.config.duration, 10);
|
||||
var fauxDuration = parseFloat(this.config.duration);
|
||||
|
||||
// True duration
|
||||
var realDuration = this.media ? Number(this.media.duration) : 0;
|
||||
@@ -12594,11 +12702,16 @@ var Plyr = function () {
|
||||
quality = this.config.quality.default;
|
||||
}
|
||||
|
||||
if (!this.options.quality.includes(quality)) {
|
||||
this.debug.warn('Unsupported quality option (' + quality + ')');
|
||||
if (!this.options.quality.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.quality.includes(quality)) {
|
||||
var closest = utils.closest(this.options.quality, quality);
|
||||
this.debug.warn('Unsupported quality option: ' + quality + ', using ' + closest + ' instead');
|
||||
quality = closest;
|
||||
}
|
||||
|
||||
// Update config
|
||||
this.config.quality.selected = quality;
|
||||
|
||||
@@ -12750,17 +12863,29 @@ var Plyr = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle captions based on input
|
||||
this.toggleCaptions(!utils.is.empty(input));
|
||||
|
||||
// If empty string is passed, assume disable captions
|
||||
if (utils.is.empty(input)) {
|
||||
this.toggleCaptions(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize
|
||||
var language = input.toLowerCase();
|
||||
|
||||
// Check for support
|
||||
if (!this.options.captions.includes(language)) {
|
||||
this.debug.warn('Unsupported language option: ' + language);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure captions are enabled
|
||||
this.toggleCaptions(true);
|
||||
|
||||
// Enabled only
|
||||
if (language === 'enabled') {
|
||||
return;
|
||||
}
|
||||
|
||||
// If nothing to change, bail
|
||||
if (this.language === language) {
|
||||
return;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+7
-7
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "plyr",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.2.2",
|
||||
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||
"homepage": "https://plyr.io",
|
||||
"main": "./dist/plyr.js",
|
||||
@@ -9,14 +9,14 @@
|
||||
"style": "./dist/plyr.css",
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-eslint": "^8.2.2",
|
||||
"babel-eslint": "^8.2.3",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"del": "^3.0.0",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-import": "^2.10.0",
|
||||
"eslint-plugin-import": "^2.11.0",
|
||||
"git-branch": "^2.0.1",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^5.0.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-replace": "^0.6.1",
|
||||
"gulp-s3": "^0.11.0",
|
||||
"gulp-sass": "^3.2.1",
|
||||
"gulp-sass": "^4.0.1",
|
||||
"gulp-size": "^3.0.0",
|
||||
"gulp-sourcemaps": "^2.6.4",
|
||||
"gulp-svgmin": "^1.2.4",
|
||||
@@ -37,16 +37,16 @@
|
||||
"gulp-util": "^3.0.8",
|
||||
"prettier-eslint": "^8.8.1",
|
||||
"prettier-stylelint": "^0.4.2",
|
||||
"rollup-plugin-babel": "^3.0.3",
|
||||
"rollup-plugin-babel": "^3.0.4",
|
||||
"rollup-plugin-commonjs": "^9.1.0",
|
||||
"rollup-plugin-node-resolve": "^3.3.0",
|
||||
"run-sequence": "^2.2.1",
|
||||
"stylelint": "^9.2.0",
|
||||
"stylelint-config-prettier": "^3.0.4",
|
||||
"stylelint-config-prettier": "^3.2.0",
|
||||
"stylelint-config-recommended": "^2.1.0",
|
||||
"stylelint-config-sass-guidelines": "^5.0.0",
|
||||
"stylelint-order": "^0.8.1",
|
||||
"stylelint-scss": "^3.0.0",
|
||||
"stylelint-scss": "^3.0.1",
|
||||
"stylelint-selector-bem-pattern": "^2.0.0"
|
||||
},
|
||||
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
|
||||
|
||||
@@ -128,7 +128,7 @@ See [initialising](#initialising) for more information on advanced setups.
|
||||
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript, you can use the following:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.plyr.io/3.1.0-beta.1/plyr.js"></script>
|
||||
<script src="https://cdn.plyr.io/3.2.2/plyr.js"></script>
|
||||
```
|
||||
|
||||
_Note_: Be sure to read the [polyfills](#polyfills) section below about browser compatibility
|
||||
@@ -144,13 +144,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:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.1.0-beta.1/plyr.css">
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.2.2/plyr.css">
|
||||
```
|
||||
|
||||
### 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
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.1.0-beta.1/plyr.svg`.
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.2.2/plyr.svg`.
|
||||
|
||||
## Ads
|
||||
|
||||
|
||||
+45
-6
@@ -6,6 +6,7 @@
|
||||
import support from './support';
|
||||
import utils from './utils';
|
||||
import controls from './controls';
|
||||
import i18n from './i18n';
|
||||
|
||||
const captions = {
|
||||
// Setup captions
|
||||
@@ -46,6 +47,7 @@ const captions = {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Inject the container
|
||||
if (!utils.is.element(this.elements.captions)) {
|
||||
this.elements.captions = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.captions));
|
||||
@@ -148,7 +150,49 @@ const captions = {
|
||||
|
||||
// Get the current track for the current language
|
||||
getCurrentTrack() {
|
||||
return captions.getTracks.call(this).find(track => track.language.toLowerCase() === this.language);
|
||||
const tracks = captions.getTracks.call(this);
|
||||
|
||||
if (!tracks.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get track based on current language
|
||||
let track = tracks.find(track => track.language.toLowerCase() === this.language);
|
||||
|
||||
// Get the <track> with default attribute
|
||||
if (!track) {
|
||||
track = utils.getElement.call(this, 'track[default]');
|
||||
}
|
||||
|
||||
// Get the first track
|
||||
if (!track) {
|
||||
[track] = tracks;
|
||||
}
|
||||
|
||||
return track;
|
||||
},
|
||||
|
||||
// Get UI label for track
|
||||
getLabel(track) {
|
||||
let currentTrack = track;
|
||||
|
||||
if (!utils.is.track(currentTrack) && support.textTracks && this.captions.active) {
|
||||
currentTrack = captions.getCurrentTrack.call(this);
|
||||
}
|
||||
|
||||
if (utils.is.track(currentTrack)) {
|
||||
if (!utils.is.empty(currentTrack.label)) {
|
||||
return currentTrack.label;
|
||||
}
|
||||
|
||||
if (!utils.is.empty(currentTrack.language)) {
|
||||
return track.language.toUpperCase();
|
||||
}
|
||||
|
||||
return i18n.get('enabled', this.config);
|
||||
}
|
||||
|
||||
return i18n.get('disabled', this.config);
|
||||
},
|
||||
|
||||
// Display active caption if it contains text
|
||||
@@ -206,11 +250,6 @@ const captions = {
|
||||
|
||||
// Display captions container and button (for initialization)
|
||||
show() {
|
||||
// If there's no caption toggle, bail
|
||||
if (!utils.is.element(this.elements.buttons.captions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to load the value from storage
|
||||
let active = this.storage.get('captions');
|
||||
|
||||
|
||||
Vendored
+87
-78
@@ -15,11 +15,6 @@ const browser = utils.getBrowser();
|
||||
const controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill(target) {
|
||||
// WebKit only
|
||||
if (!browser.isWebkit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get range from event if event passed
|
||||
const range = utils.is.event(target) ? target.target : target;
|
||||
|
||||
@@ -28,6 +23,14 @@ const controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set aria value for https://github.com/sampotts/plyr/issues/905
|
||||
range.setAttribute('aria-valuenow', range.value);
|
||||
|
||||
// WebKit only
|
||||
if (!browser.isWebkit) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set CSS custom property
|
||||
range.style.setProperty('--value', `${range.value / range.max * 100}%`);
|
||||
},
|
||||
@@ -52,6 +55,7 @@ const controls = {
|
||||
icon,
|
||||
utils.extend(attributes, {
|
||||
role: 'presentation',
|
||||
focusable: 'false',
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -238,6 +242,7 @@ const controls = {
|
||||
'label',
|
||||
{
|
||||
for: attributes.id,
|
||||
id: `${attributes.id}-label`,
|
||||
class: this.config.classNames.hidden,
|
||||
},
|
||||
i18n.get(type, this.config),
|
||||
@@ -255,6 +260,12 @@ const controls = {
|
||||
step: 0.01,
|
||||
value: 0,
|
||||
autocomplete: 'off',
|
||||
// A11y fixes for https://github.com/sampotts/plyr/issues/905
|
||||
role: 'slider',
|
||||
'aria-labelledby': `${attributes.id}-label`,
|
||||
'aria-valuemin': 0,
|
||||
'aria-valuemax': 100,
|
||||
'aria-valuenow': 0,
|
||||
},
|
||||
attributes,
|
||||
),
|
||||
@@ -281,6 +292,8 @@ const controls = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
value: 0,
|
||||
role: 'presentation',
|
||||
'aria-hidden': true,
|
||||
},
|
||||
attributes,
|
||||
),
|
||||
@@ -354,7 +367,7 @@ const controls = {
|
||||
}),
|
||||
);
|
||||
|
||||
const faux = utils.createElement('span', { 'aria-hidden': true });
|
||||
const faux = utils.createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
@@ -429,11 +442,7 @@ const controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab(setting, toggle) {
|
||||
const tab = this.elements.settings.tabs[setting];
|
||||
const pane = this.elements.settings.panes[setting];
|
||||
|
||||
utils.toggleHidden(tab, !toggle);
|
||||
utils.toggleHidden(pane, !toggle);
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
// Set the quality menu
|
||||
@@ -456,6 +465,9 @@ const controls = {
|
||||
const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
|
||||
// If we're hiding, nothing more to do
|
||||
if (!toggle) {
|
||||
return;
|
||||
@@ -474,13 +486,7 @@ const controls = {
|
||||
break;
|
||||
|
||||
case 1440:
|
||||
label = 'WQHD';
|
||||
break;
|
||||
|
||||
case 1080:
|
||||
label = 'HD';
|
||||
break;
|
||||
|
||||
case 720:
|
||||
label = 'HD';
|
||||
break;
|
||||
@@ -501,13 +507,15 @@ const controls = {
|
||||
};
|
||||
|
||||
// Sort options by the config and then render options
|
||||
this.options.quality.sort((a, b) => {
|
||||
const sorting = this.config.quality.options;
|
||||
return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
|
||||
}).forEach(quality => {
|
||||
const label = controls.getLabel.call(this, 'quality', quality);
|
||||
controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality));
|
||||
});
|
||||
this.options.quality
|
||||
.sort((a, b) => {
|
||||
const sorting = this.config.quality.options;
|
||||
return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
|
||||
})
|
||||
.forEach(quality => {
|
||||
const label = controls.getLabel.call(this, 'quality', quality);
|
||||
controls.createMenuItem.call(this, quality, list, type, label, getBadge(quality));
|
||||
});
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
},
|
||||
@@ -517,16 +525,17 @@ const controls = {
|
||||
getLabel(setting, value) {
|
||||
switch (setting) {
|
||||
case 'speed':
|
||||
return value === 1 ? 'Normal' : `${value}×`;
|
||||
return value === 1 ? i18n.get('normal', this.config) : `${value}×`;
|
||||
|
||||
case 'quality':
|
||||
if (utils.is.number(value)) {
|
||||
return `${value}p`;
|
||||
}
|
||||
|
||||
return utils.toTitleCase(value);
|
||||
|
||||
case 'captions':
|
||||
return controls.getLanguage.call(this);
|
||||
return captions.getLabel.call(this);
|
||||
|
||||
default:
|
||||
return null;
|
||||
@@ -541,7 +550,16 @@ const controls = {
|
||||
|
||||
switch (setting) {
|
||||
case 'captions':
|
||||
value = this.captions.active ? this.captions.language : i18n.get('disabled', this.config);
|
||||
if (this.captions.active) {
|
||||
if (this.options.captions.length > 2 || !this.options.captions.some(lang => lang === 'enabled')) {
|
||||
value = this.captions.language;
|
||||
} else {
|
||||
value = 'enabled';
|
||||
}
|
||||
} else {
|
||||
value = '';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -572,17 +590,19 @@ const controls = {
|
||||
list = pane && pane.querySelector('ul');
|
||||
}
|
||||
|
||||
// Update the label
|
||||
if (!utils.is.empty(value)) {
|
||||
const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
// If there's no list it means it's not been rendered...
|
||||
if (!utils.is.element(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the radio option
|
||||
// Update the label
|
||||
const label = this.elements.settings.tabs[setting].querySelector(`.${this.config.classNames.menu.value}`);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
|
||||
// Find the radio option and check it
|
||||
const target = list && list.querySelector(`input[value="${value}"]`);
|
||||
|
||||
if (utils.is.element(target)) {
|
||||
// Check it
|
||||
target.checked = true;
|
||||
}
|
||||
},
|
||||
@@ -633,21 +653,6 @@ const controls = {
|
||||
|
||||
// Get current selected caption language
|
||||
// TODO: rework this to user the getter in the API?
|
||||
getLanguage() {
|
||||
if (!this.supported.ui) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (support.textTracks && captions.getTracks.call(this).length && this.captions.active) {
|
||||
const currentTrack = captions.getCurrentTrack.call(this);
|
||||
|
||||
if (utils.is.track(currentTrack)) {
|
||||
return currentTrack.label;
|
||||
}
|
||||
}
|
||||
|
||||
return i18n.get('disabled', this.config);
|
||||
},
|
||||
|
||||
// Set a list of available captions languages
|
||||
setCaptionsMenu() {
|
||||
@@ -656,21 +661,24 @@ const controls = {
|
||||
const list = this.elements.settings.panes.captions.querySelector('ul');
|
||||
|
||||
// Toggle the pane and tab
|
||||
const hasTracks = captions.getTracks.call(this).length;
|
||||
controls.toggleTab.call(this, type, hasTracks);
|
||||
const toggle = captions.getTracks.call(this).length;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
|
||||
// If there's no captions, bail
|
||||
if (!hasTracks) {
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-map the tracks into just the data we need
|
||||
const tracks = captions.getTracks.call(this).map(track => ({
|
||||
language: track.language,
|
||||
label: !utils.is.empty(track.label) ? track.label : track.language.toUpperCase(),
|
||||
language: !utils.is.empty(track.language) ? track.language : 'enabled',
|
||||
label: captions.getLabel.call(this, track),
|
||||
}));
|
||||
|
||||
// Add the "Disabled" option to turn off captions
|
||||
@@ -686,12 +694,15 @@ const controls = {
|
||||
track.language,
|
||||
list,
|
||||
'language',
|
||||
track.label || track.language,
|
||||
controls.createBadge.call(this, track.language.toUpperCase()),
|
||||
track.label,
|
||||
track.language !== 'enabled' ? controls.createBadge.call(this, track.language.toUpperCase()) : null,
|
||||
track.language.toLowerCase() === this.captions.language.toLowerCase(),
|
||||
);
|
||||
});
|
||||
|
||||
// Store reference
|
||||
this.options.captions = tracks.map(track => track.language);
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
},
|
||||
|
||||
@@ -710,7 +721,9 @@ const controls = {
|
||||
const type = 'speed';
|
||||
|
||||
// Set the speed options
|
||||
if (!utils.is.array(options)) {
|
||||
if (utils.is.array(options)) {
|
||||
this.options.speed = options;
|
||||
} else if (this.isHTML5 || this.isVimeo) {
|
||||
this.options.speed = [
|
||||
0.5,
|
||||
0.75,
|
||||
@@ -720,15 +733,13 @@ const controls = {
|
||||
1.75,
|
||||
2,
|
||||
];
|
||||
} else {
|
||||
this.options.speed = options;
|
||||
}
|
||||
|
||||
// Set options if passed and filter based on config
|
||||
this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));
|
||||
|
||||
// Toggle the pane and tab
|
||||
const toggle = !utils.is.empty(this.options.speed);
|
||||
const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
@@ -742,15 +753,14 @@ const controls = {
|
||||
// Get the list to populate
|
||||
const list = this.elements.settings.panes.speed.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
utils.toggleHidden(this.elements.settings.tabs.speed, false);
|
||||
utils.toggleHidden(this.elements.settings.panes.speed, false);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
// Create items
|
||||
this.options.speed.forEach(speed => controls.createMenuItem.call(this, speed, list, type, controls.getLabel.call(this, 'speed', speed)));
|
||||
this.options.speed.forEach(speed => {
|
||||
const label = controls.getLabel.call(this, 'speed', speed);
|
||||
controls.createMenuItem.call(this, speed, list, type, label);
|
||||
});
|
||||
|
||||
controls.updateSetting.call(this, type, list);
|
||||
},
|
||||
@@ -773,7 +783,7 @@ const controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true';
|
||||
const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
|
||||
|
||||
if (utils.is.event(event)) {
|
||||
const isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
@@ -798,7 +808,7 @@ const controls = {
|
||||
}
|
||||
|
||||
if (utils.is.element(form)) {
|
||||
form.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(form, !show);
|
||||
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||
|
||||
if (show) {
|
||||
@@ -814,7 +824,7 @@ const controls = {
|
||||
const clone = tab.cloneNode(true);
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
||||
@@ -858,7 +868,7 @@ const controls = {
|
||||
|
||||
// Hide all other tabs
|
||||
// Get other tabs
|
||||
const current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]');
|
||||
const current = menu.querySelector('[role="tabpanel"]:not([hidden])');
|
||||
const container = current.parentNode;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
@@ -902,11 +912,11 @@ const controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
current.setAttribute('aria-hidden', true);
|
||||
utils.toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
pane.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(pane, !show);
|
||||
tab.setAttribute('aria-expanded', show);
|
||||
pane.removeAttribute('tabindex');
|
||||
|
||||
@@ -1033,6 +1043,7 @@ const controls = {
|
||||
if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {
|
||||
const menu = utils.createElement('div', {
|
||||
class: 'plyr__menu',
|
||||
hidden: '',
|
||||
});
|
||||
|
||||
menu.appendChild(
|
||||
@@ -1047,7 +1058,7 @@ const controls = {
|
||||
const form = utils.createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: `plyr-settings-${data.id}`,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
||||
role: 'tablist',
|
||||
tabindex: -1,
|
||||
@@ -1057,7 +1068,6 @@ const controls = {
|
||||
|
||||
const home = utils.createElement('div', {
|
||||
id: `plyr-settings-${data.id}-home`,
|
||||
'aria-hidden': false,
|
||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
||||
role: 'tabpanel',
|
||||
});
|
||||
@@ -1108,11 +1118,10 @@ const controls = {
|
||||
this.config.settings.forEach(type => {
|
||||
const pane = utils.createElement('div', {
|
||||
id: `plyr-settings-${data.id}-${type}`,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,
|
||||
role: 'tabpanel',
|
||||
tabindex: -1,
|
||||
hidden: '',
|
||||
});
|
||||
|
||||
const back = utils.createElement(
|
||||
@@ -1167,12 +1176,12 @@ const controls = {
|
||||
|
||||
this.elements.controls = container;
|
||||
|
||||
controls.setSpeedMenu.call(this);
|
||||
|
||||
if (this.isHTML5) {
|
||||
controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
|
||||
}
|
||||
|
||||
controls.setSpeedMenu.call(this);
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
@@ -1213,7 +1222,7 @@ const controls = {
|
||||
seektime: this.config.seekTime,
|
||||
speed: this.speed,
|
||||
quality: this.quality,
|
||||
captions: controls.getLanguage.call(this),
|
||||
captions: captions.getLabel.call(this),
|
||||
// TODO: Looping
|
||||
// loop: 'None',
|
||||
});
|
||||
@@ -1235,7 +1244,7 @@ const controls = {
|
||||
// Inject controls HTML
|
||||
if (utils.is.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else {
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -56,14 +56,14 @@ const defaults = {
|
||||
// Sprite (for icons)
|
||||
loadSprite: true,
|
||||
iconPrefix: 'plyr',
|
||||
iconUrl: 'https://cdn.plyr.io/3.1.0-beta.1/plyr.svg',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.2/plyr.svg',
|
||||
|
||||
// Blank video (used to prevent errors on source change)
|
||||
blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
|
||||
|
||||
// Quality default
|
||||
quality: {
|
||||
default: 720,
|
||||
default: 576,
|
||||
options: [
|
||||
4320,
|
||||
2880,
|
||||
@@ -115,7 +115,7 @@ const defaults = {
|
||||
// Captions settings
|
||||
captions: {
|
||||
active: false,
|
||||
language: window.navigator.language.split('-')[0],
|
||||
language: (navigator.language || navigator.userLanguage).split('-')[0],
|
||||
},
|
||||
|
||||
// Fullscreen settings
|
||||
@@ -177,6 +177,7 @@ const defaults = {
|
||||
captions: 'Captions',
|
||||
settings: 'Settings',
|
||||
speed: 'Speed',
|
||||
normal: 'Normal',
|
||||
quality: 'Quality',
|
||||
loop: 'Loop',
|
||||
start: 'Start',
|
||||
@@ -184,6 +185,7 @@ const defaults = {
|
||||
all: 'All',
|
||||
reset: 'Reset',
|
||||
disabled: 'Disabled',
|
||||
enabled: 'Enabled',
|
||||
advertisement: 'Ad',
|
||||
},
|
||||
|
||||
|
||||
@@ -68,13 +68,15 @@ class Fullscreen {
|
||||
});
|
||||
|
||||
// Fullscreen toggle on double click
|
||||
utils.on(this.player.elements.container, 'dblclick', () => {
|
||||
utils.on(this.player.elements.container, 'dblclick', event => {
|
||||
// Ignore double click in controls
|
||||
if (this.player.elements.controls.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggle();
|
||||
});
|
||||
|
||||
// Prevent double click on controls bubbling up
|
||||
utils.on(this.player.elements.controls, 'dblclick', event => event.stopPropagation());
|
||||
|
||||
// Update the UI
|
||||
this.update();
|
||||
}
|
||||
@@ -88,7 +90,7 @@ class Fullscreen {
|
||||
static get prefix() {
|
||||
// No prefix
|
||||
if (utils.is.function(document.exitFullscreen)) {
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
|
||||
// Check for fullscreen support by vendor prefix
|
||||
@@ -191,7 +193,7 @@ class Fullscreen {
|
||||
} else if (!Fullscreen.native) {
|
||||
toggleFallback.call(this, false);
|
||||
} else if (!this.prefix) {
|
||||
document.cancelFullScreen();
|
||||
(document.cancelFullScreen || document.exitFullscreen).call(document);
|
||||
} else if (!utils.is.empty(this.prefix)) {
|
||||
const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
||||
document[`${this.prefix}${action}${this.name}`]();
|
||||
|
||||
+5
-2
@@ -2,7 +2,6 @@
|
||||
// Plyr Event Listeners
|
||||
// ==========================================================================
|
||||
|
||||
import support from './support';
|
||||
import utils from './utils';
|
||||
import controls from './controls';
|
||||
import ui from './ui';
|
||||
@@ -293,6 +292,10 @@ class Listeners {
|
||||
// If autoplay, then load advertisement if required
|
||||
// TODO: Show some sort of loading state while the ad manager loads else there's a delay before ad shows
|
||||
utils.on(this.player.media, 'playing', () => {
|
||||
if (!this.player.ads) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If ads are enabled, wait for them first
|
||||
if (this.player.ads.enabled && !this.player.ads.initialized) {
|
||||
// Wait for manager response
|
||||
@@ -331,7 +334,7 @@ class Listeners {
|
||||
// Disable right click
|
||||
if (this.player.supported.ui && this.player.config.disableContextMenu) {
|
||||
utils.on(
|
||||
this.player.media,
|
||||
this.player.elements.wrapper,
|
||||
'contextmenu',
|
||||
event => {
|
||||
event.preventDefault();
|
||||
|
||||
+25
-4
@@ -35,10 +35,14 @@ const vimeo = {
|
||||
setAspectRatio(input) {
|
||||
const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');
|
||||
const padding = 100 / ratio[0] * ratio[1];
|
||||
const height = 240;
|
||||
const offset = (height - padding) / (height / 50);
|
||||
this.elements.wrapper.style.paddingBottom = `${padding}%`;
|
||||
this.media.style.transform = `translateY(-${offset}%)`;
|
||||
|
||||
if (this.supported.ui) {
|
||||
const height = 240;
|
||||
const offset = (height - padding) / (height / 50);
|
||||
|
||||
this.media.style.transform = `translateY(-${offset}%)`;
|
||||
}
|
||||
},
|
||||
|
||||
// API Ready
|
||||
@@ -55,6 +59,7 @@ const vimeo = {
|
||||
speed: true,
|
||||
transparent: 0,
|
||||
gesture: 'media',
|
||||
playsinline: !this.config.fullscreen.iosNative,
|
||||
};
|
||||
const params = utils.buildUrlParams(options);
|
||||
|
||||
@@ -88,6 +93,11 @@ const vimeo = {
|
||||
player.media.paused = true;
|
||||
player.media.currentTime = 0;
|
||||
|
||||
// Disable native text track rendering
|
||||
if (player.supported.ui) {
|
||||
player.embed.disableTextTrack();
|
||||
}
|
||||
|
||||
// Create a faux HTML5 API using the Vimeo API
|
||||
player.media.play = () => {
|
||||
player.embed.play().then(() => {
|
||||
@@ -124,7 +134,9 @@ const vimeo = {
|
||||
utils.dispatchEvent.call(player, player.media, 'seeking');
|
||||
|
||||
// Seek after events
|
||||
player.embed.setCurrentTime(time);
|
||||
player.embed.setCurrentTime(time).catch(() => {
|
||||
// Do nothing
|
||||
});
|
||||
|
||||
// Restore pause state
|
||||
if (paused) {
|
||||
@@ -310,6 +322,15 @@ const vimeo = {
|
||||
if (parseInt(data.percent, 10) === 1) {
|
||||
utils.dispatchEvent.call(player, player.media, 'canplaythrough');
|
||||
}
|
||||
|
||||
// Get duration as if we do it before load, it gives an incorrect value
|
||||
// https://github.com/sampotts/plyr/issues/891
|
||||
player.embed.getDuration().then(value => {
|
||||
if (value !== player.media.duration) {
|
||||
player.media.duration = value;
|
||||
utils.dispatchEvent.call(player, player.media, 'durationchange');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
player.embed.on('seeked', () => {
|
||||
|
||||
@@ -270,6 +270,9 @@ const youtube = {
|
||||
return Number(instance.getCurrentTime());
|
||||
},
|
||||
set(time) {
|
||||
// Vimeo will automatically play on seek
|
||||
const { paused } = player.media;
|
||||
|
||||
// Set seeking flag
|
||||
player.media.seeking = true;
|
||||
|
||||
@@ -278,6 +281,11 @@ const youtube = {
|
||||
|
||||
// Seek after events sent
|
||||
instance.seekTo(time);
|
||||
|
||||
// Restore pause state
|
||||
if (paused) {
|
||||
player.pause();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -351,8 +359,7 @@ const youtube = {
|
||||
});
|
||||
|
||||
// Get available speeds
|
||||
const options = instance.getAvailablePlaybackRates();
|
||||
controls.setSpeedMenu.call(player, options);
|
||||
player.options.speed = instance.getAvailablePlaybackRates();
|
||||
|
||||
// Set the tabindex to avoid focus entering iframe
|
||||
if (player.supported.ui) {
|
||||
|
||||
+41
-18
@@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr
|
||||
// plyr.js v3.1.0-beta.1
|
||||
// plyr.js v3.2.2
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
@@ -57,7 +57,7 @@ class Plyr {
|
||||
this.config = utils.extend(
|
||||
{},
|
||||
defaults,
|
||||
options,
|
||||
options || {},
|
||||
(() => {
|
||||
try {
|
||||
return JSON.parse(this.media.getAttribute('data-plyr-config'));
|
||||
@@ -97,6 +97,7 @@ class Plyr {
|
||||
this.options = {
|
||||
speed: [],
|
||||
quality: [],
|
||||
captions: [],
|
||||
};
|
||||
|
||||
// Debugging
|
||||
@@ -184,12 +185,17 @@ class Plyr {
|
||||
if (truthy.includes(params.autoplay)) {
|
||||
this.config.autoplay = true;
|
||||
}
|
||||
if (truthy.includes(params.playsinline)) {
|
||||
this.config.inline = true;
|
||||
}
|
||||
if (truthy.includes(params.loop)) {
|
||||
this.config.loop.active = true;
|
||||
}
|
||||
|
||||
// TODO: replace fullscreen.iosNative with this playsinline config option
|
||||
// YouTube requires the playsinline in the URL
|
||||
if (this.isYouTube) {
|
||||
this.config.playsinline = truthy.includes(params.playsinline);
|
||||
} else {
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// <div> with attributes
|
||||
@@ -223,7 +229,7 @@ class Plyr {
|
||||
this.config.autoplay = true;
|
||||
}
|
||||
if (this.media.hasAttribute('playsinline')) {
|
||||
this.config.inline = true;
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
if (this.media.hasAttribute('muted')) {
|
||||
this.config.muted = true;
|
||||
@@ -240,7 +246,7 @@ class Plyr {
|
||||
}
|
||||
|
||||
// Check for support again but with type
|
||||
this.supported = support.check(this.type, this.provider, this.config.inline);
|
||||
this.supported = support.check(this.type, this.provider, this.config.playsinline);
|
||||
|
||||
// If no support for even API, bail
|
||||
if (!this.supported.api) {
|
||||
@@ -368,7 +374,7 @@ class Plyr {
|
||||
* Get playing state
|
||||
*/
|
||||
get playing() {
|
||||
return Boolean(!this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true));
|
||||
return Boolean(this.ready && !this.paused && !this.ended && (this.isHTML5 ? this.media.readyState > 2 : true));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,7 +452,7 @@ class Plyr {
|
||||
}
|
||||
|
||||
// Set
|
||||
this.media.currentTime = parseFloat(targetTime.toFixed(4));
|
||||
this.media.currentTime = targetTime;
|
||||
|
||||
// Logging
|
||||
this.debug.log(`Seeking to ${this.currentTime} seconds`);
|
||||
@@ -492,7 +498,7 @@ class Plyr {
|
||||
*/
|
||||
get duration() {
|
||||
// Faux duration set via config
|
||||
const fauxDuration = parseInt(this.config.duration, 10);
|
||||
const fauxDuration = parseFloat(this.config.duration);
|
||||
|
||||
// True duration
|
||||
const realDuration = this.media ? Number(this.media.duration) : 0;
|
||||
@@ -692,11 +698,16 @@ class Plyr {
|
||||
quality = this.config.quality.default;
|
||||
}
|
||||
|
||||
if (!this.options.quality.includes(quality)) {
|
||||
this.debug.warn(`Unsupported quality option (${quality})`);
|
||||
if (!this.options.quality.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.options.quality.includes(quality)) {
|
||||
const closest = utils.closest(this.options.quality, quality);
|
||||
this.debug.warn(`Unsupported quality option: ${quality}, using ${closest} instead`);
|
||||
quality = closest;
|
||||
}
|
||||
|
||||
// Update config
|
||||
this.config.quality.selected = quality;
|
||||
|
||||
@@ -834,13 +845,13 @@ class Plyr {
|
||||
* @param {boolean} input - Whether to enable captions
|
||||
*/
|
||||
toggleCaptions(input) {
|
||||
// If there's no full support, or there's no caption toggle
|
||||
if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) {
|
||||
// If there's no full support
|
||||
if (!this.supported.ui) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the method is called without parameter, toggle based on current value
|
||||
const show = utils.is.boolean(input) ? input : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;
|
||||
const show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active);
|
||||
|
||||
// Nothing to change...
|
||||
if (this.captions.active === show) {
|
||||
@@ -870,17 +881,29 @@ class Plyr {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle captions based on input
|
||||
this.toggleCaptions(!utils.is.empty(input));
|
||||
|
||||
// If empty string is passed, assume disable captions
|
||||
if (utils.is.empty(input)) {
|
||||
this.toggleCaptions(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize
|
||||
const language = input.toLowerCase();
|
||||
|
||||
// Check for support
|
||||
if (!this.options.captions.includes(language)) {
|
||||
this.debug.warn(`Unsupported language option: ${language}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure captions are enabled
|
||||
this.toggleCaptions(true);
|
||||
|
||||
// Enabled only
|
||||
if (language === 'enabled') {
|
||||
return;
|
||||
}
|
||||
|
||||
// If nothing to change, bail
|
||||
if (this.language === language) {
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr Polyfilled Build
|
||||
// plyr.js v3.1.0-beta.1
|
||||
// plyr.js v3.2.2
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
|
||||
+2
-2
@@ -55,7 +55,7 @@ const source = {
|
||||
this.provider = !utils.is.empty(input.sources[0].provider) ? input.sources[0].provider : providers.html5;
|
||||
|
||||
// Check for support
|
||||
this.supported = support.check(this.type, this.provider, this.config.inline);
|
||||
this.supported = support.check(this.type, this.provider, this.config.playsinline);
|
||||
|
||||
// Create new markup
|
||||
switch (`${this.provider}:${this.type}`) {
|
||||
@@ -103,7 +103,7 @@ const source = {
|
||||
if (this.config.muted) {
|
||||
this.media.setAttribute('muted', '');
|
||||
}
|
||||
if (this.config.inline) {
|
||||
if (this.config.playsinline) {
|
||||
this.media.setAttribute('playsinline', '');
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -12,16 +12,16 @@ const support = {
|
||||
|
||||
// Check for support
|
||||
// Basic functionality vs full UI
|
||||
check(type, provider, inline) {
|
||||
check(type, provider, playsinline) {
|
||||
let api = false;
|
||||
let ui = false;
|
||||
const browser = utils.getBrowser();
|
||||
const playsInline = browser.isIPhone && inline && support.inline;
|
||||
const canPlayInline = browser.isIPhone && playsinline && support.playsinline;
|
||||
|
||||
switch (`${provider}:${type}`) {
|
||||
case 'html5:video':
|
||||
api = support.video;
|
||||
ui = api && support.rangeInput && (!browser.isIPhone || playsInline);
|
||||
ui = api && support.rangeInput && (!browser.isIPhone || canPlayInline);
|
||||
break;
|
||||
|
||||
case 'html5:audio':
|
||||
@@ -32,7 +32,7 @@ const support = {
|
||||
case 'youtube:video':
|
||||
case 'vimeo:video':
|
||||
api = true;
|
||||
ui = support.rangeInput && (!browser.isIPhone || playsInline);
|
||||
ui = support.rangeInput && (!browser.isIPhone || canPlayInline);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -59,7 +59,7 @@ const support = {
|
||||
|
||||
// Inline playback support
|
||||
// https://webkit.org/blog/6784/new-video-policies-for-ios/
|
||||
inline: 'playsInline' in document.createElement('video'),
|
||||
playsinline: 'playsInline' in document.createElement('video'),
|
||||
|
||||
// Check for mime type support against a player instance
|
||||
// Credits: http://diveintohtml5.info/everything.html
|
||||
|
||||
+28
-13
@@ -375,6 +375,25 @@ const utils = {
|
||||
return attributes;
|
||||
},
|
||||
|
||||
// Toggle hidden
|
||||
toggleHidden(element, hidden) {
|
||||
if (!utils.is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let hide = hidden;
|
||||
|
||||
if (!utils.is.boolean(hide)) {
|
||||
hide = !element.hasAttribute('hidden');
|
||||
}
|
||||
|
||||
if (hide) {
|
||||
element.setAttribute('hidden', '');
|
||||
} else {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
// Toggle class on an element
|
||||
toggleClass(element, className, toggle) {
|
||||
if (utils.is.element(element)) {
|
||||
@@ -393,19 +412,6 @@ const utils = {
|
||||
return utils.is.element(element) && element.classList.contains(className);
|
||||
},
|
||||
|
||||
// Toggle hidden attribute on an element
|
||||
toggleHidden(element, toggle) {
|
||||
if (!utils.is.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
element.setAttribute('hidden', '');
|
||||
} else {
|
||||
element.removeAttribute('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
// Element matches selector
|
||||
matches(element, selector) {
|
||||
const prototype = { Element };
|
||||
@@ -746,6 +752,15 @@ const utils = {
|
||||
return array.filter((item, index) => array.indexOf(item) === index);
|
||||
},
|
||||
|
||||
// Get the closest value in an array
|
||||
closest(array, value) {
|
||||
if (!utils.is.array(array) || !array.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));
|
||||
},
|
||||
|
||||
// Get the provider for a given URL
|
||||
getProviderByUrl(url) {
|
||||
// YouTube
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
font: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
// Ignore focus
|
||||
&:focus {
|
||||
outline: 0;
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
// YouTube, Vimeo, etc
|
||||
// --------------------------------------------------------------
|
||||
|
||||
.plyr__video-embed {
|
||||
// Default to 16:9 ratio but this is set by JavaScript based on config
|
||||
$padding: ((100 / 16) * 9);
|
||||
$height: 240;
|
||||
$offset: to-percentage(($height - $padding) / ($height / 50));
|
||||
// Default to 16:9 ratio but this is set by JavaScript based on config
|
||||
$embed-padding: ((100 / 16) * 9);
|
||||
|
||||
.plyr__video-embed {
|
||||
height: 0;
|
||||
padding-bottom: to-percentage($padding);
|
||||
padding-bottom: to-percentage($embed-padding);
|
||||
position: relative;
|
||||
|
||||
iframe {
|
||||
@@ -22,6 +20,17 @@
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// If the full custom UI is supported
|
||||
.plyr--full-ui .plyr__video-embed {
|
||||
$height: 240;
|
||||
$offset: to-percentage(($height - $embed-padding) / ($height / 50));
|
||||
|
||||
// To allow mouse events to be captured if full support
|
||||
iframe {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Vimeo hack
|
||||
> div {
|
||||
@@ -30,7 +39,3 @@
|
||||
transform: translateY(-$offset);
|
||||
}
|
||||
}
|
||||
// To allow mouse events to be captured if full support
|
||||
.plyr--full-ui .plyr__video-embed iframe {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
right: -3px;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
|
||||
> div {
|
||||
overflow: hidden;
|
||||
@@ -74,6 +74,7 @@
|
||||
align-items: center;
|
||||
color: $plyr-menu-color;
|
||||
display: flex;
|
||||
font-size: $plyr-font-size-menu;
|
||||
padding: ceil($plyr-control-padding / 2) ($plyr-control-padding * 2);
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
&::-webkit-slider-runnable-track {
|
||||
@include plyr-range-track();
|
||||
background-image: linear-gradient(to right, currentColor var(--value), transparent var(--value));
|
||||
background-image: linear-gradient(to right, currentColor var(--value, 0%), transparent var(--value, 0%));
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
|
||||
@@ -8,8 +8,9 @@ $plyr-font-size-small: 14px !default;
|
||||
$plyr-font-size-large: 18px !default;
|
||||
$plyr-font-size-xlarge: 21px !default;
|
||||
|
||||
$plyr-font-size-time: 14px !default;
|
||||
$plyr-font-size-time: $plyr-font-size-small !default;
|
||||
$plyr-font-size-badge: 9px !default;
|
||||
$plyr-font-size-menu: $plyr-font-size-small !default;
|
||||
|
||||
$plyr-font-weight-regular: 500 !default;
|
||||
$plyr-font-weight-bold: 600 !default;
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
// Hiding content nicely
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// Attributes
|
||||
.plyr--full-ui [hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.plyr--full-ui [aria-hidden='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Screen reader only elements
|
||||
.plyr__sr-only {
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
|
||||
@@ -2,12 +2,18 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@babel/code-frame@7.0.0-beta.42", "@babel/code-frame@^7.0.0-beta.40":
|
||||
"@babel/code-frame@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.42.tgz#a9c83233fa7cd06b39dc77adbb908616ff4f1962"
|
||||
dependencies:
|
||||
"@babel/highlight" "7.0.0-beta.42"
|
||||
|
||||
"@babel/code-frame@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9"
|
||||
dependencies:
|
||||
"@babel/highlight" "7.0.0-beta.44"
|
||||
|
||||
"@babel/core@^7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.0.0-beta.42.tgz#b3a838fddbd19663369a0b4892189fd8d3f82001"
|
||||
@@ -38,6 +44,16 @@
|
||||
source-map "^0.5.0"
|
||||
trim-right "^1.0.1"
|
||||
|
||||
"@babel/generator@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42"
|
||||
dependencies:
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.2.0"
|
||||
source-map "^0.5.0"
|
||||
trim-right "^1.0.1"
|
||||
|
||||
"@babel/helper-function-name@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.42.tgz#b38b8f4f85168d1812c543dd700b5d549b0c4658"
|
||||
@@ -46,18 +62,38 @@
|
||||
"@babel/template" "7.0.0-beta.42"
|
||||
"@babel/types" "7.0.0-beta.42"
|
||||
|
||||
"@babel/helper-function-name@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd"
|
||||
dependencies:
|
||||
"@babel/helper-get-function-arity" "7.0.0-beta.44"
|
||||
"@babel/template" "7.0.0-beta.44"
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
|
||||
"@babel/helper-get-function-arity@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.42.tgz#ad072e32f912c033053fc80478169aeadc22191e"
|
||||
dependencies:
|
||||
"@babel/types" "7.0.0-beta.42"
|
||||
|
||||
"@babel/helper-get-function-arity@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15"
|
||||
dependencies:
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
|
||||
"@babel/helper-split-export-declaration@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.42.tgz#0d0d5254220a9cc4e7e226240306b939dc210ee7"
|
||||
dependencies:
|
||||
"@babel/types" "7.0.0-beta.42"
|
||||
|
||||
"@babel/helper-split-export-declaration@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc"
|
||||
dependencies:
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
|
||||
"@babel/helpers@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.0.0-beta.42.tgz#151c1c4e9da1b6ce83d54c1be5fb8c9c57aa5044"
|
||||
@@ -74,6 +110,14 @@
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^3.0.0"
|
||||
|
||||
"@babel/highlight@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5"
|
||||
dependencies:
|
||||
chalk "^2.0.0"
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^3.0.0"
|
||||
|
||||
"@babel/template@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.42.tgz#7186d4e70d44cdec975049ba0a73bdaf5cdee052"
|
||||
@@ -83,7 +127,16 @@
|
||||
babylon "7.0.0-beta.42"
|
||||
lodash "^4.2.0"
|
||||
|
||||
"@babel/traverse@7.0.0-beta.42", "@babel/traverse@^7.0.0-beta.40", "@babel/traverse@^7.0.0-beta.42":
|
||||
"@babel/template@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
|
||||
dependencies:
|
||||
"@babel/code-frame" "7.0.0-beta.44"
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
babylon "7.0.0-beta.44"
|
||||
lodash "^4.2.0"
|
||||
|
||||
"@babel/traverse@7.0.0-beta.42", "@babel/traverse@^7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.42.tgz#f4bf4d1e33d41baf45205e2d0463591d57326285"
|
||||
dependencies:
|
||||
@@ -98,7 +151,22 @@
|
||||
invariant "^2.2.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
"@babel/types@7.0.0-beta.42", "@babel/types@^7.0.0-beta.40":
|
||||
"@babel/traverse@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966"
|
||||
dependencies:
|
||||
"@babel/code-frame" "7.0.0-beta.44"
|
||||
"@babel/generator" "7.0.0-beta.44"
|
||||
"@babel/helper-function-name" "7.0.0-beta.44"
|
||||
"@babel/helper-split-export-declaration" "7.0.0-beta.44"
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
babylon "7.0.0-beta.44"
|
||||
debug "^3.1.0"
|
||||
globals "^11.1.0"
|
||||
invariant "^2.2.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
"@babel/types@7.0.0-beta.42":
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.42.tgz#1e2118767684880f6963801b272fd2b3348efacc"
|
||||
dependencies:
|
||||
@@ -106,6 +174,14 @@
|
||||
lodash "^4.2.0"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@7.0.0-beta.44":
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757"
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.2.0"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@gulp-sourcemaps/identity-map@1.X":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz#cfa23bc5840f9104ce32a65e74db7e7a974bbee1"
|
||||
@@ -441,14 +517,14 @@ babel-core@^6.26.0:
|
||||
slash "^1.0.0"
|
||||
source-map "^0.5.6"
|
||||
|
||||
babel-eslint@^8.2.2:
|
||||
version "8.2.2"
|
||||
resolved "http://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz#1102273354c6f0b29b4ea28a65f97d122296b68b"
|
||||
babel-eslint@^8.2.3:
|
||||
version "8.2.3"
|
||||
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.3.tgz#1a2e6681cc9bc4473c32899e59915e19cd6733cf"
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0-beta.40"
|
||||
"@babel/traverse" "^7.0.0-beta.40"
|
||||
"@babel/types" "^7.0.0-beta.40"
|
||||
babylon "^7.0.0-beta.40"
|
||||
"@babel/code-frame" "7.0.0-beta.44"
|
||||
"@babel/traverse" "7.0.0-beta.44"
|
||||
"@babel/types" "7.0.0-beta.44"
|
||||
babylon "7.0.0-beta.44"
|
||||
eslint-scope "~3.7.1"
|
||||
eslint-visitor-keys "^1.0.0"
|
||||
|
||||
@@ -888,10 +964,14 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
|
||||
lodash "^4.17.4"
|
||||
to-fast-properties "^1.0.3"
|
||||
|
||||
babylon@7.0.0-beta.42, babylon@^7.0.0-beta.40, babylon@^7.0.0-beta.42:
|
||||
babylon@7.0.0-beta.42, babylon@^7.0.0-beta.42:
|
||||
version "7.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.42.tgz#67cfabcd4f3ec82999d29031ccdea89d0ba99657"
|
||||
|
||||
babylon@7.0.0-beta.44:
|
||||
version "7.0.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d"
|
||||
|
||||
babylon@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
|
||||
@@ -1016,7 +1096,7 @@ browserslist@^3.1.1:
|
||||
caniuse-lite "^1.0.30000813"
|
||||
electron-to-chromium "^1.3.36"
|
||||
|
||||
builtin-modules@^1.0.0, builtin-modules@^1.1.1:
|
||||
builtin-modules@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||
|
||||
@@ -1784,11 +1864,10 @@ eslint-module-utils@^2.2.0:
|
||||
debug "^2.6.8"
|
||||
pkg-dir "^1.0.0"
|
||||
|
||||
eslint-plugin-import@^2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.10.0.tgz#fa09083d5a75288df9c6c7d09fe12255985655e7"
|
||||
eslint-plugin-import@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.11.0.tgz#15aeea37a67499d848e8e981806d4627b5503816"
|
||||
dependencies:
|
||||
builtin-modules "^1.1.1"
|
||||
contains-path "^0.1.0"
|
||||
debug "^2.6.8"
|
||||
doctrine "1.5.0"
|
||||
@@ -1798,6 +1877,7 @@ eslint-plugin-import@^2.10.0:
|
||||
lodash "^4.17.4"
|
||||
minimatch "^3.0.3"
|
||||
read-pkg-up "^2.0.0"
|
||||
resolve "^1.6.0"
|
||||
|
||||
eslint-restricted-globals@^0.1.1:
|
||||
version "0.1.1"
|
||||
@@ -2629,13 +2709,16 @@ gulp-s3@^0.11.0:
|
||||
knox ""
|
||||
mime "~1.2.11"
|
||||
|
||||
gulp-sass@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-3.2.1.tgz#2e3688a96fd8be1c0c01340750c191b2e79fab94"
|
||||
gulp-sass@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.0.1.tgz#7f43d117eb2d303524968a1b48494af1bc64d1d9"
|
||||
dependencies:
|
||||
gulp-util "^3.0"
|
||||
chalk "^2.3.0"
|
||||
lodash.clonedeep "^4.3.2"
|
||||
node-sass "^4.8.3"
|
||||
plugin-error "^1.0.1"
|
||||
replace-ext "^1.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
through2 "^2.0.0"
|
||||
vinyl-sourcemaps-apply "^0.2.0"
|
||||
|
||||
@@ -2693,7 +2776,7 @@ gulp-uglify-es@^1.0.1:
|
||||
vinyl "^2.1.0"
|
||||
vinyl-sourcemaps-apply "^0.2.1"
|
||||
|
||||
gulp-util@^3.0, gulp-util@^3.0.0, gulp-util@^3.0.4, gulp-util@^3.0.8:
|
||||
gulp-util@^3.0.0, gulp-util@^3.0.4, gulp-util@^3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
|
||||
dependencies:
|
||||
@@ -5254,6 +5337,12 @@ resolve@^1.3.2:
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
resolve@^1.6.0:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
restore-cursor@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
|
||||
@@ -5271,9 +5360,9 @@ rimraf@2, rimraf@^2.2.8:
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
|
||||
rollup-plugin-babel@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.3.tgz#63adedc863130327512a4a9006efc2241c5b7c15"
|
||||
rollup-plugin-babel@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.4.tgz#41b3e762fe64450dd61da3105a2cf7ad76be4edc"
|
||||
dependencies:
|
||||
rollup-pluginutils "^1.5.0"
|
||||
|
||||
@@ -5730,9 +5819,9 @@ style-search@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902"
|
||||
|
||||
stylelint-config-prettier@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.0.4.tgz#1259093c1db2d5e8dfff7d9672f6f41db2101845"
|
||||
stylelint-config-prettier@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-3.2.0.tgz#af32b7845adeeddbf0a0bd642ace4ca1e68958e2"
|
||||
dependencies:
|
||||
stylelint "^9.1.1"
|
||||
|
||||
@@ -5765,9 +5854,9 @@ stylelint-scss@^2.0.0:
|
||||
postcss-selector-parser "^3.1.1"
|
||||
postcss-value-parser "^3.3.0"
|
||||
|
||||
stylelint-scss@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.0.0.tgz#15beb887117ccef20668a3f4728eb5be5fbda045"
|
||||
stylelint-scss@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.0.1.tgz#bc062e818add985f19dee98f7f5b4bff4f38706e"
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
postcss-media-query-parser "^0.2.3"
|
||||
|
||||
Reference in New Issue
Block a user