Compare commits

...

18 Commits

Author SHA1 Message Date
Sam Potts b444aa3a98 pkg: deploy v3.6.3 2020-11-14 13:29:47 +11:00
Sam Potts e8d883edba v3.6.3 (#2016)
* force fullscreen events to trigger on plyr element (media element in iOS) and not fullscreen container

* Fixing "missing code in detail" for PlyrEvent type

When using typescript and listening for youtube statechange event, it is missing the code property definition inside the event (even though it is provided in the code).
By making events a map of key-value, we can add easily custom event type for specific event name. Since YouTube "statechange" event differs from the basic PlyrEvent, I added a new Event Type "PlyrStateChangeEvent" having a code property corresponding to a YoutubeState enum defined by the YouTube API documentation.
This pattern follows how addEventListener in the lib.dom.d.ts is defined.

* Update link to working dash.js demo (was broken)

* Fix PreviewThumbnailsOptions type

According to the docs, the `src` should also accept an array of strings.

* fix issue #1872

* Check if key is a string before attempt --plyr checking

* Fix for Slow loading videos not autoplaying

* Fix for Slow loading videos not autoplaying

* Network requests are not cancelled after the player is destroyed

* Fix for apect ratio problem when using Vimeo player on mobile devices (issue #1940)

* chore: update packages and linting

* Invoke custom listener on triggering fullscreen via double-click

* Fix volume when unmuting from volume 0

* adding a nice Svelte plugin that I found

* Add missing unit to calc in media query

* Assigning player's lastSeekTime on rewind/fast forward to prevent immediate controls hide on mobile

* Fix youtube not working when player is inside shadow dom

* v3.6.2

* ESLint to use common config

* add BitChute to users list

* Fix aspect ratio issue

* Revert noCookie change

* feat: demo radius tweaks

* fix: poster image shouldn’t receive click events

* chore: package updates

* chore: linting

* feat: custom controls option for embedded players

* Package upgrades

* ESLint to use common config

* Linting changes

* Update README.md

* chore: formatting

* fix: revert pointer events change for poster

* fix: hack for Safari 14 not repainting Vimeo embed on entering fullscreen

* fix: demo using custom controls for YouTube

* doc: Add STROLLÿN among the list of Plyr users

* Fixes #2005

* fix: overflowing volume slider

* chore: clean up CSS

* fix: hide poster when not using custom controls

* Package upgrades

* ESLint to use common config

* Linting changes

* chore: revert customControls default option (to prevent breaking change)

* docs: changelog for v3.6.3

Co-authored-by: Som Meaden <som@theprojectsomething.com>
Co-authored-by: akuma06 <demon.akuma06@gmail.com>
Co-authored-by: Jonathan Arbely <dev@jonathanarbely.de>
Co-authored-by: Takeshi <iwatakeshi@users.noreply.github.com>
Co-authored-by: Hex <hex@codeigniter.org.cn>
Co-authored-by: Syed Husain <syed.husain@appspace.com>
Co-authored-by: Danielh112 <Daniel@sbgsportssoftware.com>
Co-authored-by: Danil Stoyanov <d.stoyanov@corp.mail.ru>
Co-authored-by: Guru Prasad Srinivasa <gurupras@buffalo.edu>
Co-authored-by: Stephane Fortin Bouchard <stephane.f.bouchard@gmail.com>
Co-authored-by: Zev Averbach <zev@averba.ch>
Co-authored-by: Vincent Orback <hello@vincentorback.se>
Co-authored-by: trafium <trafium@gmail.com>
Co-authored-by: xansen <27698939+xansen@users.noreply.github.com>
Co-authored-by: zoomerdev <59863739+zoomerdev@users.noreply.github.com>
Co-authored-by: Mikaël Castellani <mikael.castellani@gmail.com>
Co-authored-by: dirkjf <d.j.faber@outlook.com>
2020-11-14 13:24:11 +11:00
Sam Potts 5d2c288721 Merge pull request #1961 from Benny739/master
fixed #1181 vimeo oembed api
2020-10-19 22:41:09 +11:00
Sam Potts 30989e4dbc Merge pull request #1982 from tbntdima/feat/fix-fulscreen-type
fix(plyr.d.ts): add force to FullScreenOptions
2020-10-15 09:09:49 +11:00
Dima An 967206c695 fix(plyr.d.ts): add force to FullScreenOptions 2020-10-14 17:09:14 +02:00
Benny739 e646207ed6 vimeo oembed api 2020-09-23 01:24:11 +02:00
Sam Potts 98dbb2e43f Merge pull request #1885 from mercuryseries/patch-1
Fix small typo
2020-08-30 15:52:19 +10:00
Sam Potts 3e70f32555 Merge pull request #1904 from sampotts/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19
2020-08-30 15:47:00 +10:00
Sam Potts 80fbeeb415 Merge pull request #1920 from Kithaitaa/Kithaitaa-patch-2
Please add our website to the "Used by" list
2020-08-30 15:46:11 +10:00
Sam Potts 8261ebd502 Merge pull request #1928 from ethanve/patch-1
fix: blankVideo type
2020-08-30 15:45:57 +10:00
Ethan Veres 6f77e21e51 chore: fix blankVideo types 2020-08-12 10:11:45 -04:00
Kith 7910fea011 Please add our website to the "Used by" list
I would be happy if you could add our website to the "used by" list. We are a video game magazine that has been using Plyr for some time now for. Thx in advance.

Besides that i send you a donation through PayPal a few days ago =)
2020-08-05 10:44:41 +02:00
dependabot[bot] 8e0cde2949 Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-16 18:00:08 +00:00
Sam Potts 391afe2814 Merge pull request #1889 from rutheneum-bote/patch-1
Add us to the "Used by" list
2020-06-30 22:08:25 +10:00
Rutheneum-Bote 68e3944bb8 Add us to the "Used by" list
We're the students' newspaper of the Goethe Grammar School/Rutheneum since 1608 and we use Plyr in order to present the students' songs that were submitted to our school's creativity contest.
2020-06-30 11:47:09 +00:00
Honoré Hounwanou 2ee6ae16b2 Fix small typo
Add missing "d" in video.
2020-06-27 10:18:49 -04:00
Sam Potts ef85cb6195 Merge pull request #1822 from zoomerdev/patch-1
Add BitChute to users list
2020-05-05 15:26:29 +10:00
zoomerdev dc8612fcd0 add BitChute to users list 2020-05-05 01:19:42 -04:00
58 changed files with 3472 additions and 1916 deletions
+16 -28
View File
@@ -1,30 +1,18 @@
{ {
"parser": "babel-eslint", "parser": "babel-eslint",
"extends": ["airbnb-base", "prettier"], "extends": ["@sampotts/eslint-config/es6"],
"plugins": ["simple-import-sort", "import"], "env": {
"env": { "browser": true,
"browser": true, "es6": true
"es6": true },
}, "globals": {
"globals": { "Plyr": false,
"Plyr": false, "jQuery": false
"jQuery": false },
}, "rules": {
"rules": { "import/no-cycle": "warn"
"import/no-cycle": "warn", },
"padding-line-between-statements": [ "parserOptions": {
"error", "sourceType": "module"
{ }
"blankLine": "never",
"prev": ["singleline-const", "singleline-let", "singleline-var"],
"next": ["singleline-const", "singleline-let", "singleline-var"]
}
],
"sort-imports": "off",
"import/order": "off",
"simple-import-sort/sort": "error"
},
"parserOptions": {
"sourceType": "module"
}
} }
+15
View File
@@ -1,3 +1,18 @@
### v3.6.3
- Fix volume when unmuting from volume 0 using YouTube (thanks @stephanefbouchard)
- Add missing unit to calc in media query (thanks @vincentorback)
- Assigning player's lastSeekTime on rewind/fast forward to prevent immediate controls hide on mobile (thanks @trafium)
- Fix for volume control overflowing in Firefox (thanks @dirkjf)
- Force fullscreen events to trigger on plyr element (media element in iOS) and not fullscreen container (thanks @theprojectsomething)
- TypeScript types improvements (thanks @akuma06 & @iwatakeshi)
- Dash demo link fixed (thanks @jonathanarbely)
- Fix "A `ReferenceError: _classCallCheck is not defined` error has occurred." error (thanks @hex-ci)
- Fix issue with CSS custom property check (thanks @syedhusain-appspace)
- Fix for slow loading videos not autoplaying (thanks @DanielHuntleySBG)
- Fix for betwork requests are not cancelled after the player is destroyed (thanks @DanielHuntleySBG)
- Added option to disable custom controls for YouTube and Vimeo
### v3.6.2 ### v3.6.2
- Fixes for CSS Custom Property related errors in some build tools (thanks @Bashev) - Fixes for CSS Custom Property related errors in some build tools (thanks @Bashev)
+11 -6
View File
@@ -31,7 +31,7 @@ Plyr is a simple, lightweight, accessible and customizable HTML5, YouTube and Vi
### Demos ### Demos
You can try Plyr in Codepen using our minimal templates: [HTML5 video](https://codepen.io/pen?template=bKeqpr), [HTML5 audio](https://codepen.io/pen?template=rKLywR), [YouTube](https://codepen.io/pen?template=GGqbbJ), [Vimeo](https://codepen.io/pen?template=bKeXNq). For Streaming we also have example integrations with: [Dash.js](https://codepen.io/pen?template=zaBgBy), [Hls.js](https://codepen.io/pen?template=oyLKQb) and [Shaka Player](https://codepen.io/pen?template=ZRpzZO) You can try Plyr in Codepen using our minimal templates: [HTML5 video](https://codepen.io/pen?template=bKeqpr), [HTML5 audio](https://codepen.io/pen?template=rKLywR), [YouTube](https://codepen.io/pen?template=GGqbbJ), [Vimeo](https://codepen.io/pen?template=bKeXNq). For Streaming we also have example integrations with: [Dash.js](https://codepen.io/pen?template=GRoogML), [Hls.js](https://codepen.io/pen?template=oyLKQb) and [Shaka Player](https://codepen.io/pen?template=ZRpzZO)
# Quick setup # Quick setup
@@ -134,13 +134,13 @@ See [initialising](#initialising) for more information on advanced setups.
You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build. You can use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript. There's 2 versions; one with and one without [polyfills](#polyfills). My recommendation would be to manage polyfills seperately as part of your application but to make life easier you can use the polyfilled build.
```html ```html
<script src="https://cdn.plyr.io/3.6.2/plyr.js"></script> <script src="https://cdn.plyr.io/3.6.3/plyr.js"></script>
``` ```
...or... ...or...
```html ```html
<script src="https://cdn.plyr.io/3.6.2/plyr.polyfilled.js"></script> <script src="https://cdn.plyr.io/3.6.3/plyr.polyfilled.js"></script>
``` ```
## CSS ## CSS
@@ -154,13 +154,13 @@ Include the `plyr.css` stylsheet into your `<head>`.
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following: If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
```html ```html
<link rel="stylesheet" href="https://cdn.plyr.io/3.6.2/plyr.css" /> <link rel="stylesheet" href="https://cdn.plyr.io/3.6.3/plyr.css" />
``` ```
## SVG Sprite ## SVG Sprite
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.6.2/plyr.svg`. reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.6.3/plyr.svg`.
# Ads # Ads
@@ -268,7 +268,7 @@ You can set them in your CSS for all players:
```html ```html
<video class="player" style="--plyr-color-main: #1ac266;"> <video class="player" style="--plyr-color-main: #1ac266;">
... ...
</vieo> </video>
``` ```
### SASS ### SASS
@@ -790,6 +790,7 @@ Some awesome folks have made plugins for CMSs and Components for JavaScript fram
| Neos | Jon Uhlmann ([@jonnitto](https://github.com/jonnitto)) | [https://packagist.org/packages/jonnitto/plyr](https://packagist.org/packages/jonnitto/plyr) | | Neos | Jon Uhlmann ([@jonnitto](https://github.com/jonnitto)) | [https://packagist.org/packages/jonnitto/plyr](https://packagist.org/packages/jonnitto/plyr) |
| Kirby | Dominik Pschenitschni ([@dpschen](https://github.com/dpschen)) | [https://github.com/dpschen/kirby-plyrtag](https://github.com/dpschen/kirby-plyrtag) | | Kirby | Dominik Pschenitschni ([@dpschen](https://github.com/dpschen)) | [https://github.com/dpschen/kirby-plyrtag](https://github.com/dpschen/kirby-plyrtag) |
| REDAXO | FriendsOfRedaxo / skerbis ([@skerbis](https://friendsofredaxo.github.io)) | [https://github.com/FriendsOfREDAXO/plyr](https://github.com/FriendsOfREDAXO/plyr) | | REDAXO | FriendsOfRedaxo / skerbis ([@skerbis](https://friendsofredaxo.github.io)) | [https://github.com/FriendsOfREDAXO/plyr](https://github.com/FriendsOfREDAXO/plyr) |
| svelte-plyr | Ben Woodward / benwoodward ([@benwoodward](https://github.com/benwoodward)) | [https://github.com/benwoodward](https://github.com/benwoodward) |
# Issues # Issues
@@ -833,6 +834,10 @@ Plyr costs money to run, not only my time. I donate my time for free as I enjoy
- [Oscar Radio](http://oscar-radio.xyz/) - [Oscar Radio](http://oscar-radio.xyz/)
- [Sparkk TV](https://www.sparkktv.com/) - [Sparkk TV](https://www.sparkktv.com/)
- [@halfhalftravel](https://www.halfhalftravel.com/) - [@halfhalftravel](https://www.halfhalftravel.com/)
- [BitChute](https://www.bitchute.com)
- [Rutheneum-Bote](https://gymnasium-rutheneum.de/content/newspaper/kreativwettbewerb.php)
- [pressakey.com | Blog-Magazin für Videospiele](https://pressakey.com)
- [STROLLÿN: Work with a View](https://strollyn.com)
If you want to be added to the list, open a pull request. It'd be awesome to see how you're using Plyr 😎 If you want to be added to the list, open a pull request. It'd be awesome to see how you're using Plyr 😎
+1 -1
View File
File diff suppressed because one or more lines are too long
+218 -148
View File
@@ -14463,7 +14463,7 @@ typeof navigator === "object" && (function () {
check$1(typeof self == 'object' && self) || check$1(typeof self == 'object' && self) ||
check$1(typeof commonjsGlobal == 'object' && commonjsGlobal) || check$1(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-new-func
Function('return this')(); (function () { return this; })() || Function('return this')();
var fails$1 = function (exec) { var fails$1 = function (exec) {
try { try {
@@ -14658,7 +14658,7 @@ typeof navigator === "object" && (function () {
(module.exports = function (key, value) { (module.exports = function (key, value) {
return sharedStore$1[key] || (sharedStore$1[key] = value !== undefined ? value : {}); return sharedStore$1[key] || (sharedStore$1[key] = value !== undefined ? value : {});
})('versions', []).push({ })('versions', []).push({
version: '3.6.5', version: '3.7.0',
mode: 'global', mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)' copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
}); });
@@ -14696,11 +14696,12 @@ typeof navigator === "object" && (function () {
}; };
if (nativeWeakMap$1) { if (nativeWeakMap$1) {
var store$3 = new WeakMap$4(); var store$3 = sharedStore$1.state || (sharedStore$1.state = new WeakMap$4());
var wmget$1 = store$3.get; var wmget$1 = store$3.get;
var wmhas$1 = store$3.has; var wmhas$1 = store$3.has;
var wmset$1 = store$3.set; var wmset$1 = store$3.set;
set$3 = function (it, metadata) { set$3 = function (it, metadata) {
metadata.facade = it;
wmset$1.call(store$3, it, metadata); wmset$1.call(store$3, it, metadata);
return metadata; return metadata;
}; };
@@ -14714,6 +14715,7 @@ typeof navigator === "object" && (function () {
var STATE$1 = sharedKey$1('state'); var STATE$1 = sharedKey$1('state');
hiddenKeys$2[STATE$1] = true; hiddenKeys$2[STATE$1] = true;
set$3 = function (it, metadata) { set$3 = function (it, metadata) {
metadata.facade = it;
createNonEnumerableProperty$1(it, STATE$1, metadata); createNonEnumerableProperty$1(it, STATE$1, metadata);
return metadata; return metadata;
}; };
@@ -14742,9 +14744,15 @@ typeof navigator === "object" && (function () {
var unsafe = options ? !!options.unsafe : false; var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false; var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false; var noTargetGet = options ? !!options.noTargetGet : false;
var state;
if (typeof value == 'function') { if (typeof value == 'function') {
if (typeof key == 'string' && !has$2(value, 'name')) createNonEnumerableProperty$1(value, 'name', key); if (typeof key == 'string' && !has$2(value, 'name')) {
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : ''); createNonEnumerableProperty$1(value, 'name', key);
}
state = enforceInternalState(value);
if (!state.source) {
state.source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
} }
if (O === global_1$1) { if (O === global_1$1) {
if (simple) O[key] = value; if (simple) O[key] = value;
@@ -15370,14 +15378,20 @@ typeof navigator === "object" && (function () {
// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables // https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables$1(FIND$1); addToUnscopables$1(FIND$1);
var iteratorClose = function (iterator) {
var returnMethod = iterator['return'];
if (returnMethod !== undefined) {
return anObject$1(returnMethod.call(iterator)).value;
}
};
// call something on iterator step with safe closing on error // call something on iterator step with safe closing on error
var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) { var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) {
try { try {
return ENTRIES ? fn(anObject$1(value)[0], value[1]) : fn(value); return ENTRIES ? fn(anObject$1(value)[0], value[1]) : fn(value);
// 7.4.6 IteratorClose(iterator, completion) // 7.4.6 IteratorClose(iterator, completion)
} catch (error) { } catch (error) {
var returnMethod = iterator['return']; iteratorClose(iterator);
if (returnMethod !== undefined) anObject$1(returnMethod.call(iterator));
throw error; throw error;
} }
}; };
@@ -16098,11 +16112,11 @@ typeof navigator === "object" && (function () {
var regexp = /./; var regexp = /./;
try { try {
'/./'[METHOD_NAME](regexp); '/./'[METHOD_NAME](regexp);
} catch (e) { } catch (error1) {
try { try {
regexp[MATCH$4] = false; regexp[MATCH$4] = false;
return '/./'[METHOD_NAME](regexp); return '/./'[METHOD_NAME](regexp);
} catch (f) { /* empty */ } } catch (error2) { /* empty */ }
} return false; } return false;
}; };
@@ -16422,16 +16436,31 @@ typeof navigator === "object" && (function () {
var internalMetadata_3$1 = internalMetadata$1.getWeakData; var internalMetadata_3$1 = internalMetadata$1.getWeakData;
var internalMetadata_4$1 = internalMetadata$1.onFreeze; var internalMetadata_4$1 = internalMetadata$1.onFreeze;
var iterate_1$1 = createCommonjsModule(function (module) {
var Result = function (stopped, result) { var Result = function (stopped, result) {
this.stopped = stopped; this.stopped = stopped;
this.result = result; this.result = result;
}; };
var iterate = module.exports = function (iterable, fn, that, AS_ENTRIES, IS_ITERATOR) { var iterate = function (iterable, unboundFunction, options) {
var boundFunction = functionBindContext$1(fn, that, AS_ENTRIES ? 2 : 1); var that = options && options.that;
var AS_ENTRIES = !!(options && options.AS_ENTRIES);
var IS_ITERATOR = !!(options && options.IS_ITERATOR);
var INTERRUPTED = !!(options && options.INTERRUPTED);
var fn = functionBindContext$1(unboundFunction, that, 1 + AS_ENTRIES + INTERRUPTED);
var iterator, iterFn, index, length, result, next, step; var iterator, iterFn, index, length, result, next, step;
var stop = function (condition) {
if (iterator) iteratorClose(iterator);
return new Result(true, condition);
};
var callFn = function (value) {
if (AS_ENTRIES) {
anObject$1(value);
return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
} return INTERRUPTED ? fn(value, stop) : fn(value);
};
if (IS_ITERATOR) { if (IS_ITERATOR) {
iterator = iterable; iterator = iterable;
} else { } else {
@@ -16440,9 +16469,7 @@ typeof navigator === "object" && (function () {
// optimisation for array iterators // optimisation for array iterators
if (isArrayIteratorMethod$1(iterFn)) { if (isArrayIteratorMethod$1(iterFn)) {
for (index = 0, length = toLength$1(iterable.length); length > index; index++) { for (index = 0, length = toLength$1(iterable.length); length > index; index++) {
result = AS_ENTRIES result = callFn(iterable[index]);
? boundFunction(anObject$1(step = iterable[index])[0], step[1])
: boundFunction(iterable[index]);
if (result && result instanceof Result) return result; if (result && result instanceof Result) return result;
} return new Result(false); } return new Result(false);
} }
@@ -16451,16 +16478,16 @@ typeof navigator === "object" && (function () {
next = iterator.next; next = iterator.next;
while (!(step = next.call(iterator)).done) { while (!(step = next.call(iterator)).done) {
result = callWithSafeIterationClosing$1(iterator, boundFunction, step.value, AS_ENTRIES); try {
result = callFn(step.value);
} catch (error) {
iteratorClose(iterator);
throw error;
}
if (typeof result == 'object' && result && result instanceof Result) return result; if (typeof result == 'object' && result && result instanceof Result) return result;
} return new Result(false); } return new Result(false);
}; };
iterate.stop = function (result) {
return new Result(true, result);
};
});
var anInstance$1 = function (it, Constructor, name) { var anInstance$1 = function (it, Constructor, name) {
if (!(it instanceof Constructor)) { if (!(it instanceof Constructor)) {
throw TypeError('Incorrect ' + (name ? name + ' ' : '') + 'invocation'); throw TypeError('Incorrect ' + (name ? name + ' ' : '') + 'invocation');
@@ -16524,7 +16551,7 @@ typeof navigator === "object" && (function () {
Constructor = wrapper(function (dummy, iterable) { Constructor = wrapper(function (dummy, iterable) {
anInstance$1(dummy, Constructor, CONSTRUCTOR_NAME); anInstance$1(dummy, Constructor, CONSTRUCTOR_NAME);
var that = inheritIfRequired$1(new NativeConstructor(), dummy, Constructor); var that = inheritIfRequired$1(new NativeConstructor(), dummy, Constructor);
if (iterable != undefined) iterate_1$1(iterable, that[ADDER], that, IS_MAP); if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
return that; return that;
}); });
Constructor.prototype = NativePrototype; Constructor.prototype = NativePrototype;
@@ -16614,7 +16641,7 @@ typeof navigator === "object" && (function () {
id: id$3++, id: id$3++,
frozen: undefined frozen: undefined
}); });
if (iterable != undefined) iterate_1$1(iterable, that[ADDER], that, IS_MAP); if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
}); });
var getInternalState = internalStateGetterFor$1(CONSTRUCTOR_NAME); var getInternalState = internalStateGetterFor$1(CONSTRUCTOR_NAME);
@@ -17452,7 +17479,7 @@ typeof navigator === "object" && (function () {
var URLSearchParamsPrototype$1 = URLSearchParamsConstructor$1.prototype; var URLSearchParamsPrototype$1 = URLSearchParamsConstructor$1.prototype;
redefineAll$1(URLSearchParamsPrototype$1, { redefineAll$1(URLSearchParamsPrototype$1, {
// `URLSearchParams.prototype.appent` method // `URLSearchParams.prototype.append` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-append // https://url.spec.whatwg.org/#dom-urlsearchparams-append
append: function append(name, value) { append: function append(name, value) {
validateArgumentsLength$1(arguments.length, 2); validateArgumentsLength$1(arguments.length, 2);
@@ -19605,6 +19632,8 @@ typeof navigator === "object" && (function () {
var engineIsIos$1 = /(iphone|ipod|ipad).*applewebkit/i.test(engineUserAgent$1); var engineIsIos$1 = /(iphone|ipod|ipad).*applewebkit/i.test(engineUserAgent$1);
var engineIsNode = classofRaw$1(global_1$1.process) == 'process';
var location$1 = global_1$1.location; var location$1 = global_1$1.location;
var set$4 = global_1$1.setImmediate; var set$4 = global_1$1.setImmediate;
var clear$1 = global_1$1.clearImmediate; var clear$1 = global_1$1.clearImmediate;
@@ -19657,7 +19686,7 @@ typeof navigator === "object" && (function () {
delete queue$1[id]; delete queue$1[id];
}; };
// Node.js 0.8- // Node.js 0.8-
if (classofRaw$1(process$6) == 'process') { if (engineIsNode) {
defer$1 = function (id) { defer$1 = function (id) {
process$6.nextTick(runner$1(id)); process$6.nextTick(runner$1(id));
}; };
@@ -19679,8 +19708,8 @@ typeof navigator === "object" && (function () {
global_1$1.addEventListener && global_1$1.addEventListener &&
typeof postMessage == 'function' && typeof postMessage == 'function' &&
!global_1$1.importScripts && !global_1$1.importScripts &&
!fails$1(post$1) && location$1 && location$1.protocol !== 'file:' &&
location$1.protocol !== 'file:' !fails$1(post$1)
) { ) {
defer$1 = post$1; defer$1 = post$1;
global_1$1.addEventListener('message', listener$1, false); global_1$1.addEventListener('message', listener$1, false);
@@ -19706,14 +19735,14 @@ typeof navigator === "object" && (function () {
}; };
var getOwnPropertyDescriptor$7 = objectGetOwnPropertyDescriptor$1.f; var getOwnPropertyDescriptor$7 = objectGetOwnPropertyDescriptor$1.f;
var macrotask$1 = task$2.set; var macrotask$1 = task$2.set;
var MutationObserver$2 = global_1$1.MutationObserver || global_1$1.WebKitMutationObserver; var MutationObserver$2 = global_1$1.MutationObserver || global_1$1.WebKitMutationObserver;
var document$4 = global_1$1.document;
var process$7 = global_1$1.process; var process$7 = global_1$1.process;
var Promise$2 = global_1$1.Promise; var Promise$2 = global_1$1.Promise;
var IS_NODE$2 = classofRaw$1(process$7) == 'process';
// Node.js 11 shows ExperimentalWarning on getting `queueMicrotask` // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
var queueMicrotaskDescriptor$1 = getOwnPropertyDescriptor$7(global_1$1, 'queueMicrotask'); var queueMicrotaskDescriptor$1 = getOwnPropertyDescriptor$7(global_1$1, 'queueMicrotask');
var queueMicrotask$1 = queueMicrotaskDescriptor$1 && queueMicrotaskDescriptor$1.value; var queueMicrotask$1 = queueMicrotaskDescriptor$1 && queueMicrotaskDescriptor$1.value;
@@ -19724,7 +19753,7 @@ typeof navigator === "object" && (function () {
if (!queueMicrotask$1) { if (!queueMicrotask$1) {
flush$1 = function () { flush$1 = function () {
var parent, fn; var parent, fn;
if (IS_NODE$2 && (parent = process$7.domain)) parent.exit(); if (engineIsNode && (parent = process$7.domain)) parent.exit();
while (head$1) { while (head$1) {
fn = head$1.fn; fn = head$1.fn;
head$1 = head$1.next; head$1 = head$1.next;
@@ -19739,15 +19768,10 @@ typeof navigator === "object" && (function () {
if (parent) parent.enter(); if (parent) parent.enter();
}; };
// Node.js
if (IS_NODE$2) {
notify$2 = function () {
process$7.nextTick(flush$1);
};
// browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339 // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
} else if (MutationObserver$2 && !engineIsIos$1) { if (!engineIsIos$1 && !engineIsNode && MutationObserver$2 && document$4) {
toggle$1 = true; toggle$1 = true;
node$1 = document.createTextNode(''); node$1 = document$4.createTextNode('');
new MutationObserver$2(flush$1).observe(node$1, { characterData: true }); new MutationObserver$2(flush$1).observe(node$1, { characterData: true });
notify$2 = function () { notify$2 = function () {
node$1.data = toggle$1 = !toggle$1; node$1.data = toggle$1 = !toggle$1;
@@ -19760,6 +19784,11 @@ typeof navigator === "object" && (function () {
notify$2 = function () { notify$2 = function () {
then$1.call(promise$1, flush$1); then$1.call(promise$1, flush$1);
}; };
// Node.js without promises
} else if (engineIsNode) {
notify$2 = function () {
process$7.nextTick(flush$1);
};
// for other environments - macrotask based on: // for other environments - macrotask based on:
// - setImmediate // - setImmediate
// - MessageChannel // - MessageChannel
@@ -19838,6 +19867,7 @@ typeof navigator === "object" && (function () {
var SPECIES$c = wellKnownSymbol$1('species'); var SPECIES$c = wellKnownSymbol$1('species');
var PROMISE$1 = 'Promise'; var PROMISE$1 = 'Promise';
var getInternalState$8 = internalState$1.get; var getInternalState$8 = internalState$1.get;
@@ -19845,13 +19875,13 @@ typeof navigator === "object" && (function () {
var getInternalPromiseState$1 = internalState$1.getterFor(PROMISE$1); var getInternalPromiseState$1 = internalState$1.getterFor(PROMISE$1);
var PromiseConstructor$1 = nativePromiseConstructor$1; var PromiseConstructor$1 = nativePromiseConstructor$1;
var TypeError$2 = global_1$1.TypeError; var TypeError$2 = global_1$1.TypeError;
var document$4 = global_1$1.document; var document$5 = global_1$1.document;
var process$8 = global_1$1.process; var process$8 = global_1$1.process;
var $fetch$3 = getBuiltIn$1('fetch'); var $fetch$3 = getBuiltIn$1('fetch');
var newPromiseCapability$3 = newPromiseCapability$2.f; var newPromiseCapability$3 = newPromiseCapability$2.f;
var newGenericPromiseCapability$1 = newPromiseCapability$3; var newGenericPromiseCapability$1 = newPromiseCapability$3;
var IS_NODE$3 = classofRaw$1(process$8) == 'process'; var DISPATCH_EVENT$1 = !!(document$5 && document$5.createEvent && global_1$1.dispatchEvent);
var DISPATCH_EVENT$1 = !!(document$4 && document$4.createEvent && global_1$1.dispatchEvent); var NATIVE_REJECTION_EVENT = typeof PromiseRejectionEvent == 'function';
var UNHANDLED_REJECTION$1 = 'unhandledrejection'; var UNHANDLED_REJECTION$1 = 'unhandledrejection';
var REJECTION_HANDLED$1 = 'rejectionhandled'; var REJECTION_HANDLED$1 = 'rejectionhandled';
var PENDING$1 = 0; var PENDING$1 = 0;
@@ -19869,7 +19899,7 @@ typeof navigator === "object" && (function () {
// We can't detect it synchronously, so just check versions // We can't detect it synchronously, so just check versions
if (engineV8Version$1 === 66) return true; if (engineV8Version$1 === 66) return true;
// Unhandled rejections tracking support, NodeJS Promise without it fails @@species test // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
if (!IS_NODE$3 && typeof PromiseRejectionEvent != 'function') return true; if (!engineIsNode && !NATIVE_REJECTION_EVENT) return true;
} }
// We can't use @@species feature detection in V8 since it causes // We can't use @@species feature detection in V8 since it causes
// deoptimization and performance degradation // deoptimization and performance degradation
@@ -19895,7 +19925,7 @@ typeof navigator === "object" && (function () {
return isObject$2(it) && typeof (then = it.then) == 'function' ? then : false; return isObject$2(it) && typeof (then = it.then) == 'function' ? then : false;
}; };
var notify$3 = function (promise, state, isReject) { var notify$3 = function (state, isReject) {
if (state.notified) return; if (state.notified) return;
state.notified = true; state.notified = true;
var chain = state.reactions; var chain = state.reactions;
@@ -19914,7 +19944,7 @@ typeof navigator === "object" && (function () {
try { try {
if (handler) { if (handler) {
if (!ok) { if (!ok) {
if (state.rejection === UNHANDLED$1) onHandleUnhandled$1(promise, state); if (state.rejection === UNHANDLED$1) onHandleUnhandled$1(state);
state.rejection = HANDLED$1; state.rejection = HANDLED$1;
} }
if (handler === true) result = value; if (handler === true) result = value;
@@ -19939,36 +19969,37 @@ typeof navigator === "object" && (function () {
} }
state.reactions = []; state.reactions = [];
state.notified = false; state.notified = false;
if (isReject && !state.rejection) onUnhandled$1(promise, state); if (isReject && !state.rejection) onUnhandled$1(state);
}); });
}; };
var dispatchEvent$1 = function (name, promise, reason) { var dispatchEvent$1 = function (name, promise, reason) {
var event, handler; var event, handler;
if (DISPATCH_EVENT$1) { if (DISPATCH_EVENT$1) {
event = document$4.createEvent('Event'); event = document$5.createEvent('Event');
event.promise = promise; event.promise = promise;
event.reason = reason; event.reason = reason;
event.initEvent(name, false, true); event.initEvent(name, false, true);
global_1$1.dispatchEvent(event); global_1$1.dispatchEvent(event);
} else event = { promise: promise, reason: reason }; } else event = { promise: promise, reason: reason };
if (handler = global_1$1['on' + name]) handler(event); if (!NATIVE_REJECTION_EVENT && (handler = global_1$1['on' + name])) handler(event);
else if (name === UNHANDLED_REJECTION$1) hostReportErrors$1('Unhandled promise rejection', reason); else if (name === UNHANDLED_REJECTION$1) hostReportErrors$1('Unhandled promise rejection', reason);
}; };
var onUnhandled$1 = function (promise, state) { var onUnhandled$1 = function (state) {
task$3.call(global_1$1, function () { task$3.call(global_1$1, function () {
var promise = state.facade;
var value = state.value; var value = state.value;
var IS_UNHANDLED = isUnhandled$1(state); var IS_UNHANDLED = isUnhandled$1(state);
var result; var result;
if (IS_UNHANDLED) { if (IS_UNHANDLED) {
result = perform$1(function () { result = perform$1(function () {
if (IS_NODE$3) { if (engineIsNode) {
process$8.emit('unhandledRejection', value, promise); process$8.emit('unhandledRejection', value, promise);
} else dispatchEvent$1(UNHANDLED_REJECTION$1, promise, value); } else dispatchEvent$1(UNHANDLED_REJECTION$1, promise, value);
}); });
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
state.rejection = IS_NODE$3 || isUnhandled$1(state) ? UNHANDLED$1 : HANDLED$1; state.rejection = engineIsNode || isUnhandled$1(state) ? UNHANDLED$1 : HANDLED$1;
if (result.error) throw result.value; if (result.error) throw result.value;
} }
}); });
@@ -19978,55 +20009,56 @@ typeof navigator === "object" && (function () {
return state.rejection !== HANDLED$1 && !state.parent; return state.rejection !== HANDLED$1 && !state.parent;
}; };
var onHandleUnhandled$1 = function (promise, state) { var onHandleUnhandled$1 = function (state) {
task$3.call(global_1$1, function () { task$3.call(global_1$1, function () {
if (IS_NODE$3) { var promise = state.facade;
if (engineIsNode) {
process$8.emit('rejectionHandled', promise); process$8.emit('rejectionHandled', promise);
} else dispatchEvent$1(REJECTION_HANDLED$1, promise, state.value); } else dispatchEvent$1(REJECTION_HANDLED$1, promise, state.value);
}); });
}; };
var bind$1 = function (fn, promise, state, unwrap) { var bind$1 = function (fn, state, unwrap) {
return function (value) { return function (value) {
fn(promise, state, value, unwrap); fn(state, value, unwrap);
}; };
}; };
var internalReject$1 = function (promise, state, value, unwrap) { var internalReject$1 = function (state, value, unwrap) {
if (state.done) return; if (state.done) return;
state.done = true; state.done = true;
if (unwrap) state = unwrap; if (unwrap) state = unwrap;
state.value = value; state.value = value;
state.state = REJECTED$1; state.state = REJECTED$1;
notify$3(promise, state, true); notify$3(state, true);
}; };
var internalResolve$1 = function (promise, state, value, unwrap) { var internalResolve$1 = function (state, value, unwrap) {
if (state.done) return; if (state.done) return;
state.done = true; state.done = true;
if (unwrap) state = unwrap; if (unwrap) state = unwrap;
try { try {
if (promise === value) throw TypeError$2("Promise can't be resolved itself"); if (state.facade === value) throw TypeError$2("Promise can't be resolved itself");
var then = isThenable$2(value); var then = isThenable$2(value);
if (then) { if (then) {
microtask$1(function () { microtask$1(function () {
var wrapper = { done: false }; var wrapper = { done: false };
try { try {
then.call(value, then.call(value,
bind$1(internalResolve$1, promise, wrapper, state), bind$1(internalResolve$1, wrapper, state),
bind$1(internalReject$1, promise, wrapper, state) bind$1(internalReject$1, wrapper, state)
); );
} catch (error) { } catch (error) {
internalReject$1(promise, wrapper, error, state); internalReject$1(wrapper, error, state);
} }
}); });
} else { } else {
state.value = value; state.value = value;
state.state = FULFILLED$1; state.state = FULFILLED$1;
notify$3(promise, state, false); notify$3(state, false);
} }
} catch (error) { } catch (error) {
internalReject$1(promise, { done: false }, error, state); internalReject$1({ done: false }, error, state);
} }
}; };
@@ -20039,9 +20071,9 @@ typeof navigator === "object" && (function () {
Internal$1.call(this); Internal$1.call(this);
var state = getInternalState$8(this); var state = getInternalState$8(this);
try { try {
executor(bind$1(internalResolve$1, this, state), bind$1(internalReject$1, this, state)); executor(bind$1(internalResolve$1, state), bind$1(internalReject$1, state));
} catch (error) { } catch (error) {
internalReject$1(this, state, error); internalReject$1(state, error);
} }
}; };
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
@@ -20065,10 +20097,10 @@ typeof navigator === "object" && (function () {
var reaction = newPromiseCapability$3(speciesConstructor$1(this, PromiseConstructor$1)); var reaction = newPromiseCapability$3(speciesConstructor$1(this, PromiseConstructor$1));
reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
reaction.fail = typeof onRejected == 'function' && onRejected; reaction.fail = typeof onRejected == 'function' && onRejected;
reaction.domain = IS_NODE$3 ? process$8.domain : undefined; reaction.domain = engineIsNode ? process$8.domain : undefined;
state.parent = true; state.parent = true;
state.reactions.push(reaction); state.reactions.push(reaction);
if (state.state != PENDING$1) notify$3(this, state, false); if (state.state != PENDING$1) notify$3(state, false);
return reaction.promise; return reaction.promise;
}, },
// `Promise.prototype.catch` method // `Promise.prototype.catch` method
@@ -20081,8 +20113,8 @@ typeof navigator === "object" && (function () {
var promise = new Internal$1(); var promise = new Internal$1();
var state = getInternalState$8(promise); var state = getInternalState$8(promise);
this.promise = promise; this.promise = promise;
this.resolve = bind$1(internalResolve$1, promise, state); this.resolve = bind$1(internalResolve$1, state);
this.reject = bind$1(internalReject$1, promise, state); this.reject = bind$1(internalReject$1, state);
}; };
newPromiseCapability$2.f = newPromiseCapability$3 = function (C) { newPromiseCapability$2.f = newPromiseCapability$3 = function (C) {
return C === PromiseConstructor$1 || C === PromiseWrapper$1 return C === PromiseConstructor$1 || C === PromiseWrapper$1
@@ -20153,7 +20185,7 @@ typeof navigator === "object" && (function () {
var values = []; var values = [];
var counter = 0; var counter = 0;
var remaining = 1; var remaining = 1;
iterate_1$1(iterable, function (promise) { iterate(iterable, function (promise) {
var index = counter++; var index = counter++;
var alreadyCalled = false; var alreadyCalled = false;
values.push(undefined); values.push(undefined);
@@ -20178,7 +20210,7 @@ typeof navigator === "object" && (function () {
var reject = capability.reject; var reject = capability.reject;
var result = perform$1(function () { var result = perform$1(function () {
var $promiseResolve = aFunction$3(C.resolve); var $promiseResolve = aFunction$3(C.resolve);
iterate_1$1(iterable, function (promise) { iterate(iterable, function (promise) {
$promiseResolve.call(C, promise).then(capability.resolve, reject); $promiseResolve.call(C, promise).then(capability.resolve, reject);
}); });
}); });
@@ -20425,12 +20457,17 @@ typeof navigator === "object" && (function () {
var STRICT_METHOD$a = arrayMethodIsStrict$1('reduce'); var STRICT_METHOD$a = arrayMethodIsStrict$1('reduce');
var USES_TO_LENGTH$i = arrayMethodUsesToLength$1('reduce', { 1: 0 }); var USES_TO_LENGTH$i = arrayMethodUsesToLength$1('reduce', { 1: 0 });
// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG = !engineIsNode && engineV8Version$1 > 79 && engineV8Version$1 < 83;
// `Array.prototype.reduce` method // `Array.prototype.reduce` method
// https://tc39.github.io/ecma262/#sec-array.prototype.reduce // https://tc39.github.io/ecma262/#sec-array.prototype.reduce
_export$1({ target: 'Array', proto: true, forced: !STRICT_METHOD$a || !USES_TO_LENGTH$i }, { _export$1({ target: 'Array', proto: true, forced: !STRICT_METHOD$a || !USES_TO_LENGTH$i || CHROME_BUG }, {
reduce: function reduce(callbackfn /* , initialValue */) { reduce: function reduce(callbackfn /* , initialValue */) {
return $reduce$1(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined); return $reduce$1(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
} }
@@ -21064,7 +21101,12 @@ typeof navigator === "object" && (function () {
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10); var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
if (this.fullscreen.active) {
wrapper.style.paddingBottom = null;
} else {
this.media.style.transform = "translateY(-".concat(offset, "%)");
}
} else if (this.isHTML5) { } else if (this.isHTML5) {
wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
} }
@@ -23644,7 +23686,7 @@ typeof navigator === "object" && (function () {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.6.2/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.6.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
// Quality default // Quality default
@@ -23762,7 +23804,7 @@ typeof navigator === "object" && (function () {
vimeo: { vimeo: {
sdk: 'https://player.vimeo.com/api/player.js', sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}', iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json' api: 'https://vimeo.com/api/oembed.json?url={0}'
}, },
youtube: { youtube: {
sdk: 'https://www.youtube.com/iframe_api', sdk: 'https://www.youtube.com/iframe_api',
@@ -23932,24 +23974,27 @@ typeof navigator === "object" && (function () {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// Custom settings from Plyr
customControls: true,
referrerPolicy: null,
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account // Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc) // (which allows us to properly hide controls without CSS hacks, etc)
premium: false, premium: false
// Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: true,
// Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
showinfo: 0, showinfo: 0,
// Hide info // Hide info
iv_load_policy: 3, iv_load_policy: 3,
// Hide annotations // Hide annotations
modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) modestbranding: 1,
// Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: true,
noCookie: false // Whether to use an alternative version of YouTube without cookies
} }
}; };
@@ -24068,7 +24113,7 @@ typeof navigator === "object" && (function () {
return; return;
} }
_this.toggle(); _this.player.listeners.proxy(event, _this.toggle, 'fullscreen');
}); // Tap focus when in fullscreen }); // Tap focus when in fullscreen
on.call(this, this.player.elements.container, 'keydown', function (event) { on.call(this, this.player.elements.container, 'keydown', function (event) {
@@ -24091,10 +24136,12 @@ typeof navigator === "object" && (function () {
if (is$2.element(button)) { if (is$2.element(button)) {
button.pressed = this.active; button.pressed = this.active;
} // Trigger an event } // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up
triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); var target = this.target === this.player.media ? this.target : this.player.elements.container; // Trigger an event
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
} }
}, { }, {
key: "toggleFallback", key: "toggleFallback",
@@ -24489,7 +24536,9 @@ typeof navigator === "object" && (function () {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('data-poster', poster); // Wait until ui is ready this.media.setAttribute('data-poster', poster); // Show the poster
this.elements.poster.removeAttribute('hidden'); // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@@ -24573,7 +24622,7 @@ typeof navigator === "object" && (function () {
// Loop through values (as they are the keys when the object is spread 🤔) // Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) { .filter(function (key) {
return !is$2.empty(key) && key.startsWith('--plyr'); return !is$2.empty(key) && is$2.string(key) && key.startsWith('--plyr');
}).forEach(function (key) { }).forEach(function (key) {
// Set on the container // Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element _this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
@@ -24921,7 +24970,14 @@ typeof navigator === "object" && (function () {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // Horrible hack for Safari 14 not repainting properly on entering fullscreen
if (isEnter) {
setTimeout(function () {
return repaint(elements.container);
}, 100);
} // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@@ -25112,9 +25168,17 @@ typeof navigator === "object" && (function () {
this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind
this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind this.bind(elements.buttons.rewind, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after rewind
player.lastSeekTime = Date.now();
player.rewind();
}, 'rewind'); // Rewind
this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle this.bind(elements.buttons.fastForward, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after fast forward
player.lastSeekTime = Date.now();
player.forward();
}, 'fastForward'); // Mute toggle
this.bind(elements.buttons.mute, 'click', function () { this.bind(elements.buttons.mute, 'click', function () {
player.muted = !player.muted; player.muted = !player.muted;
@@ -25822,35 +25886,32 @@ typeof navigator === "object" && (function () {
} // Inject the package } // Inject the package
var poster = player.poster; if (premium || !config.customControls) {
iframe.setAttribute('data-poster', player.poster);
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media); player.media = replaceElement(iframe, player.media);
} else { } else {
var wrapper = createElement$1('div', { var wrapper = createElement$1('div', {
class: player.config.classNames.embedContainer, class: player.config.classNames.embedContainer,
'data-poster': poster 'data-poster': player.poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); player.media = replaceElement(wrapper, player.media);
} // Get poster image } // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { if (!config.customControls) {
if (is$2.empty(response)) { fetch(format(player.config.urls.vimeo.api, src)).then(function (response) {
return; if (is$2.empty(response) || !response.thumbnail_url) {
} // Get the URL for thumbnail return;
} // Set and show poster
var url = new URL(response[0].thumbnail_large); // Get original image ui.setPoster.call(player, response.thumbnail_url).catch(function () {});
});
url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster } // Setup instance
ui.setPoster.call(player, url.href).catch(function () {});
}); // Setup instance
// https://github.com/vimeo/player.js // https://github.com/vimeo/player.js
player.embed = new window.Vimeo.Player(iframe, { player.embed = new window.Vimeo.Player(iframe, {
autopause: player.config.autopause, autopause: player.config.autopause,
muted: player.muted muted: player.muted
@@ -26090,9 +26151,11 @@ typeof navigator === "object" && (function () {
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}); // Rebuild UI }); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 0); return ui.build.call(player);
}, 0);
}
} }
}; };
@@ -26183,7 +26246,8 @@ typeof navigator === "object" && (function () {
}, },
// API ready // API ready
ready: function ready() { ready: function ready() {
var player = this; // Ignore already setup (race condition) var player = this;
var config = player.config.youtube; // Ignore already setup (race condition)
var currentId = player.media && player.media.getAttribute('id'); var currentId = player.media && player.media.getAttribute('id');
@@ -26200,53 +26264,53 @@ typeof navigator === "object" && (function () {
var videoId = parseId$1(source); var videoId = parseId$1(source);
var id = generateId(player.provider); // Get poster, if already set var id = generateId(player.provider); // Replace media element
var poster = player.poster; // Replace media element
var container = createElement$1('div', { var container = createElement$1('div', {
id: id, id: id,
'data-poster': poster 'data-poster': config.customControls ? player.poster : undefined
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Only load the poster when using custom controls
var posterSrc = function posterSrc(s) { if (config.customControls) {
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg"); var posterSrc = function posterSrc(s) {
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
.catch(function () { .catch(function () {
return loadImage(posterSrc('sd'), 121); return loadImage(posterSrc('sd'), 121);
}) // 480p padded 4:3 }) // 480p padded 4:3
.catch(function () { .catch(function () {
return loadImage(posterSrc('hq')); return loadImage(posterSrc('hq'));
}) // 360p padded 4:3. Always exists }) // 360p padded 4:3. Always exists
.then(function (image) { .then(function (image) {
return ui.setPoster.call(player, image.src); return ui.setPoster.call(player, image.src);
}).then(function (src) { }).then(function (src) {
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters) // If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
if (!src.includes('maxres')) { if (!src.includes('maxres')) {
player.elements.poster.style.backgroundSize = 'cover'; player.elements.poster.style.backgroundSize = 'cover';
} }
}).catch(function () {}); }).catch(function () {});
var config = player.config.youtube; // Setup instance } // Setup instance
// https://developers.google.com/youtube/iframe_api_reference // https://developers.google.com/youtube/iframe_api_reference
player.embed = new window.YT.Player(id, {
player.embed = new window.YT.Player(player.media, {
videoId: videoId, videoId: videoId,
host: getHost$2(config), host: getHost$2(config),
playerVars: extend$1({}, { playerVars: extend$1({}, {
autoplay: player.config.autoplay ? 1 : 0,
// Autoplay // Autoplay
hl: player.config.hl, autoplay: player.config.autoplay ? 1 : 0,
// iframe interface language // iframe interface language
controls: player.supported.ui ? 0 : 1, hl: player.config.hl,
// Only show controls if not fully supported // Only show controls if not fully supported or opted out
disablekb: 1, controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it // Disable keyboard as we handle it
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, disablekb: 1,
// Allow iOS inline playback // Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube // Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0, cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language, cc_lang_pref: player.config.captions.language,
@@ -26357,6 +26421,7 @@ typeof navigator === "object" && (function () {
var toggle = is$2.boolean(input) ? input : muted; var toggle = is$2.boolean(input) ? input : muted;
muted = toggle; muted = toggle;
instance[toggle ? 'mute' : 'unMute'](); instance[toggle ? 'mute' : 'unMute']();
instance.setVolume(volume * 100);
triggerEvent.call(player, player.media, 'volumechange'); triggerEvent.call(player, player.media, 'volumechange');
} }
}); // Source }); // Source
@@ -26379,7 +26444,7 @@ typeof navigator === "object" && (function () {
return player.config.speed.options.includes(s); return player.config.speed.options.includes(s);
}); // Set the tabindex to avoid focus entering iframe }); // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) { if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1); player.media.setAttribute('tabindex', -1);
} }
@@ -26406,9 +26471,11 @@ typeof navigator === "object" && (function () {
} }
}, 200); // Rebuild UI }, 200); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 50); return ui.build.call(player);
}, 50);
}
}, },
onStateChange: function onStateChange(event) { onStateChange: function onStateChange(event) {
// Get the instance // Get the instance
@@ -26454,7 +26521,7 @@ typeof navigator === "object" && (function () {
case 1: case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause(); player.media.pause();
} else { } else {
assurePlaybackState$1.call(player, true); assurePlaybackState$1.call(player, true);
@@ -26527,7 +26594,8 @@ typeof navigator === "object" && (function () {
wrap$4(this.media, this.elements.wrapper); // Poster image container wrap$4(this.media, this.elements.wrapper); // Poster image container
this.elements.poster = createElement$1('div', { this.elements.poster = createElement$1('div', {
class: this.config.classNames.poster class: this.config.classNames.poster,
hidden: ''
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
@@ -28395,9 +28463,9 @@ typeof navigator === "object" && (function () {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { this.once('canplay', function () {
return silencePromise(_this.play()); return silencePromise(_this.play());
}, 10); });
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -28686,7 +28754,9 @@ typeof navigator === "object" && (function () {
} }
} else { } else {
// Unbind listeners // Unbind listeners
unbindListeners.call(_this3); // Replace the container with the original element provided unbindListeners.call(_this3); // Cancel current network requests
html5.cancelRequests.call(_this3); // Replace the container with the original element provided
replaceElement(_this3.elements.original, _this3.elements.container); // Event replaceElement(_this3.elements.original, _this3.elements.container); // Event
+3 -3
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -5,10 +5,10 @@
"homepage": "https://plyr.io", "homepage": "https://plyr.io",
"author": "Sam Potts <sam@potts.es>", "author": "Sam Potts <sam@potts.es>",
"dependencies": { "dependencies": {
"@sentry/browser": "^5.15.5", "@sentry/browser": "^5.22.3",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"custom-event-polyfill": "^1.0.7", "custom-event-polyfill": "^1.0.7",
"shr-buttons": "2.0.3", "shr-buttons": "2.0.3",
"url-polyfill": "^1.1.8" "url-polyfill": "^1.1.10"
} }
} }
+5 -5
View File
@@ -22,7 +22,7 @@ import toggleClass from './toggle-class';
if (window.location.host === production) { if (window.location.host === production) {
Sentry.init({ Sentry.init({
dsn: 'https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555', dsn: 'https://d4ad9866ad834437a4754e23937071e4@sentry.io/305555',
whitelistUrls: [production].map(d => new RegExp(`https://(([a-z0-9])+(.))*${d}`)), whitelistUrls: [production].map((d) => new RegExp(`https://(([a-z0-9])+(.))*${d}`)),
}); });
} }
@@ -79,13 +79,13 @@ import toggleClass from './toggle-class';
function render(type) { function render(type) {
// Remove active classes // Remove active classes
Array.from(buttons).forEach(button => toggleClass(button.parentElement, 'active', false)); Array.from(buttons).forEach((button) => toggleClass(button.parentElement, 'active', false));
// Set active on parent // Set active on parent
toggleClass(document.querySelector(`[data-source="${type}"]`), 'active', true); toggleClass(document.querySelector(`[data-source="${type}"]`), 'active', true);
// Show cite // Show cite
Array.from(document.querySelectorAll('.plyr__cite')).forEach(cite => { Array.from(document.querySelectorAll('.plyr__cite')).forEach((cite) => {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
cite.hidden = true; cite.hidden = true;
}); });
@@ -110,7 +110,7 @@ import toggleClass from './toggle-class';
} }
// Bind to each button // Bind to each button
Array.from(buttons).forEach(button => { Array.from(buttons).forEach((button) => {
button.addEventListener('click', () => { button.addEventListener('click', () => {
const type = button.getAttribute('data-source'); const type = button.getAttribute('data-source');
@@ -123,7 +123,7 @@ import toggleClass from './toggle-class';
}); });
// List for backwards/forwards // List for backwards/forwards
window.addEventListener('popstate', event => { window.addEventListener('popstate', (event) => {
if (event.state && Object.keys(event.state).includes('type')) { if (event.state && Object.keys(event.state).includes('type')) {
setSource(event.state.type); setSource(event.state.type);
} }
+2 -2
View File
@@ -3,7 +3,7 @@ const container = document.getElementById('container');
const tabClassName = 'tab-focus'; const tabClassName = 'tab-focus';
// Remove class on blur // Remove class on blur
document.addEventListener('focusout', event => { document.addEventListener('focusout', (event) => {
if (!event.target.classList || container.contains(event.target)) { if (!event.target.classList || container.contains(event.target)) {
return; return;
} }
@@ -12,7 +12,7 @@ document.addEventListener('focusout', event => {
}); });
// Add classname to tabbed elements // Add classname to tabbed elements
document.addEventListener('keydown', event => { document.addEventListener('keydown', (event) => {
if (event.keyCode !== 9) { if (event.keyCode !== 9) {
return; return;
} }
+1 -1
View File
@@ -4,7 +4,7 @@
// Example players // Example players
.plyr { .plyr {
border-radius: $border-radius-base; border-radius: $border-radius-large;
box-shadow: 0 2px 15px rgba(#000, 0.1); box-shadow: 0 2px 15px rgba(#000, 0.1);
margin: $spacing-base auto; margin: $spacing-base auto;
+1
View File
@@ -7,6 +7,7 @@ $arrow-size: 5px;
// Radii // Radii
$border-radius-base: 4px; $border-radius-base: 4px;
$border-radius-large: 8px;
// Background // Background
$page-background: linear-gradient(to left top, $color-background-from, $color-background-to); $page-background: linear-gradient(to left top, $color-background-from, $color-background-to);
+40 -40
View File
@@ -2,56 +2,56 @@
# yarn lockfile v1 # yarn lockfile v1
"@sentry/browser@^5.15.5": "@sentry/browser@^5.22.3":
version "5.15.5" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.15.5.tgz#d9a51f1388581067b50d30ed9b1aed2cbb333a36" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.22.3.tgz#7a64bd1cf01bf393741a3e4bf35f82aa927f5b4e"
integrity sha512-rqDvjk/EvogfdbZ4TiEpxM/lwpPKmq23z9YKEO4q81+1SwJNua53H60dOk9HpRU8nOJ1g84TMKT2Ov8H7sqDWA== integrity sha512-2TzE/CoBa5ZkvxJizDdi1Iz1ldmXSJpFQ1mL07PIXBjCt0Wxf+WOuFSj5IP4L40XHfJE5gU8wEvSH0VDR8nXtA==
dependencies: dependencies:
"@sentry/core" "5.15.5" "@sentry/core" "5.22.3"
"@sentry/types" "5.15.5" "@sentry/types" "5.22.3"
"@sentry/utils" "5.15.5" "@sentry/utils" "5.22.3"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/core@5.15.5": "@sentry/core@5.22.3":
version "5.15.5" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.15.5.tgz#40ea79bff5272d3fbbeeb4a98cdc59e1adbd2c92" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.22.3.tgz#030f435f2b518f282ba8bd954dac90cd70888bd7"
integrity sha512-enxBLv5eibBMqcWyr+vApqeix8uqkfn0iGsD3piKvoMXCgKsrfMwlb/qo9Ox0lKr71qIlZVt+9/A2vZohdgnlg== integrity sha512-eGL5uUarw3o4i9QUb9JoFHnhriPpWCaqeaIBB06HUpdcvhrjoowcKZj1+WPec5lFg5XusE35vez7z/FPzmJUDw==
dependencies: dependencies:
"@sentry/hub" "5.15.5" "@sentry/hub" "5.22.3"
"@sentry/minimal" "5.15.5" "@sentry/minimal" "5.22.3"
"@sentry/types" "5.15.5" "@sentry/types" "5.22.3"
"@sentry/utils" "5.15.5" "@sentry/utils" "5.22.3"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/hub@5.15.5": "@sentry/hub@5.22.3":
version "5.15.5" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.15.5.tgz#f5abbcdbe656a70e2ff02c02a5a4cffa0f125935" resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.22.3.tgz#08309a70d2ea8d5e313d05840c1711f34f2fffe5"
integrity sha512-zX9o49PcNIVMA4BZHe//GkbQ4Jx+nVofqU/Il32/IbwKhcpPlhGX3c1sOVQo4uag3cqd/JuQsk+DML9TKkN0Lw== integrity sha512-INo47m6N5HFEs/7GMP9cqxOIt7rmRxdERunA3H2L37owjcr77MwHVeeJ9yawRS6FMtbWXplgWTyTIWIYOuqVbw==
dependencies: dependencies:
"@sentry/types" "5.15.5" "@sentry/types" "5.22.3"
"@sentry/utils" "5.15.5" "@sentry/utils" "5.22.3"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/minimal@5.15.5": "@sentry/minimal@5.22.3":
version "5.15.5" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.15.5.tgz#a0e4e071f01d9c4d808094ae7203f6c4cca9348a" resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.22.3.tgz#706e4029ae5494123d3875c658ba8911aa5cc440"
integrity sha512-zQkkJ1l9AjmU/Us5IrOTzu7bic4sTPKCatptXvLSTfyKW7N6K9MPIIFeSpZf9o1yM2sRYdK7GV08wS2eCT3JYw== integrity sha512-HoINpYnVYCpNjn2XIPIlqH5o4BAITpTljXjtAftOx6Hzj+Opjg8tR8PWliyKDvkXPpc4kXK9D6TpEDw8MO0wZA==
dependencies: dependencies:
"@sentry/hub" "5.15.5" "@sentry/hub" "5.22.3"
"@sentry/types" "5.15.5" "@sentry/types" "5.22.3"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/types@5.15.5": "@sentry/types@5.22.3":
version "5.15.5" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.15.5.tgz#16c97e464cf09bbd1d2e8ce90d130e781709076e" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.22.3.tgz#d1d547b30ee8bd7771fa893af74c4f3d71f0fd18"
integrity sha512-F9A5W7ucgQLJUG4LXw1ZIy4iLevrYZzbeZ7GJ09aMlmXH9PqGThm1t5LSZlVpZvUfQ2rYA8NU6BdKJSt7B5LPw== integrity sha512-cv+VWK0YFgCVDvD1/HrrBWOWYG3MLuCUJRBTkV/Opdy7nkdNjhCAJQrEyMM9zX0sac8FKWKOHT0sykNh8KgmYw==
"@sentry/utils@5.15.5": "@sentry/utils@5.22.3":
version "5.15.5" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.15.5.tgz#dec1d4c79037c4da08b386f5d34409234dcbfb15" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.22.3.tgz#e3bda3e789239eb16d436f768daa12829f33d18f"
integrity sha512-Nl9gl/MGnzSkuKeo3QaefoD/OJrFLB8HmwQ7HUbTXb6E7yyEzNKAQMHXGkwNAjbdYyYbd42iABP6Y5F/h39NtA== integrity sha512-AHNryXMBvIkIE+GQxTlmhBXD0Ksh+5w1SwM5qi6AttH+1qjWLvV6WB4+4pvVvEoS8t5F+WaVUZPQLmCCWp6zKw==
dependencies: dependencies:
"@sentry/types" "5.15.5" "@sentry/types" "5.22.3"
tslib "^1.9.3" tslib "^1.9.3"
core-js@^3.6.5: core-js@^3.6.5:
@@ -74,7 +74,7 @@ tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
url-polyfill@^1.1.8: url-polyfill@^1.1.10:
version "1.1.8" version "1.1.10"
resolved "https://registry.yarnpkg.com/url-polyfill/-/url-polyfill-1.1.8.tgz#21eb58ad61192f52b77dcac8ab5293ae7bc67060" resolved "https://registry.yarnpkg.com/url-polyfill/-/url-polyfill-1.1.10.tgz#fd5bbcf66c9491fa682b0cb6d6a855e1643a9281"
integrity sha512-Ey61F4FEqhcu1vHSOMmjl0Vd/RPRLEjMj402qszD/dhMBrVfoUsnIj8KSZo2yj+eIlxJGKFdnm6ES+7UzMgZ3Q== integrity sha512-vSaPpaRgBrf41+Uky1myiSh6gpcbw8FpwHYnEy0abxndojOBnIs+yh/49gKYFLtUMP9qoNWjn6j9aUVy23Ie2A==
+1 -1
View File
File diff suppressed because one or more lines are too long
+111 -78
View File
@@ -1,7 +1,7 @@
typeof navigator === "object" && (function (global, factory) { typeof navigator === "object" && (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define('Plyr', factory) : typeof define === 'function' && define.amd ? define('Plyr', factory) :
(global = global || self, global.Plyr = factory()); (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Plyr = factory());
}(this, (function () { 'use strict'; }(this, (function () { 'use strict';
function _classCallCheck(instance, Constructor) { function _classCallCheck(instance, Constructor) {
@@ -1197,7 +1197,12 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10); var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
if (this.fullscreen.active) {
wrapper.style.paddingBottom = null;
} else {
this.media.style.transform = "translateY(-".concat(offset, "%)");
}
} else if (this.isHTML5) { } else if (this.isHTML5) {
wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
} }
@@ -3654,7 +3659,7 @@ typeof navigator === "object" && (function (global, factory) {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.6.2/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.6.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
// Quality default // Quality default
@@ -3772,7 +3777,7 @@ typeof navigator === "object" && (function (global, factory) {
vimeo: { vimeo: {
sdk: 'https://player.vimeo.com/api/player.js', sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}', iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json' api: 'https://vimeo.com/api/oembed.json?url={0}'
}, },
youtube: { youtube: {
sdk: 'https://www.youtube.com/iframe_api', sdk: 'https://www.youtube.com/iframe_api',
@@ -3942,24 +3947,27 @@ typeof navigator === "object" && (function (global, factory) {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// Custom settings from Plyr
customControls: true,
referrerPolicy: null,
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account // Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc) // (which allows us to properly hide controls without CSS hacks, etc)
premium: false, premium: false
// Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: true,
// Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
showinfo: 0, showinfo: 0,
// Hide info // Hide info
iv_load_policy: 3, iv_load_policy: 3,
// Hide annotations // Hide annotations
modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) modestbranding: 1,
// Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: true,
noCookie: false // Whether to use an alternative version of YouTube without cookies
} }
}; };
@@ -4078,7 +4086,7 @@ typeof navigator === "object" && (function (global, factory) {
return; return;
} }
_this.toggle(); _this.player.listeners.proxy(event, _this.toggle, 'fullscreen');
}); // Tap focus when in fullscreen }); // Tap focus when in fullscreen
on.call(this, this.player.elements.container, 'keydown', function (event) { on.call(this, this.player.elements.container, 'keydown', function (event) {
@@ -4101,10 +4109,12 @@ typeof navigator === "object" && (function (global, factory) {
if (is$1.element(button)) { if (is$1.element(button)) {
button.pressed = this.active; button.pressed = this.active;
} // Trigger an event } // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up
triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); var target = this.target === this.player.media ? this.target : this.player.elements.container; // Trigger an event
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
} }
}, { }, {
key: "toggleFallback", key: "toggleFallback",
@@ -4486,7 +4496,9 @@ typeof navigator === "object" && (function (global, factory) {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('data-poster', poster); // Wait until ui is ready this.media.setAttribute('data-poster', poster); // Show the poster
this.elements.poster.removeAttribute('hidden'); // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@@ -4570,7 +4582,7 @@ typeof navigator === "object" && (function (global, factory) {
// Loop through values (as they are the keys when the object is spread 🤔) // Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) { .filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr'); return !is$1.empty(key) && is$1.string(key) && key.startsWith('--plyr');
}).forEach(function (key) { }).forEach(function (key) {
// Set on the container // Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element _this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
@@ -4918,7 +4930,14 @@ typeof navigator === "object" && (function (global, factory) {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // Horrible hack for Safari 14 not repainting properly on entering fullscreen
if (isEnter) {
setTimeout(function () {
return repaint(elements.container);
}, 100);
} // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@@ -5109,9 +5128,17 @@ typeof navigator === "object" && (function (global, factory) {
this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind
this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind this.bind(elements.buttons.rewind, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after rewind
player.lastSeekTime = Date.now();
player.rewind();
}, 'rewind'); // Rewind
this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle this.bind(elements.buttons.fastForward, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after fast forward
player.lastSeekTime = Date.now();
player.forward();
}, 'fastForward'); // Mute toggle
this.bind(elements.buttons.mute, 'click', function () { this.bind(elements.buttons.mute, 'click', function () {
player.muted = !player.muted; player.muted = !player.muted;
@@ -5766,35 +5793,32 @@ typeof navigator === "object" && (function (global, factory) {
} // Inject the package } // Inject the package
var poster = player.poster; if (premium || !config.customControls) {
iframe.setAttribute('data-poster', player.poster);
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media); player.media = replaceElement(iframe, player.media);
} else { } else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
class: player.config.classNames.embedContainer, class: player.config.classNames.embedContainer,
'data-poster': poster 'data-poster': player.poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); player.media = replaceElement(wrapper, player.media);
} // Get poster image } // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { if (!config.customControls) {
if (is$1.empty(response)) { fetch(format(player.config.urls.vimeo.api, src)).then(function (response) {
return; if (is$1.empty(response) || !response.thumbnail_url) {
} // Get the URL for thumbnail return;
} // Set and show poster
var url = new URL(response[0].thumbnail_large); // Get original image ui.setPoster.call(player, response.thumbnail_url).catch(function () {});
});
url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster } // Setup instance
ui.setPoster.call(player, url.href).catch(function () {});
}); // Setup instance
// https://github.com/vimeo/player.js // https://github.com/vimeo/player.js
player.embed = new window.Vimeo.Player(iframe, { player.embed = new window.Vimeo.Player(iframe, {
autopause: player.config.autopause, autopause: player.config.autopause,
muted: player.muted muted: player.muted
@@ -6034,9 +6058,11 @@ typeof navigator === "object" && (function (global, factory) {
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}); // Rebuild UI }); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 0); return ui.build.call(player);
}, 0);
}
} }
}; };
@@ -6129,7 +6155,8 @@ typeof navigator === "object" && (function (global, factory) {
}, },
// API ready // API ready
ready: function ready() { ready: function ready() {
var player = this; // Ignore already setup (race condition) var player = this;
var config = player.config.youtube; // Ignore already setup (race condition)
var currentId = player.media && player.media.getAttribute('id'); var currentId = player.media && player.media.getAttribute('id');
@@ -6146,53 +6173,53 @@ typeof navigator === "object" && (function (global, factory) {
var videoId = parseId$1(source); var videoId = parseId$1(source);
var id = generateId(player.provider); // Get poster, if already set var id = generateId(player.provider); // Replace media element
var poster = player.poster; // Replace media element
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
'data-poster': poster 'data-poster': config.customControls ? player.poster : undefined
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Only load the poster when using custom controls
var posterSrc = function posterSrc(s) { if (config.customControls) {
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg"); var posterSrc = function posterSrc(s) {
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
.catch(function () { .catch(function () {
return loadImage(posterSrc('sd'), 121); return loadImage(posterSrc('sd'), 121);
}) // 480p padded 4:3 }) // 480p padded 4:3
.catch(function () { .catch(function () {
return loadImage(posterSrc('hq')); return loadImage(posterSrc('hq'));
}) // 360p padded 4:3. Always exists }) // 360p padded 4:3. Always exists
.then(function (image) { .then(function (image) {
return ui.setPoster.call(player, image.src); return ui.setPoster.call(player, image.src);
}).then(function (src) { }).then(function (src) {
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters) // If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
if (!src.includes('maxres')) { if (!src.includes('maxres')) {
player.elements.poster.style.backgroundSize = 'cover'; player.elements.poster.style.backgroundSize = 'cover';
} }
}).catch(function () {}); }).catch(function () {});
var config = player.config.youtube; // Setup instance } // Setup instance
// https://developers.google.com/youtube/iframe_api_reference // https://developers.google.com/youtube/iframe_api_reference
player.embed = new window.YT.Player(id, {
player.embed = new window.YT.Player(player.media, {
videoId: videoId, videoId: videoId,
host: getHost(config), host: getHost(config),
playerVars: extend({}, { playerVars: extend({}, {
autoplay: player.config.autoplay ? 1 : 0,
// Autoplay // Autoplay
hl: player.config.hl, autoplay: player.config.autoplay ? 1 : 0,
// iframe interface language // iframe interface language
controls: player.supported.ui ? 0 : 1, hl: player.config.hl,
// Only show controls if not fully supported // Only show controls if not fully supported or opted out
disablekb: 1, controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it // Disable keyboard as we handle it
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, disablekb: 1,
// Allow iOS inline playback // Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube // Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0, cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language, cc_lang_pref: player.config.captions.language,
@@ -6303,6 +6330,7 @@ typeof navigator === "object" && (function (global, factory) {
var toggle = is$1.boolean(input) ? input : muted; var toggle = is$1.boolean(input) ? input : muted;
muted = toggle; muted = toggle;
instance[toggle ? 'mute' : 'unMute'](); instance[toggle ? 'mute' : 'unMute']();
instance.setVolume(volume * 100);
triggerEvent.call(player, player.media, 'volumechange'); triggerEvent.call(player, player.media, 'volumechange');
} }
}); // Source }); // Source
@@ -6325,7 +6353,7 @@ typeof navigator === "object" && (function (global, factory) {
return player.config.speed.options.includes(s); return player.config.speed.options.includes(s);
}); // Set the tabindex to avoid focus entering iframe }); // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) { if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1); player.media.setAttribute('tabindex', -1);
} }
@@ -6352,9 +6380,11 @@ typeof navigator === "object" && (function (global, factory) {
} }
}, 200); // Rebuild UI }, 200); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 50); return ui.build.call(player);
}, 50);
}
}, },
onStateChange: function onStateChange(event) { onStateChange: function onStateChange(event) {
// Get the instance // Get the instance
@@ -6400,7 +6430,7 @@ typeof navigator === "object" && (function (global, factory) {
case 1: case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause(); player.media.pause();
} else { } else {
assurePlaybackState$1.call(player, true); assurePlaybackState$1.call(player, true);
@@ -6474,7 +6504,8 @@ typeof navigator === "object" && (function (global, factory) {
wrap(this.media, this.elements.wrapper); // Poster image container wrap(this.media, this.elements.wrapper); // Poster image container
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster,
hidden: ''
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
@@ -8291,9 +8322,9 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { this.once('canplay', function () {
return silencePromise(_this.play()); return silencePromise(_this.play());
}, 10); });
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -8582,7 +8613,9 @@ typeof navigator === "object" && (function (global, factory) {
} }
} else { } else {
// Unbind listeners // Unbind listeners
unbindListeners.call(_this3); // Replace the container with the original element provided unbindListeners.call(_this3); // Cancel current network requests
html5.cancelRequests.call(_this3); // Replace the container with the original element provided
replaceElement(_this3.elements.original, _this3.elements.container); // Event replaceElement(_this3.elements.original, _this3.elements.container); // Event
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+111 -78
View File
@@ -1,4 +1,4 @@
typeof navigator === "object" && function _classCallCheck(instance, Constructor) { function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) { if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function"); throw new TypeError("Cannot call a class as a function");
} }
@@ -1191,7 +1191,12 @@ function setAspectRatio(input) {
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10); var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
if (this.fullscreen.active) {
wrapper.style.paddingBottom = null;
} else {
this.media.style.transform = "translateY(-".concat(offset, "%)");
}
} else if (this.isHTML5) { } else if (this.isHTML5) {
wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
} }
@@ -3648,7 +3653,7 @@ var defaults$1 = {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.6.2/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.6.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
// Quality default // Quality default
@@ -3766,7 +3771,7 @@ var defaults$1 = {
vimeo: { vimeo: {
sdk: 'https://player.vimeo.com/api/player.js', sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}', iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json' api: 'https://vimeo.com/api/oembed.json?url={0}'
}, },
youtube: { youtube: {
sdk: 'https://www.youtube.com/iframe_api', sdk: 'https://www.youtube.com/iframe_api',
@@ -3936,24 +3941,27 @@ var defaults$1 = {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// Custom settings from Plyr
customControls: true,
referrerPolicy: null,
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account // Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc) // (which allows us to properly hide controls without CSS hacks, etc)
premium: false, premium: false
// Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: true,
// Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
showinfo: 0, showinfo: 0,
// Hide info // Hide info
iv_load_policy: 3, iv_load_policy: 3,
// Hide annotations // Hide annotations
modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) modestbranding: 1,
// Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: true,
noCookie: false // Whether to use an alternative version of YouTube without cookies
} }
}; };
@@ -4072,7 +4080,7 @@ var Fullscreen = /*#__PURE__*/function () {
return; return;
} }
_this.toggle(); _this.player.listeners.proxy(event, _this.toggle, 'fullscreen');
}); // Tap focus when in fullscreen }); // Tap focus when in fullscreen
on.call(this, this.player.elements.container, 'keydown', function (event) { on.call(this, this.player.elements.container, 'keydown', function (event) {
@@ -4095,10 +4103,12 @@ var Fullscreen = /*#__PURE__*/function () {
if (is$1.element(button)) { if (is$1.element(button)) {
button.pressed = this.active; button.pressed = this.active;
} // Trigger an event } // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up
triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); var target = this.target === this.player.media ? this.target : this.player.elements.container; // Trigger an event
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
} }
}, { }, {
key: "toggleFallback", key: "toggleFallback",
@@ -4480,7 +4490,9 @@ var ui = {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('data-poster', poster); // Wait until ui is ready this.media.setAttribute('data-poster', poster); // Show the poster
this.elements.poster.removeAttribute('hidden'); // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@@ -4564,7 +4576,7 @@ var ui = {
// Loop through values (as they are the keys when the object is spread 🤔) // Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) { .filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr'); return !is$1.empty(key) && is$1.string(key) && key.startsWith('--plyr');
}).forEach(function (key) { }).forEach(function (key) {
// Set on the container // Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element _this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
@@ -4912,7 +4924,14 @@ var Listeners = /*#__PURE__*/function () {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // Horrible hack for Safari 14 not repainting properly on entering fullscreen
if (isEnter) {
setTimeout(function () {
return repaint(elements.container);
}, 100);
} // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@@ -5103,9 +5122,17 @@ var Listeners = /*#__PURE__*/function () {
this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind
this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind this.bind(elements.buttons.rewind, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after rewind
player.lastSeekTime = Date.now();
player.rewind();
}, 'rewind'); // Rewind
this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle this.bind(elements.buttons.fastForward, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after fast forward
player.lastSeekTime = Date.now();
player.forward();
}, 'fastForward'); // Mute toggle
this.bind(elements.buttons.mute, 'click', function () { this.bind(elements.buttons.mute, 'click', function () {
player.muted = !player.muted; player.muted = !player.muted;
@@ -5760,35 +5787,32 @@ var vimeo = {
} // Inject the package } // Inject the package
var poster = player.poster; if (premium || !config.customControls) {
iframe.setAttribute('data-poster', player.poster);
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media); player.media = replaceElement(iframe, player.media);
} else { } else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
class: player.config.classNames.embedContainer, class: player.config.classNames.embedContainer,
'data-poster': poster 'data-poster': player.poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); player.media = replaceElement(wrapper, player.media);
} // Get poster image } // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { if (!config.customControls) {
if (is$1.empty(response)) { fetch(format(player.config.urls.vimeo.api, src)).then(function (response) {
return; if (is$1.empty(response) || !response.thumbnail_url) {
} // Get the URL for thumbnail return;
} // Set and show poster
var url = new URL(response[0].thumbnail_large); // Get original image ui.setPoster.call(player, response.thumbnail_url).catch(function () {});
});
url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster } // Setup instance
ui.setPoster.call(player, url.href).catch(function () {});
}); // Setup instance
// https://github.com/vimeo/player.js // https://github.com/vimeo/player.js
player.embed = new window.Vimeo.Player(iframe, { player.embed = new window.Vimeo.Player(iframe, {
autopause: player.config.autopause, autopause: player.config.autopause,
muted: player.muted muted: player.muted
@@ -6028,9 +6052,11 @@ var vimeo = {
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}); // Rebuild UI }); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 0); return ui.build.call(player);
}, 0);
}
} }
}; };
@@ -6123,7 +6149,8 @@ var youtube = {
}, },
// API ready // API ready
ready: function ready() { ready: function ready() {
var player = this; // Ignore already setup (race condition) var player = this;
var config = player.config.youtube; // Ignore already setup (race condition)
var currentId = player.media && player.media.getAttribute('id'); var currentId = player.media && player.media.getAttribute('id');
@@ -6140,53 +6167,53 @@ var youtube = {
var videoId = parseId$1(source); var videoId = parseId$1(source);
var id = generateId(player.provider); // Get poster, if already set var id = generateId(player.provider); // Replace media element
var poster = player.poster; // Replace media element
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
'data-poster': poster 'data-poster': config.customControls ? player.poster : undefined
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Only load the poster when using custom controls
var posterSrc = function posterSrc(s) { if (config.customControls) {
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg"); var posterSrc = function posterSrc(s) {
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
.catch(function () { .catch(function () {
return loadImage(posterSrc('sd'), 121); return loadImage(posterSrc('sd'), 121);
}) // 480p padded 4:3 }) // 480p padded 4:3
.catch(function () { .catch(function () {
return loadImage(posterSrc('hq')); return loadImage(posterSrc('hq'));
}) // 360p padded 4:3. Always exists }) // 360p padded 4:3. Always exists
.then(function (image) { .then(function (image) {
return ui.setPoster.call(player, image.src); return ui.setPoster.call(player, image.src);
}).then(function (src) { }).then(function (src) {
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters) // If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
if (!src.includes('maxres')) { if (!src.includes('maxres')) {
player.elements.poster.style.backgroundSize = 'cover'; player.elements.poster.style.backgroundSize = 'cover';
} }
}).catch(function () {}); }).catch(function () {});
var config = player.config.youtube; // Setup instance } // Setup instance
// https://developers.google.com/youtube/iframe_api_reference // https://developers.google.com/youtube/iframe_api_reference
player.embed = new window.YT.Player(id, {
player.embed = new window.YT.Player(player.media, {
videoId: videoId, videoId: videoId,
host: getHost(config), host: getHost(config),
playerVars: extend({}, { playerVars: extend({}, {
autoplay: player.config.autoplay ? 1 : 0,
// Autoplay // Autoplay
hl: player.config.hl, autoplay: player.config.autoplay ? 1 : 0,
// iframe interface language // iframe interface language
controls: player.supported.ui ? 0 : 1, hl: player.config.hl,
// Only show controls if not fully supported // Only show controls if not fully supported or opted out
disablekb: 1, controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it // Disable keyboard as we handle it
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, disablekb: 1,
// Allow iOS inline playback // Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube // Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0, cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language, cc_lang_pref: player.config.captions.language,
@@ -6297,6 +6324,7 @@ var youtube = {
var toggle = is$1.boolean(input) ? input : muted; var toggle = is$1.boolean(input) ? input : muted;
muted = toggle; muted = toggle;
instance[toggle ? 'mute' : 'unMute'](); instance[toggle ? 'mute' : 'unMute']();
instance.setVolume(volume * 100);
triggerEvent.call(player, player.media, 'volumechange'); triggerEvent.call(player, player.media, 'volumechange');
} }
}); // Source }); // Source
@@ -6319,7 +6347,7 @@ var youtube = {
return player.config.speed.options.includes(s); return player.config.speed.options.includes(s);
}); // Set the tabindex to avoid focus entering iframe }); // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) { if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1); player.media.setAttribute('tabindex', -1);
} }
@@ -6346,9 +6374,11 @@ var youtube = {
} }
}, 200); // Rebuild UI }, 200); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 50); return ui.build.call(player);
}, 50);
}
}, },
onStateChange: function onStateChange(event) { onStateChange: function onStateChange(event) {
// Get the instance // Get the instance
@@ -6394,7 +6424,7 @@ var youtube = {
case 1: case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause(); player.media.pause();
} else { } else {
assurePlaybackState$1.call(player, true); assurePlaybackState$1.call(player, true);
@@ -6468,7 +6498,8 @@ var media = {
wrap(this.media, this.elements.wrapper); // Poster image container wrap(this.media, this.elements.wrapper); // Poster image container
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster,
hidden: ''
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
@@ -8285,9 +8316,9 @@ var Plyr = /*#__PURE__*/function () {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { this.once('canplay', function () {
return silencePromise(_this.play()); return silencePromise(_this.play());
}, 10); });
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -8576,7 +8607,9 @@ var Plyr = /*#__PURE__*/function () {
} }
} else { } else {
// Unbind listeners // Unbind listeners
unbindListeners.call(_this3); // Replace the container with the original element provided unbindListeners.call(_this3); // Cancel current network requests
html5.cancelRequests.call(_this3); // Replace the container with the original element provided
replaceElement(_this3.elements.original, _this3.elements.container); // Event replaceElement(_this3.elements.original, _this3.elements.container); // Event
+228 -152
View File
@@ -1,7 +1,7 @@
typeof navigator === "object" && (function (global, factory) { typeof navigator === "object" && (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define('Plyr', factory) : typeof define === 'function' && define.amd ? define('Plyr', factory) :
(global = global || self, global.Plyr = factory()); (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Plyr = factory());
}(this, (function () { 'use strict'; }(this, (function () { 'use strict';
// Polyfill for creating CustomEvents on IE9/10/11 // Polyfill for creating CustomEvents on IE9/10/11
@@ -74,7 +74,7 @@ typeof navigator === "object" && (function (global, factory) {
check(typeof self == 'object' && self) || check(typeof self == 'object' && self) ||
check(typeof commonjsGlobal == 'object' && commonjsGlobal) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-new-func
Function('return this')(); (function () { return this; })() || Function('return this')();
var fails = function (exec) { var fails = function (exec) {
try { try {
@@ -269,7 +269,7 @@ typeof navigator === "object" && (function (global, factory) {
(module.exports = function (key, value) { (module.exports = function (key, value) {
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
})('versions', []).push({ })('versions', []).push({
version: '3.6.5', version: '3.7.0',
mode: 'global', mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)' copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
}); });
@@ -307,11 +307,12 @@ typeof navigator === "object" && (function (global, factory) {
}; };
if (nativeWeakMap) { if (nativeWeakMap) {
var store$1 = new WeakMap$2(); var store$1 = sharedStore.state || (sharedStore.state = new WeakMap$2());
var wmget = store$1.get; var wmget = store$1.get;
var wmhas = store$1.has; var wmhas = store$1.has;
var wmset = store$1.set; var wmset = store$1.set;
set = function (it, metadata) { set = function (it, metadata) {
metadata.facade = it;
wmset.call(store$1, it, metadata); wmset.call(store$1, it, metadata);
return metadata; return metadata;
}; };
@@ -325,6 +326,7 @@ typeof navigator === "object" && (function (global, factory) {
var STATE = sharedKey('state'); var STATE = sharedKey('state');
hiddenKeys[STATE] = true; hiddenKeys[STATE] = true;
set = function (it, metadata) { set = function (it, metadata) {
metadata.facade = it;
createNonEnumerableProperty(it, STATE, metadata); createNonEnumerableProperty(it, STATE, metadata);
return metadata; return metadata;
}; };
@@ -353,9 +355,15 @@ typeof navigator === "object" && (function (global, factory) {
var unsafe = options ? !!options.unsafe : false; var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false; var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false; var noTargetGet = options ? !!options.noTargetGet : false;
var state;
if (typeof value == 'function') { if (typeof value == 'function') {
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key); if (typeof key == 'string' && !has(value, 'name')) {
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : ''); createNonEnumerableProperty(value, 'name', key);
}
state = enforceInternalState(value);
if (!state.source) {
state.source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
} }
if (O === global_1) { if (O === global_1) {
if (simple) O[key] = value; if (simple) O[key] = value;
@@ -2441,14 +2449,20 @@ typeof navigator === "object" && (function (global, factory) {
} return T; } return T;
} : nativeAssign; } : nativeAssign;
var iteratorClose = function (iterator) {
var returnMethod = iterator['return'];
if (returnMethod !== undefined) {
return anObject(returnMethod.call(iterator)).value;
}
};
// call something on iterator step with safe closing on error // call something on iterator step with safe closing on error
var callWithSafeIterationClosing = function (iterator, fn, value, ENTRIES) { var callWithSafeIterationClosing = function (iterator, fn, value, ENTRIES) {
try { try {
return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value); return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
// 7.4.6 IteratorClose(iterator, completion) // 7.4.6 IteratorClose(iterator, completion)
} catch (error) { } catch (error) {
var returnMethod = iterator['return']; iteratorClose(iterator);
if (returnMethod !== undefined) anObject(returnMethod.call(iterator));
throw error; throw error;
} }
}; };
@@ -2845,7 +2859,7 @@ typeof navigator === "object" && (function (global, factory) {
var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype; var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
redefineAll(URLSearchParamsPrototype, { redefineAll(URLSearchParamsPrototype, {
// `URLSearchParams.prototype.appent` method // `URLSearchParams.prototype.append` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-append // https://url.spec.whatwg.org/#dom-urlsearchparams-append
append: function append(name, value) { append: function append(name, value) {
validateArgumentsLength(arguments.length, 2); validateArgumentsLength(arguments.length, 2);
@@ -4408,7 +4422,7 @@ typeof navigator === "object" && (function (global, factory) {
var checkIfURLSearchParamsSupported = function checkIfURLSearchParamsSupported() { var checkIfURLSearchParamsSupported = function checkIfURLSearchParamsSupported() {
try { try {
var URLSearchParams = global.URLSearchParams; var URLSearchParams = global.URLSearchParams;
return new URLSearchParams('?a=1').toString() === 'a=1' && typeof URLSearchParams.prototype.set === 'function'; return new URLSearchParams('?a=1').toString() === 'a=1' && typeof URLSearchParams.prototype.set === 'function' && typeof URLSearchParams.prototype.entries === 'function';
} catch (e) { } catch (e) {
return false; return false;
} }
@@ -4506,12 +4520,14 @@ typeof navigator === "object" && (function (global, factory) {
var _URL = global.URL; var _URL = global.URL;
var URL = function URL(url, base) { var URL = function URL(url, base) {
if (typeof url !== 'string') url = String(url); // Only create another document if the base is different from current location. if (typeof url !== 'string') url = String(url);
if (base && typeof base !== 'string') base = String(base); // Only create another document if the base is different from current location.
var doc = document, var doc = document,
baseElement; baseElement;
if (base && (global.location === void 0 || base !== global.location.href)) { if (base && (global.location === void 0 || base !== global.location.href)) {
base = base.toLowerCase();
doc = document.implementation.createHTMLDocument(''); doc = document.implementation.createHTMLDocument('');
baseElement = doc.createElement('base'); baseElement = doc.createElement('base');
baseElement.href = base; baseElement.href = base;
@@ -4532,7 +4548,11 @@ typeof navigator === "object" && (function (global, factory) {
anchorElement.href = anchorElement.href; // force href to refresh anchorElement.href = anchorElement.href; // force href to refresh
} }
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) { var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href) || !inputElement.checkValidity() && !base) {
throw new TypeError('Invalid URL'); throw new TypeError('Invalid URL');
} }
@@ -5013,11 +5033,11 @@ typeof navigator === "object" && (function (global, factory) {
var regexp = /./; var regexp = /./;
try { try {
'/./'[METHOD_NAME](regexp); '/./'[METHOD_NAME](regexp);
} catch (e) { } catch (error1) {
try { try {
regexp[MATCH$1] = false; regexp[MATCH$1] = false;
return '/./'[METHOD_NAME](regexp); return '/./'[METHOD_NAME](regexp);
} catch (f) { /* empty */ } } catch (error2) { /* empty */ }
} return false; } return false;
}; };
@@ -5099,16 +5119,31 @@ typeof navigator === "object" && (function (global, factory) {
var internalMetadata_3 = internalMetadata.getWeakData; var internalMetadata_3 = internalMetadata.getWeakData;
var internalMetadata_4 = internalMetadata.onFreeze; var internalMetadata_4 = internalMetadata.onFreeze;
var iterate_1 = createCommonjsModule(function (module) {
var Result = function (stopped, result) { var Result = function (stopped, result) {
this.stopped = stopped; this.stopped = stopped;
this.result = result; this.result = result;
}; };
var iterate = module.exports = function (iterable, fn, that, AS_ENTRIES, IS_ITERATOR) { var iterate = function (iterable, unboundFunction, options) {
var boundFunction = functionBindContext(fn, that, AS_ENTRIES ? 2 : 1); var that = options && options.that;
var AS_ENTRIES = !!(options && options.AS_ENTRIES);
var IS_ITERATOR = !!(options && options.IS_ITERATOR);
var INTERRUPTED = !!(options && options.INTERRUPTED);
var fn = functionBindContext(unboundFunction, that, 1 + AS_ENTRIES + INTERRUPTED);
var iterator, iterFn, index, length, result, next, step; var iterator, iterFn, index, length, result, next, step;
var stop = function (condition) {
if (iterator) iteratorClose(iterator);
return new Result(true, condition);
};
var callFn = function (value) {
if (AS_ENTRIES) {
anObject(value);
return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
} return INTERRUPTED ? fn(value, stop) : fn(value);
};
if (IS_ITERATOR) { if (IS_ITERATOR) {
iterator = iterable; iterator = iterable;
} else { } else {
@@ -5117,9 +5152,7 @@ typeof navigator === "object" && (function (global, factory) {
// optimisation for array iterators // optimisation for array iterators
if (isArrayIteratorMethod(iterFn)) { if (isArrayIteratorMethod(iterFn)) {
for (index = 0, length = toLength(iterable.length); length > index; index++) { for (index = 0, length = toLength(iterable.length); length > index; index++) {
result = AS_ENTRIES result = callFn(iterable[index]);
? boundFunction(anObject(step = iterable[index])[0], step[1])
: boundFunction(iterable[index]);
if (result && result instanceof Result) return result; if (result && result instanceof Result) return result;
} return new Result(false); } return new Result(false);
} }
@@ -5128,16 +5161,16 @@ typeof navigator === "object" && (function (global, factory) {
next = iterator.next; next = iterator.next;
while (!(step = next.call(iterator)).done) { while (!(step = next.call(iterator)).done) {
result = callWithSafeIterationClosing(iterator, boundFunction, step.value, AS_ENTRIES); try {
result = callFn(step.value);
} catch (error) {
iteratorClose(iterator);
throw error;
}
if (typeof result == 'object' && result && result instanceof Result) return result; if (typeof result == 'object' && result && result instanceof Result) return result;
} return new Result(false); } return new Result(false);
}; };
iterate.stop = function (result) {
return new Result(true, result);
};
});
var collection = function (CONSTRUCTOR_NAME, wrapper, common) { var collection = function (CONSTRUCTOR_NAME, wrapper, common) {
var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1; var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1; var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
@@ -5195,7 +5228,7 @@ typeof navigator === "object" && (function (global, factory) {
Constructor = wrapper(function (dummy, iterable) { Constructor = wrapper(function (dummy, iterable) {
anInstance(dummy, Constructor, CONSTRUCTOR_NAME); anInstance(dummy, Constructor, CONSTRUCTOR_NAME);
var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor); var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
if (iterable != undefined) iterate_1(iterable, that[ADDER], that, IS_MAP); if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
return that; return that;
}); });
Constructor.prototype = NativePrototype; Constructor.prototype = NativePrototype;
@@ -5285,7 +5318,7 @@ typeof navigator === "object" && (function (global, factory) {
id: id$1++, id: id$1++,
frozen: undefined frozen: undefined
}); });
if (iterable != undefined) iterate_1(iterable, that[ADDER], that, IS_MAP); if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
}); });
var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME); var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
@@ -5974,6 +6007,8 @@ typeof navigator === "object" && (function (global, factory) {
var engineIsIos = /(iphone|ipod|ipad).*applewebkit/i.test(engineUserAgent); var engineIsIos = /(iphone|ipod|ipad).*applewebkit/i.test(engineUserAgent);
var engineIsNode = classofRaw(global_1.process) == 'process';
var location = global_1.location; var location = global_1.location;
var set$1 = global_1.setImmediate; var set$1 = global_1.setImmediate;
var clear = global_1.clearImmediate; var clear = global_1.clearImmediate;
@@ -6026,7 +6061,7 @@ typeof navigator === "object" && (function (global, factory) {
delete queue[id]; delete queue[id];
}; };
// Node.js 0.8- // Node.js 0.8-
if (classofRaw(process$1) == 'process') { if (engineIsNode) {
defer = function (id) { defer = function (id) {
process$1.nextTick(runner(id)); process$1.nextTick(runner(id));
}; };
@@ -6048,8 +6083,8 @@ typeof navigator === "object" && (function (global, factory) {
global_1.addEventListener && global_1.addEventListener &&
typeof postMessage == 'function' && typeof postMessage == 'function' &&
!global_1.importScripts && !global_1.importScripts &&
!fails(post) && location && location.protocol !== 'file:' &&
location.protocol !== 'file:' !fails(post)
) { ) {
defer = post; defer = post;
global_1.addEventListener('message', listener, false); global_1.addEventListener('message', listener, false);
@@ -6075,14 +6110,14 @@ typeof navigator === "object" && (function (global, factory) {
}; };
var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f; var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f;
var macrotask = task.set; var macrotask = task.set;
var MutationObserver$1 = global_1.MutationObserver || global_1.WebKitMutationObserver; var MutationObserver$1 = global_1.MutationObserver || global_1.WebKitMutationObserver;
var document$2 = global_1.document;
var process$2 = global_1.process; var process$2 = global_1.process;
var Promise$1 = global_1.Promise; var Promise$1 = global_1.Promise;
var IS_NODE = classofRaw(process$2) == 'process';
// Node.js 11 shows ExperimentalWarning on getting `queueMicrotask` // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global_1, 'queueMicrotask'); var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global_1, 'queueMicrotask');
var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value; var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
@@ -6093,7 +6128,7 @@ typeof navigator === "object" && (function (global, factory) {
if (!queueMicrotask) { if (!queueMicrotask) {
flush = function () { flush = function () {
var parent, fn; var parent, fn;
if (IS_NODE && (parent = process$2.domain)) parent.exit(); if (engineIsNode && (parent = process$2.domain)) parent.exit();
while (head) { while (head) {
fn = head.fn; fn = head.fn;
head = head.next; head = head.next;
@@ -6108,15 +6143,10 @@ typeof navigator === "object" && (function (global, factory) {
if (parent) parent.enter(); if (parent) parent.enter();
}; };
// Node.js
if (IS_NODE) {
notify = function () {
process$2.nextTick(flush);
};
// browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339 // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
} else if (MutationObserver$1 && !engineIsIos) { if (!engineIsIos && !engineIsNode && MutationObserver$1 && document$2) {
toggle = true; toggle = true;
node = document.createTextNode(''); node = document$2.createTextNode('');
new MutationObserver$1(flush).observe(node, { characterData: true }); new MutationObserver$1(flush).observe(node, { characterData: true });
notify = function () { notify = function () {
node.data = toggle = !toggle; node.data = toggle = !toggle;
@@ -6129,6 +6159,11 @@ typeof navigator === "object" && (function (global, factory) {
notify = function () { notify = function () {
then.call(promise, flush); then.call(promise, flush);
}; };
// Node.js without promises
} else if (engineIsNode) {
notify = function () {
process$2.nextTick(flush);
};
// for other environments - macrotask based on: // for other environments - macrotask based on:
// - setImmediate // - setImmediate
// - MessageChannel // - MessageChannel
@@ -6207,6 +6242,7 @@ typeof navigator === "object" && (function (global, factory) {
var SPECIES$6 = wellKnownSymbol('species'); var SPECIES$6 = wellKnownSymbol('species');
var PROMISE = 'Promise'; var PROMISE = 'Promise';
var getInternalState$3 = internalState.get; var getInternalState$3 = internalState.get;
@@ -6214,13 +6250,13 @@ typeof navigator === "object" && (function (global, factory) {
var getInternalPromiseState = internalState.getterFor(PROMISE); var getInternalPromiseState = internalState.getterFor(PROMISE);
var PromiseConstructor = nativePromiseConstructor; var PromiseConstructor = nativePromiseConstructor;
var TypeError$1 = global_1.TypeError; var TypeError$1 = global_1.TypeError;
var document$2 = global_1.document; var document$3 = global_1.document;
var process$3 = global_1.process; var process$3 = global_1.process;
var $fetch$1 = getBuiltIn('fetch'); var $fetch$1 = getBuiltIn('fetch');
var newPromiseCapability$1 = newPromiseCapability.f; var newPromiseCapability$1 = newPromiseCapability.f;
var newGenericPromiseCapability = newPromiseCapability$1; var newGenericPromiseCapability = newPromiseCapability$1;
var IS_NODE$1 = classofRaw(process$3) == 'process'; var DISPATCH_EVENT = !!(document$3 && document$3.createEvent && global_1.dispatchEvent);
var DISPATCH_EVENT = !!(document$2 && document$2.createEvent && global_1.dispatchEvent); var NATIVE_REJECTION_EVENT = typeof PromiseRejectionEvent == 'function';
var UNHANDLED_REJECTION = 'unhandledrejection'; var UNHANDLED_REJECTION = 'unhandledrejection';
var REJECTION_HANDLED = 'rejectionhandled'; var REJECTION_HANDLED = 'rejectionhandled';
var PENDING = 0; var PENDING = 0;
@@ -6238,7 +6274,7 @@ typeof navigator === "object" && (function (global, factory) {
// We can't detect it synchronously, so just check versions // We can't detect it synchronously, so just check versions
if (engineV8Version === 66) return true; if (engineV8Version === 66) return true;
// Unhandled rejections tracking support, NodeJS Promise without it fails @@species test // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
if (!IS_NODE$1 && typeof PromiseRejectionEvent != 'function') return true; if (!engineIsNode && !NATIVE_REJECTION_EVENT) return true;
} }
// We can't use @@species feature detection in V8 since it causes // We can't use @@species feature detection in V8 since it causes
// deoptimization and performance degradation // deoptimization and performance degradation
@@ -6264,7 +6300,7 @@ typeof navigator === "object" && (function (global, factory) {
return isObject(it) && typeof (then = it.then) == 'function' ? then : false; return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
}; };
var notify$1 = function (promise, state, isReject) { var notify$1 = function (state, isReject) {
if (state.notified) return; if (state.notified) return;
state.notified = true; state.notified = true;
var chain = state.reactions; var chain = state.reactions;
@@ -6283,7 +6319,7 @@ typeof navigator === "object" && (function (global, factory) {
try { try {
if (handler) { if (handler) {
if (!ok) { if (!ok) {
if (state.rejection === UNHANDLED) onHandleUnhandled(promise, state); if (state.rejection === UNHANDLED) onHandleUnhandled(state);
state.rejection = HANDLED; state.rejection = HANDLED;
} }
if (handler === true) result = value; if (handler === true) result = value;
@@ -6308,36 +6344,37 @@ typeof navigator === "object" && (function (global, factory) {
} }
state.reactions = []; state.reactions = [];
state.notified = false; state.notified = false;
if (isReject && !state.rejection) onUnhandled(promise, state); if (isReject && !state.rejection) onUnhandled(state);
}); });
}; };
var dispatchEvent = function (name, promise, reason) { var dispatchEvent = function (name, promise, reason) {
var event, handler; var event, handler;
if (DISPATCH_EVENT) { if (DISPATCH_EVENT) {
event = document$2.createEvent('Event'); event = document$3.createEvent('Event');
event.promise = promise; event.promise = promise;
event.reason = reason; event.reason = reason;
event.initEvent(name, false, true); event.initEvent(name, false, true);
global_1.dispatchEvent(event); global_1.dispatchEvent(event);
} else event = { promise: promise, reason: reason }; } else event = { promise: promise, reason: reason };
if (handler = global_1['on' + name]) handler(event); if (!NATIVE_REJECTION_EVENT && (handler = global_1['on' + name])) handler(event);
else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason); else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
}; };
var onUnhandled = function (promise, state) { var onUnhandled = function (state) {
task$1.call(global_1, function () { task$1.call(global_1, function () {
var promise = state.facade;
var value = state.value; var value = state.value;
var IS_UNHANDLED = isUnhandled(state); var IS_UNHANDLED = isUnhandled(state);
var result; var result;
if (IS_UNHANDLED) { if (IS_UNHANDLED) {
result = perform(function () { result = perform(function () {
if (IS_NODE$1) { if (engineIsNode) {
process$3.emit('unhandledRejection', value, promise); process$3.emit('unhandledRejection', value, promise);
} else dispatchEvent(UNHANDLED_REJECTION, promise, value); } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
}); });
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
state.rejection = IS_NODE$1 || isUnhandled(state) ? UNHANDLED : HANDLED; state.rejection = engineIsNode || isUnhandled(state) ? UNHANDLED : HANDLED;
if (result.error) throw result.value; if (result.error) throw result.value;
} }
}); });
@@ -6347,55 +6384,56 @@ typeof navigator === "object" && (function (global, factory) {
return state.rejection !== HANDLED && !state.parent; return state.rejection !== HANDLED && !state.parent;
}; };
var onHandleUnhandled = function (promise, state) { var onHandleUnhandled = function (state) {
task$1.call(global_1, function () { task$1.call(global_1, function () {
if (IS_NODE$1) { var promise = state.facade;
if (engineIsNode) {
process$3.emit('rejectionHandled', promise); process$3.emit('rejectionHandled', promise);
} else dispatchEvent(REJECTION_HANDLED, promise, state.value); } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
}); });
}; };
var bind = function (fn, promise, state, unwrap) { var bind = function (fn, state, unwrap) {
return function (value) { return function (value) {
fn(promise, state, value, unwrap); fn(state, value, unwrap);
}; };
}; };
var internalReject = function (promise, state, value, unwrap) { var internalReject = function (state, value, unwrap) {
if (state.done) return; if (state.done) return;
state.done = true; state.done = true;
if (unwrap) state = unwrap; if (unwrap) state = unwrap;
state.value = value; state.value = value;
state.state = REJECTED; state.state = REJECTED;
notify$1(promise, state, true); notify$1(state, true);
}; };
var internalResolve = function (promise, state, value, unwrap) { var internalResolve = function (state, value, unwrap) {
if (state.done) return; if (state.done) return;
state.done = true; state.done = true;
if (unwrap) state = unwrap; if (unwrap) state = unwrap;
try { try {
if (promise === value) throw TypeError$1("Promise can't be resolved itself"); if (state.facade === value) throw TypeError$1("Promise can't be resolved itself");
var then = isThenable(value); var then = isThenable(value);
if (then) { if (then) {
microtask(function () { microtask(function () {
var wrapper = { done: false }; var wrapper = { done: false };
try { try {
then.call(value, then.call(value,
bind(internalResolve, promise, wrapper, state), bind(internalResolve, wrapper, state),
bind(internalReject, promise, wrapper, state) bind(internalReject, wrapper, state)
); );
} catch (error) { } catch (error) {
internalReject(promise, wrapper, error, state); internalReject(wrapper, error, state);
} }
}); });
} else { } else {
state.value = value; state.value = value;
state.state = FULFILLED; state.state = FULFILLED;
notify$1(promise, state, false); notify$1(state, false);
} }
} catch (error) { } catch (error) {
internalReject(promise, { done: false }, error, state); internalReject({ done: false }, error, state);
} }
}; };
@@ -6408,9 +6446,9 @@ typeof navigator === "object" && (function (global, factory) {
Internal.call(this); Internal.call(this);
var state = getInternalState$3(this); var state = getInternalState$3(this);
try { try {
executor(bind(internalResolve, this, state), bind(internalReject, this, state)); executor(bind(internalResolve, state), bind(internalReject, state));
} catch (error) { } catch (error) {
internalReject(this, state, error); internalReject(state, error);
} }
}; };
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
@@ -6434,10 +6472,10 @@ typeof navigator === "object" && (function (global, factory) {
var reaction = newPromiseCapability$1(speciesConstructor(this, PromiseConstructor)); var reaction = newPromiseCapability$1(speciesConstructor(this, PromiseConstructor));
reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
reaction.fail = typeof onRejected == 'function' && onRejected; reaction.fail = typeof onRejected == 'function' && onRejected;
reaction.domain = IS_NODE$1 ? process$3.domain : undefined; reaction.domain = engineIsNode ? process$3.domain : undefined;
state.parent = true; state.parent = true;
state.reactions.push(reaction); state.reactions.push(reaction);
if (state.state != PENDING) notify$1(this, state, false); if (state.state != PENDING) notify$1(state, false);
return reaction.promise; return reaction.promise;
}, },
// `Promise.prototype.catch` method // `Promise.prototype.catch` method
@@ -6450,8 +6488,8 @@ typeof navigator === "object" && (function (global, factory) {
var promise = new Internal(); var promise = new Internal();
var state = getInternalState$3(promise); var state = getInternalState$3(promise);
this.promise = promise; this.promise = promise;
this.resolve = bind(internalResolve, promise, state); this.resolve = bind(internalResolve, state);
this.reject = bind(internalReject, promise, state); this.reject = bind(internalReject, state);
}; };
newPromiseCapability.f = newPromiseCapability$1 = function (C) { newPromiseCapability.f = newPromiseCapability$1 = function (C) {
return C === PromiseConstructor || C === PromiseWrapper return C === PromiseConstructor || C === PromiseWrapper
@@ -6522,7 +6560,7 @@ typeof navigator === "object" && (function (global, factory) {
var values = []; var values = [];
var counter = 0; var counter = 0;
var remaining = 1; var remaining = 1;
iterate_1(iterable, function (promise) { iterate(iterable, function (promise) {
var index = counter++; var index = counter++;
var alreadyCalled = false; var alreadyCalled = false;
values.push(undefined); values.push(undefined);
@@ -6547,7 +6585,7 @@ typeof navigator === "object" && (function (global, factory) {
var reject = capability.reject; var reject = capability.reject;
var result = perform(function () { var result = perform(function () {
var $promiseResolve = aFunction$1(C.resolve); var $promiseResolve = aFunction$1(C.resolve);
iterate_1(iterable, function (promise) { iterate(iterable, function (promise) {
$promiseResolve.call(C, promise).then(capability.resolve, reject); $promiseResolve.call(C, promise).then(capability.resolve, reject);
}); });
}); });
@@ -6794,12 +6832,17 @@ typeof navigator === "object" && (function (global, factory) {
var STRICT_METHOD$5 = arrayMethodIsStrict('reduce'); var STRICT_METHOD$5 = arrayMethodIsStrict('reduce');
var USES_TO_LENGTH$9 = arrayMethodUsesToLength('reduce', { 1: 0 }); var USES_TO_LENGTH$9 = arrayMethodUsesToLength('reduce', { 1: 0 });
// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG = !engineIsNode && engineV8Version > 79 && engineV8Version < 83;
// `Array.prototype.reduce` method // `Array.prototype.reduce` method
// https://tc39.github.io/ecma262/#sec-array.prototype.reduce // https://tc39.github.io/ecma262/#sec-array.prototype.reduce
_export({ target: 'Array', proto: true, forced: !STRICT_METHOD$5 || !USES_TO_LENGTH$9 }, { _export({ target: 'Array', proto: true, forced: !STRICT_METHOD$5 || !USES_TO_LENGTH$9 || CHROME_BUG }, {
reduce: function reduce(callbackfn /* , initialValue */) { reduce: function reduce(callbackfn /* , initialValue */) {
return $reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined); return $reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
} }
@@ -7433,7 +7476,12 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10); var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
if (this.fullscreen.active) {
wrapper.style.paddingBottom = null;
} else {
this.media.style.transform = "translateY(-".concat(offset, "%)");
}
} else if (this.isHTML5) { } else if (this.isHTML5) {
wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
} }
@@ -9975,7 +10023,7 @@ typeof navigator === "object" && (function (global, factory) {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.6.2/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.6.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
// Quality default // Quality default
@@ -10093,7 +10141,7 @@ typeof navigator === "object" && (function (global, factory) {
vimeo: { vimeo: {
sdk: 'https://player.vimeo.com/api/player.js', sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}', iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json' api: 'https://vimeo.com/api/oembed.json?url={0}'
}, },
youtube: { youtube: {
sdk: 'https://www.youtube.com/iframe_api', sdk: 'https://www.youtube.com/iframe_api',
@@ -10263,24 +10311,27 @@ typeof navigator === "object" && (function (global, factory) {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// Custom settings from Plyr
customControls: true,
referrerPolicy: null,
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account // Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc) // (which allows us to properly hide controls without CSS hacks, etc)
premium: false, premium: false
// Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: true,
// Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
showinfo: 0, showinfo: 0,
// Hide info // Hide info
iv_load_policy: 3, iv_load_policy: 3,
// Hide annotations // Hide annotations
modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) modestbranding: 1,
// Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: true,
noCookie: false // Whether to use an alternative version of YouTube without cookies
} }
}; };
@@ -10399,7 +10450,7 @@ typeof navigator === "object" && (function (global, factory) {
return; return;
} }
_this.toggle(); _this.player.listeners.proxy(event, _this.toggle, 'fullscreen');
}); // Tap focus when in fullscreen }); // Tap focus when in fullscreen
on.call(this, this.player.elements.container, 'keydown', function (event) { on.call(this, this.player.elements.container, 'keydown', function (event) {
@@ -10422,10 +10473,12 @@ typeof navigator === "object" && (function (global, factory) {
if (is$1.element(button)) { if (is$1.element(button)) {
button.pressed = this.active; button.pressed = this.active;
} // Trigger an event } // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up
triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); var target = this.target === this.player.media ? this.target : this.player.elements.container; // Trigger an event
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
} }
}, { }, {
key: "toggleFallback", key: "toggleFallback",
@@ -10820,7 +10873,9 @@ typeof navigator === "object" && (function (global, factory) {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('data-poster', poster); // Wait until ui is ready this.media.setAttribute('data-poster', poster); // Show the poster
this.elements.poster.removeAttribute('hidden'); // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@@ -10904,7 +10959,7 @@ typeof navigator === "object" && (function (global, factory) {
// Loop through values (as they are the keys when the object is spread 🤔) // Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) { .filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr'); return !is$1.empty(key) && is$1.string(key) && key.startsWith('--plyr');
}).forEach(function (key) { }).forEach(function (key) {
// Set on the container // Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element _this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
@@ -11252,7 +11307,14 @@ typeof navigator === "object" && (function (global, factory) {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // Horrible hack for Safari 14 not repainting properly on entering fullscreen
if (isEnter) {
setTimeout(function () {
return repaint(elements.container);
}, 100);
} // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@@ -11443,9 +11505,17 @@ typeof navigator === "object" && (function (global, factory) {
this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind
this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind this.bind(elements.buttons.rewind, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after rewind
player.lastSeekTime = Date.now();
player.rewind();
}, 'rewind'); // Rewind
this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle this.bind(elements.buttons.fastForward, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after fast forward
player.lastSeekTime = Date.now();
player.forward();
}, 'fastForward'); // Mute toggle
this.bind(elements.buttons.mute, 'click', function () { this.bind(elements.buttons.mute, 'click', function () {
player.muted = !player.muted; player.muted = !player.muted;
@@ -12153,35 +12223,32 @@ typeof navigator === "object" && (function (global, factory) {
} // Inject the package } // Inject the package
var poster = player.poster; if (premium || !config.customControls) {
iframe.setAttribute('data-poster', player.poster);
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media); player.media = replaceElement(iframe, player.media);
} else { } else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
class: player.config.classNames.embedContainer, class: player.config.classNames.embedContainer,
'data-poster': poster 'data-poster': player.poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); player.media = replaceElement(wrapper, player.media);
} // Get poster image } // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { if (!config.customControls) {
if (is$1.empty(response)) { fetch(format(player.config.urls.vimeo.api, src)).then(function (response) {
return; if (is$1.empty(response) || !response.thumbnail_url) {
} // Get the URL for thumbnail return;
} // Set and show poster
var url = new URL(response[0].thumbnail_large); // Get original image ui.setPoster.call(player, response.thumbnail_url).catch(function () {});
});
url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster } // Setup instance
ui.setPoster.call(player, url.href).catch(function () {});
}); // Setup instance
// https://github.com/vimeo/player.js // https://github.com/vimeo/player.js
player.embed = new window.Vimeo.Player(iframe, { player.embed = new window.Vimeo.Player(iframe, {
autopause: player.config.autopause, autopause: player.config.autopause,
muted: player.muted muted: player.muted
@@ -12421,9 +12488,11 @@ typeof navigator === "object" && (function (global, factory) {
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}); // Rebuild UI }); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 0); return ui.build.call(player);
}, 0);
}
} }
}; };
@@ -12514,7 +12583,8 @@ typeof navigator === "object" && (function (global, factory) {
}, },
// API ready // API ready
ready: function ready() { ready: function ready() {
var player = this; // Ignore already setup (race condition) var player = this;
var config = player.config.youtube; // Ignore already setup (race condition)
var currentId = player.media && player.media.getAttribute('id'); var currentId = player.media && player.media.getAttribute('id');
@@ -12531,53 +12601,53 @@ typeof navigator === "object" && (function (global, factory) {
var videoId = parseId$1(source); var videoId = parseId$1(source);
var id = generateId(player.provider); // Get poster, if already set var id = generateId(player.provider); // Replace media element
var poster = player.poster; // Replace media element
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
'data-poster': poster 'data-poster': config.customControls ? player.poster : undefined
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Only load the poster when using custom controls
var posterSrc = function posterSrc(s) { if (config.customControls) {
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg"); var posterSrc = function posterSrc(s) {
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
.catch(function () { .catch(function () {
return loadImage(posterSrc('sd'), 121); return loadImage(posterSrc('sd'), 121);
}) // 480p padded 4:3 }) // 480p padded 4:3
.catch(function () { .catch(function () {
return loadImage(posterSrc('hq')); return loadImage(posterSrc('hq'));
}) // 360p padded 4:3. Always exists }) // 360p padded 4:3. Always exists
.then(function (image) { .then(function (image) {
return ui.setPoster.call(player, image.src); return ui.setPoster.call(player, image.src);
}).then(function (src) { }).then(function (src) {
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters) // If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
if (!src.includes('maxres')) { if (!src.includes('maxres')) {
player.elements.poster.style.backgroundSize = 'cover'; player.elements.poster.style.backgroundSize = 'cover';
} }
}).catch(function () {}); }).catch(function () {});
var config = player.config.youtube; // Setup instance } // Setup instance
// https://developers.google.com/youtube/iframe_api_reference // https://developers.google.com/youtube/iframe_api_reference
player.embed = new window.YT.Player(id, {
player.embed = new window.YT.Player(player.media, {
videoId: videoId, videoId: videoId,
host: getHost$1(config), host: getHost$1(config),
playerVars: extend({}, { playerVars: extend({}, {
autoplay: player.config.autoplay ? 1 : 0,
// Autoplay // Autoplay
hl: player.config.hl, autoplay: player.config.autoplay ? 1 : 0,
// iframe interface language // iframe interface language
controls: player.supported.ui ? 0 : 1, hl: player.config.hl,
// Only show controls if not fully supported // Only show controls if not fully supported or opted out
disablekb: 1, controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it // Disable keyboard as we handle it
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, disablekb: 1,
// Allow iOS inline playback // Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube // Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0, cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language, cc_lang_pref: player.config.captions.language,
@@ -12688,6 +12758,7 @@ typeof navigator === "object" && (function (global, factory) {
var toggle = is$1.boolean(input) ? input : muted; var toggle = is$1.boolean(input) ? input : muted;
muted = toggle; muted = toggle;
instance[toggle ? 'mute' : 'unMute'](); instance[toggle ? 'mute' : 'unMute']();
instance.setVolume(volume * 100);
triggerEvent.call(player, player.media, 'volumechange'); triggerEvent.call(player, player.media, 'volumechange');
} }
}); // Source }); // Source
@@ -12710,7 +12781,7 @@ typeof navigator === "object" && (function (global, factory) {
return player.config.speed.options.includes(s); return player.config.speed.options.includes(s);
}); // Set the tabindex to avoid focus entering iframe }); // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) { if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1); player.media.setAttribute('tabindex', -1);
} }
@@ -12737,9 +12808,11 @@ typeof navigator === "object" && (function (global, factory) {
} }
}, 200); // Rebuild UI }, 200); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 50); return ui.build.call(player);
}, 50);
}
}, },
onStateChange: function onStateChange(event) { onStateChange: function onStateChange(event) {
// Get the instance // Get the instance
@@ -12785,7 +12858,7 @@ typeof navigator === "object" && (function (global, factory) {
case 1: case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause(); player.media.pause();
} else { } else {
assurePlaybackState$1.call(player, true); assurePlaybackState$1.call(player, true);
@@ -12858,7 +12931,8 @@ typeof navigator === "object" && (function (global, factory) {
wrap$1(this.media, this.elements.wrapper); // Poster image container wrap$1(this.media, this.elements.wrapper); // Poster image container
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster,
hidden: ''
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
@@ -14726,9 +14800,9 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { this.once('canplay', function () {
return silencePromise(_this.play()); return silencePromise(_this.play());
}, 10); });
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -15017,7 +15091,9 @@ typeof navigator === "object" && (function (global, factory) {
} }
} else { } else {
// Unbind listeners // Unbind listeners
unbindListeners.call(_this3); // Replace the container with the original element provided unbindListeners.call(_this3); // Cancel current network requests
html5.cancelRequests.call(_this3); // Replace the container with the original element provided
replaceElement(_this3.elements.original, _this3.elements.container); // Event replaceElement(_this3.elements.original, _this3.elements.container); // Event
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+228 -152
View File
@@ -1,4 +1,4 @@
typeof navigator === "object" && // Polyfill for creating CustomEvents on IE9/10/11 // Polyfill for creating CustomEvents on IE9/10/11
// code pulled from: // code pulled from:
// https://github.com/d4tocchini/customevent-polyfill // https://github.com/d4tocchini/customevent-polyfill
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill
@@ -68,7 +68,7 @@ var global_1 =
check(typeof self == 'object' && self) || check(typeof self == 'object' && self) ||
check(typeof commonjsGlobal == 'object' && commonjsGlobal) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
// eslint-disable-next-line no-new-func // eslint-disable-next-line no-new-func
Function('return this')(); (function () { return this; })() || Function('return this')();
var fails = function (exec) { var fails = function (exec) {
try { try {
@@ -263,7 +263,7 @@ var shared = createCommonjsModule(function (module) {
(module.exports = function (key, value) { (module.exports = function (key, value) {
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
})('versions', []).push({ })('versions', []).push({
version: '3.6.5', version: '3.7.0',
mode: 'global', mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)' copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
}); });
@@ -301,11 +301,12 @@ var getterFor = function (TYPE) {
}; };
if (nativeWeakMap) { if (nativeWeakMap) {
var store$1 = new WeakMap$2(); var store$1 = sharedStore.state || (sharedStore.state = new WeakMap$2());
var wmget = store$1.get; var wmget = store$1.get;
var wmhas = store$1.has; var wmhas = store$1.has;
var wmset = store$1.set; var wmset = store$1.set;
set = function (it, metadata) { set = function (it, metadata) {
metadata.facade = it;
wmset.call(store$1, it, metadata); wmset.call(store$1, it, metadata);
return metadata; return metadata;
}; };
@@ -319,6 +320,7 @@ if (nativeWeakMap) {
var STATE = sharedKey('state'); var STATE = sharedKey('state');
hiddenKeys[STATE] = true; hiddenKeys[STATE] = true;
set = function (it, metadata) { set = function (it, metadata) {
metadata.facade = it;
createNonEnumerableProperty(it, STATE, metadata); createNonEnumerableProperty(it, STATE, metadata);
return metadata; return metadata;
}; };
@@ -347,9 +349,15 @@ var TEMPLATE = String(String).split('String');
var unsafe = options ? !!options.unsafe : false; var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false; var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false; var noTargetGet = options ? !!options.noTargetGet : false;
var state;
if (typeof value == 'function') { if (typeof value == 'function') {
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key); if (typeof key == 'string' && !has(value, 'name')) {
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : ''); createNonEnumerableProperty(value, 'name', key);
}
state = enforceInternalState(value);
if (!state.source) {
state.source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
} }
if (O === global_1) { if (O === global_1) {
if (simple) O[key] = value; if (simple) O[key] = value;
@@ -2435,14 +2443,20 @@ var objectAssign = !nativeAssign || fails(function () {
} return T; } return T;
} : nativeAssign; } : nativeAssign;
var iteratorClose = function (iterator) {
var returnMethod = iterator['return'];
if (returnMethod !== undefined) {
return anObject(returnMethod.call(iterator)).value;
}
};
// call something on iterator step with safe closing on error // call something on iterator step with safe closing on error
var callWithSafeIterationClosing = function (iterator, fn, value, ENTRIES) { var callWithSafeIterationClosing = function (iterator, fn, value, ENTRIES) {
try { try {
return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value); return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value);
// 7.4.6 IteratorClose(iterator, completion) // 7.4.6 IteratorClose(iterator, completion)
} catch (error) { } catch (error) {
var returnMethod = iterator['return']; iteratorClose(iterator);
if (returnMethod !== undefined) anObject(returnMethod.call(iterator));
throw error; throw error;
} }
}; };
@@ -2839,7 +2853,7 @@ var URLSearchParamsConstructor = function URLSearchParams(/* init */) {
var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype; var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
redefineAll(URLSearchParamsPrototype, { redefineAll(URLSearchParamsPrototype, {
// `URLSearchParams.prototype.appent` method // `URLSearchParams.prototype.append` method
// https://url.spec.whatwg.org/#dom-urlsearchparams-append // https://url.spec.whatwg.org/#dom-urlsearchparams-append
append: function append(name, value) { append: function append(name, value) {
validateArgumentsLength(arguments.length, 2); validateArgumentsLength(arguments.length, 2);
@@ -4402,7 +4416,7 @@ function _nonIterableRest() {
var checkIfURLSearchParamsSupported = function checkIfURLSearchParamsSupported() { var checkIfURLSearchParamsSupported = function checkIfURLSearchParamsSupported() {
try { try {
var URLSearchParams = global.URLSearchParams; var URLSearchParams = global.URLSearchParams;
return new URLSearchParams('?a=1').toString() === 'a=1' && typeof URLSearchParams.prototype.set === 'function'; return new URLSearchParams('?a=1').toString() === 'a=1' && typeof URLSearchParams.prototype.set === 'function' && typeof URLSearchParams.prototype.entries === 'function';
} catch (e) { } catch (e) {
return false; return false;
} }
@@ -4500,12 +4514,14 @@ function _nonIterableRest() {
var _URL = global.URL; var _URL = global.URL;
var URL = function URL(url, base) { var URL = function URL(url, base) {
if (typeof url !== 'string') url = String(url); // Only create another document if the base is different from current location. if (typeof url !== 'string') url = String(url);
if (base && typeof base !== 'string') base = String(base); // Only create another document if the base is different from current location.
var doc = document, var doc = document,
baseElement; baseElement;
if (base && (global.location === void 0 || base !== global.location.href)) { if (base && (global.location === void 0 || base !== global.location.href)) {
base = base.toLowerCase();
doc = document.implementation.createHTMLDocument(''); doc = document.implementation.createHTMLDocument('');
baseElement = doc.createElement('base'); baseElement = doc.createElement('base');
baseElement.href = base; baseElement.href = base;
@@ -4526,7 +4542,11 @@ function _nonIterableRest() {
anchorElement.href = anchorElement.href; // force href to refresh anchorElement.href = anchorElement.href; // force href to refresh
} }
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) { var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href) || !inputElement.checkValidity() && !base) {
throw new TypeError('Invalid URL'); throw new TypeError('Invalid URL');
} }
@@ -5007,11 +5027,11 @@ var correctIsRegexpLogic = function (METHOD_NAME) {
var regexp = /./; var regexp = /./;
try { try {
'/./'[METHOD_NAME](regexp); '/./'[METHOD_NAME](regexp);
} catch (e) { } catch (error1) {
try { try {
regexp[MATCH$1] = false; regexp[MATCH$1] = false;
return '/./'[METHOD_NAME](regexp); return '/./'[METHOD_NAME](regexp);
} catch (f) { /* empty */ } } catch (error2) { /* empty */ }
} return false; } return false;
}; };
@@ -5093,16 +5113,31 @@ var internalMetadata_2 = internalMetadata.fastKey;
var internalMetadata_3 = internalMetadata.getWeakData; var internalMetadata_3 = internalMetadata.getWeakData;
var internalMetadata_4 = internalMetadata.onFreeze; var internalMetadata_4 = internalMetadata.onFreeze;
var iterate_1 = createCommonjsModule(function (module) {
var Result = function (stopped, result) { var Result = function (stopped, result) {
this.stopped = stopped; this.stopped = stopped;
this.result = result; this.result = result;
}; };
var iterate = module.exports = function (iterable, fn, that, AS_ENTRIES, IS_ITERATOR) { var iterate = function (iterable, unboundFunction, options) {
var boundFunction = functionBindContext(fn, that, AS_ENTRIES ? 2 : 1); var that = options && options.that;
var AS_ENTRIES = !!(options && options.AS_ENTRIES);
var IS_ITERATOR = !!(options && options.IS_ITERATOR);
var INTERRUPTED = !!(options && options.INTERRUPTED);
var fn = functionBindContext(unboundFunction, that, 1 + AS_ENTRIES + INTERRUPTED);
var iterator, iterFn, index, length, result, next, step; var iterator, iterFn, index, length, result, next, step;
var stop = function (condition) {
if (iterator) iteratorClose(iterator);
return new Result(true, condition);
};
var callFn = function (value) {
if (AS_ENTRIES) {
anObject(value);
return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
} return INTERRUPTED ? fn(value, stop) : fn(value);
};
if (IS_ITERATOR) { if (IS_ITERATOR) {
iterator = iterable; iterator = iterable;
} else { } else {
@@ -5111,9 +5146,7 @@ var iterate = module.exports = function (iterable, fn, that, AS_ENTRIES, IS_ITER
// optimisation for array iterators // optimisation for array iterators
if (isArrayIteratorMethod(iterFn)) { if (isArrayIteratorMethod(iterFn)) {
for (index = 0, length = toLength(iterable.length); length > index; index++) { for (index = 0, length = toLength(iterable.length); length > index; index++) {
result = AS_ENTRIES result = callFn(iterable[index]);
? boundFunction(anObject(step = iterable[index])[0], step[1])
: boundFunction(iterable[index]);
if (result && result instanceof Result) return result; if (result && result instanceof Result) return result;
} return new Result(false); } return new Result(false);
} }
@@ -5122,16 +5155,16 @@ var iterate = module.exports = function (iterable, fn, that, AS_ENTRIES, IS_ITER
next = iterator.next; next = iterator.next;
while (!(step = next.call(iterator)).done) { while (!(step = next.call(iterator)).done) {
result = callWithSafeIterationClosing(iterator, boundFunction, step.value, AS_ENTRIES); try {
result = callFn(step.value);
} catch (error) {
iteratorClose(iterator);
throw error;
}
if (typeof result == 'object' && result && result instanceof Result) return result; if (typeof result == 'object' && result && result instanceof Result) return result;
} return new Result(false); } return new Result(false);
}; };
iterate.stop = function (result) {
return new Result(true, result);
};
});
var collection = function (CONSTRUCTOR_NAME, wrapper, common) { var collection = function (CONSTRUCTOR_NAME, wrapper, common) {
var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1; var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1; var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
@@ -5189,7 +5222,7 @@ var collection = function (CONSTRUCTOR_NAME, wrapper, common) {
Constructor = wrapper(function (dummy, iterable) { Constructor = wrapper(function (dummy, iterable) {
anInstance(dummy, Constructor, CONSTRUCTOR_NAME); anInstance(dummy, Constructor, CONSTRUCTOR_NAME);
var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor); var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
if (iterable != undefined) iterate_1(iterable, that[ADDER], that, IS_MAP); if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
return that; return that;
}); });
Constructor.prototype = NativePrototype; Constructor.prototype = NativePrototype;
@@ -5279,7 +5312,7 @@ var collectionWeak = {
id: id$1++, id: id$1++,
frozen: undefined frozen: undefined
}); });
if (iterable != undefined) iterate_1(iterable, that[ADDER], that, IS_MAP); if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
}); });
var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME); var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
@@ -5968,6 +6001,8 @@ var setSpecies = function (CONSTRUCTOR_NAME) {
var engineIsIos = /(iphone|ipod|ipad).*applewebkit/i.test(engineUserAgent); var engineIsIos = /(iphone|ipod|ipad).*applewebkit/i.test(engineUserAgent);
var engineIsNode = classofRaw(global_1.process) == 'process';
var location = global_1.location; var location = global_1.location;
var set$1 = global_1.setImmediate; var set$1 = global_1.setImmediate;
var clear = global_1.clearImmediate; var clear = global_1.clearImmediate;
@@ -6020,7 +6055,7 @@ if (!set$1 || !clear) {
delete queue[id]; delete queue[id];
}; };
// Node.js 0.8- // Node.js 0.8-
if (classofRaw(process$1) == 'process') { if (engineIsNode) {
defer = function (id) { defer = function (id) {
process$1.nextTick(runner(id)); process$1.nextTick(runner(id));
}; };
@@ -6042,8 +6077,8 @@ if (!set$1 || !clear) {
global_1.addEventListener && global_1.addEventListener &&
typeof postMessage == 'function' && typeof postMessage == 'function' &&
!global_1.importScripts && !global_1.importScripts &&
!fails(post) && location && location.protocol !== 'file:' &&
location.protocol !== 'file:' !fails(post)
) { ) {
defer = post; defer = post;
global_1.addEventListener('message', listener, false); global_1.addEventListener('message', listener, false);
@@ -6069,14 +6104,14 @@ var task = {
}; };
var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f; var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f;
var macrotask = task.set; var macrotask = task.set;
var MutationObserver$1 = global_1.MutationObserver || global_1.WebKitMutationObserver; var MutationObserver$1 = global_1.MutationObserver || global_1.WebKitMutationObserver;
var document$2 = global_1.document;
var process$2 = global_1.process; var process$2 = global_1.process;
var Promise$1 = global_1.Promise; var Promise$1 = global_1.Promise;
var IS_NODE = classofRaw(process$2) == 'process';
// Node.js 11 shows ExperimentalWarning on getting `queueMicrotask` // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global_1, 'queueMicrotask'); var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global_1, 'queueMicrotask');
var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value; var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
@@ -6087,7 +6122,7 @@ var flush, head, last, notify, toggle, node, promise, then;
if (!queueMicrotask) { if (!queueMicrotask) {
flush = function () { flush = function () {
var parent, fn; var parent, fn;
if (IS_NODE && (parent = process$2.domain)) parent.exit(); if (engineIsNode && (parent = process$2.domain)) parent.exit();
while (head) { while (head) {
fn = head.fn; fn = head.fn;
head = head.next; head = head.next;
@@ -6102,15 +6137,10 @@ if (!queueMicrotask) {
if (parent) parent.enter(); if (parent) parent.enter();
}; };
// Node.js
if (IS_NODE) {
notify = function () {
process$2.nextTick(flush);
};
// browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339 // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
} else if (MutationObserver$1 && !engineIsIos) { if (!engineIsIos && !engineIsNode && MutationObserver$1 && document$2) {
toggle = true; toggle = true;
node = document.createTextNode(''); node = document$2.createTextNode('');
new MutationObserver$1(flush).observe(node, { characterData: true }); new MutationObserver$1(flush).observe(node, { characterData: true });
notify = function () { notify = function () {
node.data = toggle = !toggle; node.data = toggle = !toggle;
@@ -6123,6 +6153,11 @@ if (!queueMicrotask) {
notify = function () { notify = function () {
then.call(promise, flush); then.call(promise, flush);
}; };
// Node.js without promises
} else if (engineIsNode) {
notify = function () {
process$2.nextTick(flush);
};
// for other environments - macrotask based on: // for other environments - macrotask based on:
// - setImmediate // - setImmediate
// - MessageChannel // - MessageChannel
@@ -6201,6 +6236,7 @@ var task$1 = task.set;
var SPECIES$6 = wellKnownSymbol('species'); var SPECIES$6 = wellKnownSymbol('species');
var PROMISE = 'Promise'; var PROMISE = 'Promise';
var getInternalState$3 = internalState.get; var getInternalState$3 = internalState.get;
@@ -6208,13 +6244,13 @@ var setInternalState$6 = internalState.set;
var getInternalPromiseState = internalState.getterFor(PROMISE); var getInternalPromiseState = internalState.getterFor(PROMISE);
var PromiseConstructor = nativePromiseConstructor; var PromiseConstructor = nativePromiseConstructor;
var TypeError$1 = global_1.TypeError; var TypeError$1 = global_1.TypeError;
var document$2 = global_1.document; var document$3 = global_1.document;
var process$3 = global_1.process; var process$3 = global_1.process;
var $fetch$1 = getBuiltIn('fetch'); var $fetch$1 = getBuiltIn('fetch');
var newPromiseCapability$1 = newPromiseCapability.f; var newPromiseCapability$1 = newPromiseCapability.f;
var newGenericPromiseCapability = newPromiseCapability$1; var newGenericPromiseCapability = newPromiseCapability$1;
var IS_NODE$1 = classofRaw(process$3) == 'process'; var DISPATCH_EVENT = !!(document$3 && document$3.createEvent && global_1.dispatchEvent);
var DISPATCH_EVENT = !!(document$2 && document$2.createEvent && global_1.dispatchEvent); var NATIVE_REJECTION_EVENT = typeof PromiseRejectionEvent == 'function';
var UNHANDLED_REJECTION = 'unhandledrejection'; var UNHANDLED_REJECTION = 'unhandledrejection';
var REJECTION_HANDLED = 'rejectionhandled'; var REJECTION_HANDLED = 'rejectionhandled';
var PENDING = 0; var PENDING = 0;
@@ -6232,7 +6268,7 @@ var FORCED$3 = isForced_1(PROMISE, function () {
// We can't detect it synchronously, so just check versions // We can't detect it synchronously, so just check versions
if (engineV8Version === 66) return true; if (engineV8Version === 66) return true;
// Unhandled rejections tracking support, NodeJS Promise without it fails @@species test // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
if (!IS_NODE$1 && typeof PromiseRejectionEvent != 'function') return true; if (!engineIsNode && !NATIVE_REJECTION_EVENT) return true;
} }
// We can't use @@species feature detection in V8 since it causes // We can't use @@species feature detection in V8 since it causes
// deoptimization and performance degradation // deoptimization and performance degradation
@@ -6258,7 +6294,7 @@ var isThenable = function (it) {
return isObject(it) && typeof (then = it.then) == 'function' ? then : false; return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
}; };
var notify$1 = function (promise, state, isReject) { var notify$1 = function (state, isReject) {
if (state.notified) return; if (state.notified) return;
state.notified = true; state.notified = true;
var chain = state.reactions; var chain = state.reactions;
@@ -6277,7 +6313,7 @@ var notify$1 = function (promise, state, isReject) {
try { try {
if (handler) { if (handler) {
if (!ok) { if (!ok) {
if (state.rejection === UNHANDLED) onHandleUnhandled(promise, state); if (state.rejection === UNHANDLED) onHandleUnhandled(state);
state.rejection = HANDLED; state.rejection = HANDLED;
} }
if (handler === true) result = value; if (handler === true) result = value;
@@ -6302,36 +6338,37 @@ var notify$1 = function (promise, state, isReject) {
} }
state.reactions = []; state.reactions = [];
state.notified = false; state.notified = false;
if (isReject && !state.rejection) onUnhandled(promise, state); if (isReject && !state.rejection) onUnhandled(state);
}); });
}; };
var dispatchEvent = function (name, promise, reason) { var dispatchEvent = function (name, promise, reason) {
var event, handler; var event, handler;
if (DISPATCH_EVENT) { if (DISPATCH_EVENT) {
event = document$2.createEvent('Event'); event = document$3.createEvent('Event');
event.promise = promise; event.promise = promise;
event.reason = reason; event.reason = reason;
event.initEvent(name, false, true); event.initEvent(name, false, true);
global_1.dispatchEvent(event); global_1.dispatchEvent(event);
} else event = { promise: promise, reason: reason }; } else event = { promise: promise, reason: reason };
if (handler = global_1['on' + name]) handler(event); if (!NATIVE_REJECTION_EVENT && (handler = global_1['on' + name])) handler(event);
else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason); else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
}; };
var onUnhandled = function (promise, state) { var onUnhandled = function (state) {
task$1.call(global_1, function () { task$1.call(global_1, function () {
var promise = state.facade;
var value = state.value; var value = state.value;
var IS_UNHANDLED = isUnhandled(state); var IS_UNHANDLED = isUnhandled(state);
var result; var result;
if (IS_UNHANDLED) { if (IS_UNHANDLED) {
result = perform(function () { result = perform(function () {
if (IS_NODE$1) { if (engineIsNode) {
process$3.emit('unhandledRejection', value, promise); process$3.emit('unhandledRejection', value, promise);
} else dispatchEvent(UNHANDLED_REJECTION, promise, value); } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
}); });
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
state.rejection = IS_NODE$1 || isUnhandled(state) ? UNHANDLED : HANDLED; state.rejection = engineIsNode || isUnhandled(state) ? UNHANDLED : HANDLED;
if (result.error) throw result.value; if (result.error) throw result.value;
} }
}); });
@@ -6341,55 +6378,56 @@ var isUnhandled = function (state) {
return state.rejection !== HANDLED && !state.parent; return state.rejection !== HANDLED && !state.parent;
}; };
var onHandleUnhandled = function (promise, state) { var onHandleUnhandled = function (state) {
task$1.call(global_1, function () { task$1.call(global_1, function () {
if (IS_NODE$1) { var promise = state.facade;
if (engineIsNode) {
process$3.emit('rejectionHandled', promise); process$3.emit('rejectionHandled', promise);
} else dispatchEvent(REJECTION_HANDLED, promise, state.value); } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
}); });
}; };
var bind = function (fn, promise, state, unwrap) { var bind = function (fn, state, unwrap) {
return function (value) { return function (value) {
fn(promise, state, value, unwrap); fn(state, value, unwrap);
}; };
}; };
var internalReject = function (promise, state, value, unwrap) { var internalReject = function (state, value, unwrap) {
if (state.done) return; if (state.done) return;
state.done = true; state.done = true;
if (unwrap) state = unwrap; if (unwrap) state = unwrap;
state.value = value; state.value = value;
state.state = REJECTED; state.state = REJECTED;
notify$1(promise, state, true); notify$1(state, true);
}; };
var internalResolve = function (promise, state, value, unwrap) { var internalResolve = function (state, value, unwrap) {
if (state.done) return; if (state.done) return;
state.done = true; state.done = true;
if (unwrap) state = unwrap; if (unwrap) state = unwrap;
try { try {
if (promise === value) throw TypeError$1("Promise can't be resolved itself"); if (state.facade === value) throw TypeError$1("Promise can't be resolved itself");
var then = isThenable(value); var then = isThenable(value);
if (then) { if (then) {
microtask(function () { microtask(function () {
var wrapper = { done: false }; var wrapper = { done: false };
try { try {
then.call(value, then.call(value,
bind(internalResolve, promise, wrapper, state), bind(internalResolve, wrapper, state),
bind(internalReject, promise, wrapper, state) bind(internalReject, wrapper, state)
); );
} catch (error) { } catch (error) {
internalReject(promise, wrapper, error, state); internalReject(wrapper, error, state);
} }
}); });
} else { } else {
state.value = value; state.value = value;
state.state = FULFILLED; state.state = FULFILLED;
notify$1(promise, state, false); notify$1(state, false);
} }
} catch (error) { } catch (error) {
internalReject(promise, { done: false }, error, state); internalReject({ done: false }, error, state);
} }
}; };
@@ -6402,9 +6440,9 @@ if (FORCED$3) {
Internal.call(this); Internal.call(this);
var state = getInternalState$3(this); var state = getInternalState$3(this);
try { try {
executor(bind(internalResolve, this, state), bind(internalReject, this, state)); executor(bind(internalResolve, state), bind(internalReject, state));
} catch (error) { } catch (error) {
internalReject(this, state, error); internalReject(state, error);
} }
}; };
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
@@ -6428,10 +6466,10 @@ if (FORCED$3) {
var reaction = newPromiseCapability$1(speciesConstructor(this, PromiseConstructor)); var reaction = newPromiseCapability$1(speciesConstructor(this, PromiseConstructor));
reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
reaction.fail = typeof onRejected == 'function' && onRejected; reaction.fail = typeof onRejected == 'function' && onRejected;
reaction.domain = IS_NODE$1 ? process$3.domain : undefined; reaction.domain = engineIsNode ? process$3.domain : undefined;
state.parent = true; state.parent = true;
state.reactions.push(reaction); state.reactions.push(reaction);
if (state.state != PENDING) notify$1(this, state, false); if (state.state != PENDING) notify$1(state, false);
return reaction.promise; return reaction.promise;
}, },
// `Promise.prototype.catch` method // `Promise.prototype.catch` method
@@ -6444,8 +6482,8 @@ if (FORCED$3) {
var promise = new Internal(); var promise = new Internal();
var state = getInternalState$3(promise); var state = getInternalState$3(promise);
this.promise = promise; this.promise = promise;
this.resolve = bind(internalResolve, promise, state); this.resolve = bind(internalResolve, state);
this.reject = bind(internalReject, promise, state); this.reject = bind(internalReject, state);
}; };
newPromiseCapability.f = newPromiseCapability$1 = function (C) { newPromiseCapability.f = newPromiseCapability$1 = function (C) {
return C === PromiseConstructor || C === PromiseWrapper return C === PromiseConstructor || C === PromiseWrapper
@@ -6516,7 +6554,7 @@ _export({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION$1 }, {
var values = []; var values = [];
var counter = 0; var counter = 0;
var remaining = 1; var remaining = 1;
iterate_1(iterable, function (promise) { iterate(iterable, function (promise) {
var index = counter++; var index = counter++;
var alreadyCalled = false; var alreadyCalled = false;
values.push(undefined); values.push(undefined);
@@ -6541,7 +6579,7 @@ _export({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION$1 }, {
var reject = capability.reject; var reject = capability.reject;
var result = perform(function () { var result = perform(function () {
var $promiseResolve = aFunction$1(C.resolve); var $promiseResolve = aFunction$1(C.resolve);
iterate_1(iterable, function (promise) { iterate(iterable, function (promise) {
$promiseResolve.call(C, promise).then(capability.resolve, reject); $promiseResolve.call(C, promise).then(capability.resolve, reject);
}); });
}); });
@@ -6788,12 +6826,17 @@ var $reduce = arrayReduce.left;
var STRICT_METHOD$5 = arrayMethodIsStrict('reduce'); var STRICT_METHOD$5 = arrayMethodIsStrict('reduce');
var USES_TO_LENGTH$9 = arrayMethodUsesToLength('reduce', { 1: 0 }); var USES_TO_LENGTH$9 = arrayMethodUsesToLength('reduce', { 1: 0 });
// Chrome 80-82 has a critical bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
var CHROME_BUG = !engineIsNode && engineV8Version > 79 && engineV8Version < 83;
// `Array.prototype.reduce` method // `Array.prototype.reduce` method
// https://tc39.github.io/ecma262/#sec-array.prototype.reduce // https://tc39.github.io/ecma262/#sec-array.prototype.reduce
_export({ target: 'Array', proto: true, forced: !STRICT_METHOD$5 || !USES_TO_LENGTH$9 }, { _export({ target: 'Array', proto: true, forced: !STRICT_METHOD$5 || !USES_TO_LENGTH$9 || CHROME_BUG }, {
reduce: function reduce(callbackfn /* , initialValue */) { reduce: function reduce(callbackfn /* , initialValue */) {
return $reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined); return $reduce(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
} }
@@ -7427,7 +7470,12 @@ function setAspectRatio(input) {
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10); var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
if (this.fullscreen.active) {
wrapper.style.paddingBottom = null;
} else {
this.media.style.transform = "translateY(-".concat(offset, "%)");
}
} else if (this.isHTML5) { } else if (this.isHTML5) {
wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
} }
@@ -9969,7 +10017,7 @@ var defaults$1 = {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.6.2/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.6.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
// Quality default // Quality default
@@ -10087,7 +10135,7 @@ var defaults$1 = {
vimeo: { vimeo: {
sdk: 'https://player.vimeo.com/api/player.js', sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}', iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json' api: 'https://vimeo.com/api/oembed.json?url={0}'
}, },
youtube: { youtube: {
sdk: 'https://www.youtube.com/iframe_api', sdk: 'https://www.youtube.com/iframe_api',
@@ -10257,24 +10305,27 @@ var defaults$1 = {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// Custom settings from Plyr
customControls: true,
referrerPolicy: null,
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account // Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc) // (which allows us to properly hide controls without CSS hacks, etc)
premium: false, premium: false
// Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: true,
// Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
showinfo: 0, showinfo: 0,
// Hide info // Hide info
iv_load_policy: 3, iv_load_policy: 3,
// Hide annotations // Hide annotations
modestbranding: 1 // Hide logos as much as possible (they still show one in the corner when paused) modestbranding: 1,
// Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: true,
noCookie: false // Whether to use an alternative version of YouTube without cookies
} }
}; };
@@ -10393,7 +10444,7 @@ var Fullscreen = /*#__PURE__*/function () {
return; return;
} }
_this.toggle(); _this.player.listeners.proxy(event, _this.toggle, 'fullscreen');
}); // Tap focus when in fullscreen }); // Tap focus when in fullscreen
on.call(this, this.player.elements.container, 'keydown', function (event) { on.call(this, this.player.elements.container, 'keydown', function (event) {
@@ -10416,10 +10467,12 @@ var Fullscreen = /*#__PURE__*/function () {
if (is$1.element(button)) { if (is$1.element(button)) {
button.pressed = this.active; button.pressed = this.active;
} // Trigger an event } // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up
triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); var target = this.target === this.player.media ? this.target : this.player.elements.container; // Trigger an event
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
} }
}, { }, {
key: "toggleFallback", key: "toggleFallback",
@@ -10814,7 +10867,9 @@ var ui = {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('data-poster', poster); // Wait until ui is ready this.media.setAttribute('data-poster', poster); // Show the poster
this.elements.poster.removeAttribute('hidden'); // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@@ -10898,7 +10953,7 @@ var ui = {
// Loop through values (as they are the keys when the object is spread 🤔) // Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) { .filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr'); return !is$1.empty(key) && is$1.string(key) && key.startsWith('--plyr');
}).forEach(function (key) { }).forEach(function (key) {
// Set on the container // Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element _this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
@@ -11246,7 +11301,14 @@ var Listeners = /*#__PURE__*/function () {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // Horrible hack for Safari 14 not repainting properly on entering fullscreen
if (isEnter) {
setTimeout(function () {
return repaint(elements.container);
}, 100);
} // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@@ -11437,9 +11499,17 @@ var Listeners = /*#__PURE__*/function () {
this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); // Rewind
this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); // Rewind this.bind(elements.buttons.rewind, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after rewind
player.lastSeekTime = Date.now();
player.rewind();
}, 'rewind'); // Rewind
this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); // Mute toggle this.bind(elements.buttons.fastForward, 'click', function () {
// Record seek time so we can prevent hiding controls for a few seconds after fast forward
player.lastSeekTime = Date.now();
player.forward();
}, 'fastForward'); // Mute toggle
this.bind(elements.buttons.mute, 'click', function () { this.bind(elements.buttons.mute, 'click', function () {
player.muted = !player.muted; player.muted = !player.muted;
@@ -12147,35 +12217,32 @@ var vimeo = {
} // Inject the package } // Inject the package
var poster = player.poster; if (premium || !config.customControls) {
iframe.setAttribute('data-poster', player.poster);
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media); player.media = replaceElement(iframe, player.media);
} else { } else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
class: player.config.classNames.embedContainer, class: player.config.classNames.embedContainer,
'data-poster': poster 'data-poster': player.poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); player.media = replaceElement(wrapper, player.media);
} // Get poster image } // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { if (!config.customControls) {
if (is$1.empty(response)) { fetch(format(player.config.urls.vimeo.api, src)).then(function (response) {
return; if (is$1.empty(response) || !response.thumbnail_url) {
} // Get the URL for thumbnail return;
} // Set and show poster
var url = new URL(response[0].thumbnail_large); // Get original image ui.setPoster.call(player, response.thumbnail_url).catch(function () {});
});
url.pathname = "".concat(url.pathname.split('_')[0], ".jpg"); // Set and show poster } // Setup instance
ui.setPoster.call(player, url.href).catch(function () {});
}); // Setup instance
// https://github.com/vimeo/player.js // https://github.com/vimeo/player.js
player.embed = new window.Vimeo.Player(iframe, { player.embed = new window.Vimeo.Player(iframe, {
autopause: player.config.autopause, autopause: player.config.autopause,
muted: player.muted muted: player.muted
@@ -12415,9 +12482,11 @@ var vimeo = {
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}); // Rebuild UI }); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 0); return ui.build.call(player);
}, 0);
}
} }
}; };
@@ -12508,7 +12577,8 @@ var youtube = {
}, },
// API ready // API ready
ready: function ready() { ready: function ready() {
var player = this; // Ignore already setup (race condition) var player = this;
var config = player.config.youtube; // Ignore already setup (race condition)
var currentId = player.media && player.media.getAttribute('id'); var currentId = player.media && player.media.getAttribute('id');
@@ -12525,53 +12595,53 @@ var youtube = {
var videoId = parseId$1(source); var videoId = parseId$1(source);
var id = generateId(player.provider); // Get poster, if already set var id = generateId(player.provider); // Replace media element
var poster = player.poster; // Replace media element
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
'data-poster': poster 'data-poster': config.customControls ? player.poster : undefined
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Only load the poster when using custom controls
var posterSrc = function posterSrc(s) { if (config.customControls) {
return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg"); var posterSrc = function posterSrc(s) {
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg");
}; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
.catch(function () { .catch(function () {
return loadImage(posterSrc('sd'), 121); return loadImage(posterSrc('sd'), 121);
}) // 480p padded 4:3 }) // 480p padded 4:3
.catch(function () { .catch(function () {
return loadImage(posterSrc('hq')); return loadImage(posterSrc('hq'));
}) // 360p padded 4:3. Always exists }) // 360p padded 4:3. Always exists
.then(function (image) { .then(function (image) {
return ui.setPoster.call(player, image.src); return ui.setPoster.call(player, image.src);
}).then(function (src) { }).then(function (src) {
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters) // If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
if (!src.includes('maxres')) { if (!src.includes('maxres')) {
player.elements.poster.style.backgroundSize = 'cover'; player.elements.poster.style.backgroundSize = 'cover';
} }
}).catch(function () {}); }).catch(function () {});
var config = player.config.youtube; // Setup instance } // Setup instance
// https://developers.google.com/youtube/iframe_api_reference // https://developers.google.com/youtube/iframe_api_reference
player.embed = new window.YT.Player(id, {
player.embed = new window.YT.Player(player.media, {
videoId: videoId, videoId: videoId,
host: getHost$1(config), host: getHost$1(config),
playerVars: extend({}, { playerVars: extend({}, {
autoplay: player.config.autoplay ? 1 : 0,
// Autoplay // Autoplay
hl: player.config.hl, autoplay: player.config.autoplay ? 1 : 0,
// iframe interface language // iframe interface language
controls: player.supported.ui ? 0 : 1, hl: player.config.hl,
// Only show controls if not fully supported // Only show controls if not fully supported or opted out
disablekb: 1, controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it // Disable keyboard as we handle it
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, disablekb: 1,
// Allow iOS inline playback // Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube // Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0, cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language, cc_lang_pref: player.config.captions.language,
@@ -12682,6 +12752,7 @@ var youtube = {
var toggle = is$1.boolean(input) ? input : muted; var toggle = is$1.boolean(input) ? input : muted;
muted = toggle; muted = toggle;
instance[toggle ? 'mute' : 'unMute'](); instance[toggle ? 'mute' : 'unMute']();
instance.setVolume(volume * 100);
triggerEvent.call(player, player.media, 'volumechange'); triggerEvent.call(player, player.media, 'volumechange');
} }
}); // Source }); // Source
@@ -12704,7 +12775,7 @@ var youtube = {
return player.config.speed.options.includes(s); return player.config.speed.options.includes(s);
}); // Set the tabindex to avoid focus entering iframe }); // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) { if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1); player.media.setAttribute('tabindex', -1);
} }
@@ -12731,9 +12802,11 @@ var youtube = {
} }
}, 200); // Rebuild UI }, 200); // Rebuild UI
setTimeout(function () { if (config.customControls) {
return ui.build.call(player); setTimeout(function () {
}, 50); return ui.build.call(player);
}, 50);
}
}, },
onStateChange: function onStateChange(event) { onStateChange: function onStateChange(event) {
// Get the instance // Get the instance
@@ -12779,7 +12852,7 @@ var youtube = {
case 1: case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause(); player.media.pause();
} else { } else {
assurePlaybackState$1.call(player, true); assurePlaybackState$1.call(player, true);
@@ -12852,7 +12925,8 @@ var media = {
wrap$1(this.media, this.elements.wrapper); // Poster image container wrap$1(this.media, this.elements.wrapper); // Poster image container
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster,
hidden: ''
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
@@ -14720,9 +14794,9 @@ var Plyr = /*#__PURE__*/function () {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { this.once('canplay', function () {
return silencePromise(_this.play()); return silencePromise(_this.play());
}, 10); });
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -15011,7 +15085,9 @@ var Plyr = /*#__PURE__*/function () {
} }
} else { } else {
// Unbind listeners // Unbind listeners
unbindListeners.call(_this3); // Replace the container with the original element provided unbindListeners.call(_this3); // Cancel current network requests
html5.cancelRequests.call(_this3); // Replace the container with the original element provided
replaceElement(_this3.elements.original, _this3.elements.container); // Event replaceElement(_this3.elements.original, _this3.elements.container); // Event
+30 -30
View File
@@ -1,6 +1,6 @@
{ {
"name": "plyr", "name": "plyr",
"version": "3.6.2", "version": "3.6.3",
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player", "description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
"homepage": "https://plyr.io", "homepage": "https://plyr.io",
"author": "Sam Potts <sam@potts.es>", "author": "Sam Potts <sam@potts.es>",
@@ -35,66 +35,66 @@
"lint:fix": "eslint --fix src/js", "lint:fix": "eslint --fix src/js",
"remark": "remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'", "remark": "remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'",
"deploy": "yarn lint && gulp version && gulp build && gulp deploy", "deploy": "yarn lint && gulp version && gulp build && gulp deploy",
"format": "prettier --write \"./{src,demo/src}/**/*.{js,scss}\"" "format": "prettier --write \"./{src,demo/src}/**/*.{js,scss}\"",
"start": "gulp"
}, },
"devDependencies": { "devDependencies": {
"@sampotts/eslint-config": "1.1.5",
"ansi-colors": "^4.1.1", "ansi-colors": "^4.1.1",
"autoprefixer": "^9.7.6", "autoprefixer": "^10.0.2",
"aws-sdk": "^2.668.0", "aws-sdk": "^2.773.0",
"@babel/core": "^7.9.6", "@babel/core": "^7.12.3",
"@babel/preset-env": "^7.9.6", "@babel/preset-env": "^7.12.1",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"browser-sync": "^2.26.7", "browser-sync": "^2.26.13",
"del": "^5.1.0", "del": "^6.0.0",
"eslint": "^6.8.0", "eslint": "^7.3.1",
"eslint-config-airbnb-base": "^14.1.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-simple-import-sort": "^5.0.3",
"fancy-log": "^1.3.3", "fancy-log": "^1.3.3",
"fastly-purge": "^1.0.1", "fastly-purge": "^1.0.1",
"git-branch": "^2.0.1", "git-branch": "^2.0.1",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-awspublish": "^4.1.1", "gulp-awspublish": "^4.1.2",
"gulp-better-rollup": "^4.0.1", "gulp-better-rollup": "^4.0.1",
"gulp-filter": "^6.0.0", "gulp-filter": "^6.0.0",
"gulp-header": "^2.0.9", "gulp-header": "^2.0.9",
"gulp-hub": "^4.2.0", "gulp-hub": "^4.2.0",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0", "gulp-imagemin": "^7.1.0",
"gulp-open": "^3.0.1", "gulp-open": "^3.0.1",
"gulp-plumber": "^1.2.1", "gulp-plumber": "^1.2.1",
"gulp-postcss": "^8.0.0", "gulp-postcss": "^9.0.0",
"gulp-rename": "^2.0.0", "gulp-rename": "^2.0.0",
"gulp-replace": "^1.0.0", "gulp-replace": "^1.0.0",
"gulp-sass": "^4.1.0", "gulp-sass": "^4.1.0",
"gulp-size": "^3.0.0", "gulp-size": "^3.0.0",
"gulp-sourcemaps": "^2.6.5", "gulp-sourcemaps": "^3.0.0",
"gulp-svgstore": "^7.0.1", "gulp-svgstore": "^7.0.1",
"gulp-terser": "^1.2.0", "gulp-terser": "^1.4.1",
"postcss": "^8.1.7",
"postcss-clean": "^1.1.0", "postcss-clean": "^1.1.0",
"postcss-custom-properties": "^9.1.1", "postcss-custom-properties": "^10.0.0",
"prettier-eslint": "^9.0.1", "prettier-eslint": "^11.0.0",
"prettier-stylelint": "^0.4.2", "prettier-stylelint": "^0.4.2",
"remark-cli": "^8.0.0", "remark-cli": "^9.0.0",
"remark-validate-links": "^10.0.0", "remark-validate-links": "^10.0.2",
"rollup": "^2.7.6", "rollup": "^2.33.1",
"rollup-plugin-babel": "^4.4.0", "rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-node-resolve": "^5.2.0",
"stylelint": "^13.3.3", "stylelint": "^13.7.2",
"stylelint-config-prettier": "^8.0.1", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-recommended": "^3.0.0", "stylelint-config-recommended": "^3.0.0",
"stylelint-config-sass-guidelines": "^7.0.0", "stylelint-config-sass-guidelines": "^7.1.0",
"stylelint-order": "^4.0.0", "stylelint-order": "^4.1.0",
"stylelint-scss": "^3.17.1", "stylelint-scss": "^3.18.0",
"stylelint-selector-bem-pattern": "^2.1.0", "stylelint-selector-bem-pattern": "^2.1.0",
"through2": "^3.0.1" "through2": "^4.0.2"
}, },
"dependencies": { "dependencies": {
"core-js": "^3.6.5", "core-js": "^3.7.0",
"custom-event-polyfill": "^1.0.7", "custom-event-polyfill": "^1.0.7",
"loadjs": "^4.2.0", "loadjs": "^4.2.0",
"rangetouch": "^2.0.1", "rangetouch": "^2.0.1",
"url-polyfill": "^1.1.8" "url-polyfill": "^1.1.12"
} }
} }
+13 -13
View File
@@ -56,7 +56,7 @@ const captions = {
if (browser.isIE && window.URL) { if (browser.isIE && window.URL) {
const elements = this.media.querySelectorAll('track'); const elements = this.media.querySelectorAll('track');
Array.from(elements).forEach(track => { Array.from(elements).forEach((track) => {
const src = track.getAttribute('src'); const src = track.getAttribute('src');
const url = parseUrl(src); const url = parseUrl(src);
@@ -66,7 +66,7 @@ const captions = {
['http:', 'https:'].includes(url.protocol) ['http:', 'https:'].includes(url.protocol)
) { ) {
fetch(src, 'blob') fetch(src, 'blob')
.then(blob => { .then((blob) => {
track.setAttribute('src', window.URL.createObjectURL(blob)); track.setAttribute('src', window.URL.createObjectURL(blob));
}) })
.catch(() => { .catch(() => {
@@ -84,7 +84,7 @@ const captions = {
// * toggled: The real captions state // * toggled: The real captions state
const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en']; const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];
const languages = dedupe(browserLanguages.map(language => language.split('-')[0])); const languages = dedupe(browserLanguages.map((language) => language.split('-')[0]));
let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase(); let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();
// Use first browser language when language is 'auto' // Use first browser language when language is 'auto'
@@ -119,13 +119,13 @@ const captions = {
const tracks = captions.getTracks.call(this, true); const tracks = captions.getTracks.call(this, true);
// Get the wanted language // Get the wanted language
const { active, language, meta, currentTrackNode } = this.captions; const { active, language, meta, currentTrackNode } = this.captions;
const languageExists = Boolean(tracks.find(track => track.language === language)); const languageExists = Boolean(tracks.find((track) => track.language === language));
// Handle tracks (add event listener and "pseudo"-default) // Handle tracks (add event listener and "pseudo"-default)
if (this.isHTML5 && this.isVideo) { if (this.isHTML5 && this.isVideo) {
tracks tracks
.filter(track => !meta.get(track)) .filter((track) => !meta.get(track))
.forEach(track => { .forEach((track) => {
this.debug.log('Track added', track); this.debug.log('Track added', track);
// Attempt to store if the original dom element was "default" // Attempt to store if the original dom element was "default"
@@ -309,19 +309,19 @@ const captions = {
// For HTML5, use cache instead of current tracks when it exists (if captions.update is false) // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)
// Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
return tracks return tracks
.filter(track => !this.isHTML5 || update || this.captions.meta.has(track)) .filter((track) => !this.isHTML5 || update || this.captions.meta.has(track))
.filter(track => ['captions', 'subtitles'].includes(track.kind)); .filter((track) => ['captions', 'subtitles'].includes(track.kind));
}, },
// Match tracks based on languages and get the first // Match tracks based on languages and get the first
findTrack(languages, force = false) { findTrack(languages, force = false) {
const tracks = captions.getTracks.call(this); const tracks = captions.getTracks.call(this);
const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default); const sortIsDefault = (track) => Number((this.captions.meta.get(track) || {}).default);
const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a)); const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));
let track; let track;
languages.every(language => { languages.every((language) => {
track = sorted.find(t => t.language === language); track = sorted.find((t) => t.language === language);
return !track; // Break iteration if there is a match return !track; // Break iteration if there is a match
}); });
@@ -383,12 +383,12 @@ const captions = {
const track = captions.getCurrentTrack.call(this); const track = captions.getCurrentTrack.call(this);
cues = Array.from((track || {}).activeCues || []) cues = Array.from((track || {}).activeCues || [])
.map(cue => cue.getCueAsHTML()) .map((cue) => cue.getCueAsHTML())
.map(getHTML); .map(getHTML);
} }
// Set new caption text // Set new caption text
const content = cues.map(cueText => cueText.trim()).join('\n'); const content = cues.map((cueText) => cueText.trim()).join('\n');
const changed = content !== this.elements.captions.innerHTML; const changed = content !== this.elements.captions.innerHTML;
if (changed) { if (changed) {
+8 -5
View File
@@ -61,7 +61,7 @@ const defaults = {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.6.2/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.6.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
@@ -200,7 +200,7 @@ const defaults = {
vimeo: { vimeo: {
sdk: 'https://player.vimeo.com/api/player.js', sdk: 'https://player.vimeo.com/api/player.js',
iframe: 'https://player.vimeo.com/video/{0}?{1}', iframe: 'https://player.vimeo.com/video/{0}?{1}',
api: 'https://vimeo.com/api/v2/video/{0}.json', api: 'https://vimeo.com/api/oembed.json?url={0}',
}, },
youtube: { youtube: {
sdk: 'https://www.youtube.com/iframe_api', sdk: 'https://www.youtube.com/iframe_api',
@@ -422,20 +422,23 @@ const defaults = {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// Custom settings from Plyr
customControls: true,
referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
// Whether the owner of the video has a Pro or Business account // Whether the owner of the video has a Pro or Business account
// (which allows us to properly hide controls without CSS hacks, etc) // (which allows us to properly hide controls without CSS hacks, etc)
premium: false, premium: false,
// Custom settings from Plyr
referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: true, // Whether to use an alternative version of YouTube without cookies
rel: 0, // No related vids rel: 0, // No related vids
showinfo: 0, // Hide info showinfo: 0, // Hide info
iv_load_policy: 3, // Hide annotations iv_load_policy: 3, // Hide annotations
modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused) modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)
// Custom settings from Plyr
customControls: true,
noCookie: false, // Whether to use an alternative version of YouTube without cookies
}, },
}; };
+25 -27
View File
@@ -179,7 +179,7 @@ const controls = {
iconPressed: null, iconPressed: null,
}; };
['element', 'icon', 'label'].forEach(key => { ['element', 'icon', 'label'].forEach((key) => {
if (Object.keys(attributes).includes(key)) { if (Object.keys(attributes).includes(key)) {
props[key] = attributes[key]; props[key] = attributes[key];
delete attributes[key]; delete attributes[key];
@@ -193,7 +193,7 @@ const controls = {
// Set class name // Set class name
if (Object.keys(attributes).includes('class')) { if (Object.keys(attributes).includes('class')) {
if (!attributes.class.split(' ').some(c => c === this.config.classNames.control)) { if (!attributes.class.split(' ').some((c) => c === this.config.classNames.control)) {
extend(attributes, { extend(attributes, {
class: `${attributes.class} ${this.config.classNames.control}`, class: `${attributes.class} ${this.config.classNames.control}`,
}); });
@@ -401,7 +401,7 @@ const controls = {
this, this,
menuItem, menuItem,
'keydown keyup', 'keydown keyup',
event => { (event) => {
// We only care about space and ⬆️ ⬇️ ➡️ // We only care about space and ⬆️ ⬇️ ➡️
if (![32, 38, 39, 40].includes(event.which)) { if (![32, 38, 39, 40].includes(event.which)) {
return; return;
@@ -448,7 +448,7 @@ const controls = {
// Enter will fire a `click` event but we still need to manage focus // Enter will fire a `click` event but we still need to manage focus
// So we bind to keyup which fires after and set focus here // So we bind to keyup which fires after and set focus here
on.call(this, menuItem, 'keyup', event => { on.call(this, menuItem, 'keyup', (event) => {
if (event.which !== 13) { if (event.which !== 13) {
return; return;
} }
@@ -493,8 +493,8 @@ const controls = {
// Ensure exclusivity // Ensure exclusivity
if (check) { if (check) {
Array.from(menuItem.parentNode.children) Array.from(menuItem.parentNode.children)
.filter(node => matches(node, '[role="menuitemradio"]')) .filter((node) => matches(node, '[role="menuitemradio"]'))
.forEach(node => node.setAttribute('aria-checked', 'false')); .forEach((node) => node.setAttribute('aria-checked', 'false'));
} }
menuItem.setAttribute('aria-checked', check ? 'true' : 'false'); menuItem.setAttribute('aria-checked', check ? 'true' : 'false');
@@ -504,7 +504,7 @@ const controls = {
this.listeners.bind( this.listeners.bind(
menuItem, menuItem,
'click keyup', 'click keyup',
event => { (event) => {
if (is.keyboardEvent(event) && event.which !== 32) { if (is.keyboardEvent(event) && event.which !== 32) {
return; return;
} }
@@ -698,7 +698,7 @@ const controls = {
} }
const visible = `${this.config.classNames.tooltip}--visible`; const visible = `${this.config.classNames.tooltip}--visible`;
const toggle = show => toggleClass(this.elements.display.seekTooltip, visible, show); const toggle = (show) => toggleClass(this.elements.display.seekTooltip, visible, show);
// Hide on touch // Hide on touch
if (this.touch) { if (this.touch) {
@@ -894,7 +894,7 @@ const controls = {
// Set options if passed and filter based on uniqueness and config // Set options if passed and filter based on uniqueness and config
if (is.array(options)) { if (is.array(options)) {
this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality)); this.options.quality = dedupe(options).filter((quality) => this.config.quality.options.includes(quality));
} }
// Toggle the pane and tab // Toggle the pane and tab
@@ -913,7 +913,7 @@ const controls = {
} }
// Get the badge HTML for HD, 4K etc // Get the badge HTML for HD, 4K etc
const getBadge = quality => { const getBadge = (quality) => {
const label = i18n.get(`qualityBadge.${quality}`, this.config); const label = i18n.get(`qualityBadge.${quality}`, this.config);
if (!label.length) { if (!label.length) {
@@ -929,7 +929,7 @@ const controls = {
const sorting = this.config.quality.options; const sorting = this.config.quality.options;
return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
}) })
.forEach(quality => { .forEach((quality) => {
controls.createMenuItem.call(this, { controls.createMenuItem.call(this, {
value: quality, value: quality,
list, list,
@@ -1052,7 +1052,7 @@ const controls = {
const list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); const list = this.elements.settings.panels.speed.querySelector('[role="menu"]');
// Filter out invalid speeds // Filter out invalid speeds
this.options.speed = this.options.speed.filter(o => o >= this.minimumSpeed && o <= this.maximumSpeed); this.options.speed = this.options.speed.filter((o) => o >= this.minimumSpeed && o <= this.maximumSpeed);
// Toggle the pane and tab // Toggle the pane and tab
const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1; const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
@@ -1070,7 +1070,7 @@ const controls = {
} }
// Create items // Create items
this.options.speed.forEach(speed => { this.options.speed.forEach((speed) => {
controls.createMenuItem.call(this, { controls.createMenuItem.call(this, {
value: speed, value: speed,
list, list,
@@ -1085,7 +1085,7 @@ const controls = {
// Check if we need to hide/show the settings menu // Check if we need to hide/show the settings menu
checkMenu() { checkMenu() {
const { buttons } = this.elements.settings; const { buttons } = this.elements.settings;
const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden); const visible = !is.empty(buttons) && Object.values(buttons).some((button) => !button.hidden);
toggleHidden(this.elements.settings.menu, !visible); toggleHidden(this.elements.settings.menu, !visible);
}, },
@@ -1099,7 +1099,7 @@ const controls = {
let target = pane; let target = pane;
if (!is.element(target)) { if (!is.element(target)) {
target = Object.values(this.elements.settings.panels).find(p => !p.hidden); target = Object.values(this.elements.settings.panels).find((p) => !p.hidden);
} }
const firstItem = target.querySelector('[role^="menuitem"]'); const firstItem = target.querySelector('[role^="menuitem"]');
@@ -1191,7 +1191,7 @@ const controls = {
// Hide all other panels // Hide all other panels
const container = target.parentNode; const container = target.parentNode;
const current = Array.from(container.children).find(node => !node.hidden); const current = Array.from(container.children).find((node) => !node.hidden);
// If we can do fancy animations, we'll animate the height/width // If we can do fancy animations, we'll animate the height/width
if (support.transitions && !support.reducedMotion) { if (support.transitions && !support.reducedMotion) {
@@ -1203,7 +1203,7 @@ const controls = {
const size = controls.getMenuSize.call(this, target); const size = controls.getMenuSize.call(this, target);
// Restore auto height/width // Restore auto height/width
const restore = event => { const restore = (event) => {
// We're only bothered about height and width on the container // We're only bothered about height and width on the container
if (event.target !== container || !['width', 'height'].includes(event.propertyName)) { if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {
return; return;
@@ -1275,7 +1275,7 @@ const controls = {
const defaultAttributes = { class: 'plyr__controls__item' }; const defaultAttributes = { class: 'plyr__controls__item' };
// Loop through controls in order // Loop through controls in order
dedupe(is.array(this.config.controls) ? this.config.controls: []).forEach(control => { dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach((control) => {
// Restart button // Restart button
if (control === 'restart') { if (control === 'restart') {
container.appendChild(createButton.call(this, 'restart', defaultAttributes)); container.appendChild(createButton.call(this, 'restart', defaultAttributes));
@@ -1437,7 +1437,7 @@ const controls = {
this.elements.settings.panels.home = home; this.elements.settings.panels.home = home;
// Build the menu items // Build the menu items
this.config.settings.forEach(type => { this.config.settings.forEach((type) => {
// TODO: bundle this with the createMenuItem helper and bindings // TODO: bundle this with the createMenuItem helper and bindings
const menuItem = createElement( const menuItem = createElement(
'button', 'button',
@@ -1510,7 +1510,7 @@ const controls = {
this, this,
pane, pane,
'keydown', 'keydown',
event => { (event) => {
// We only care about <- // We only care about <-
if (event.which !== 37) { if (event.which !== 37) {
return; return;
@@ -1661,7 +1661,7 @@ const controls = {
} }
// Replace props with their value // Replace props with their value
const replace = input => { const replace = (input) => {
let result = input; let result = input;
Object.entries(props).forEach(([key, value]) => { Object.entries(props).forEach(([key, value]) => {
@@ -1702,7 +1702,7 @@ const controls = {
// Add pressed property to buttons // Add pressed property to buttons
if (!is.empty(this.elements.buttons)) { if (!is.empty(this.elements.buttons)) {
const addProperty = button => { const addProperty = (button) => {
const className = this.config.classNames.controlPressed; const className = this.config.classNames.controlPressed;
Object.defineProperty(button, 'pressed', { Object.defineProperty(button, 'pressed', {
enumerable: true, enumerable: true,
@@ -1718,11 +1718,9 @@ const controls = {
// Toggle classname when pressed property is set // Toggle classname when pressed property is set
Object.values(this.elements.buttons) Object.values(this.elements.buttons)
.filter(Boolean) .filter(Boolean)
.forEach(button => { .forEach((button) => {
if (is.array(button) || is.nodeList(button)) { if (is.array(button) || is.nodeList(button)) {
Array.from(button) Array.from(button).filter(Boolean).forEach(addProperty);
.filter(Boolean)
.forEach(addProperty);
} else { } else {
addProperty(button); addProperty(button);
} }
@@ -1740,7 +1738,7 @@ const controls = {
const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`; const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;
const labels = getElements.call(this, selector); const labels = getElements.call(this, selector);
Array.from(labels).forEach(label => { Array.from(labels).forEach((label) => {
toggleClass(label, this.config.classNames.hidden, false); toggleClass(label, this.config.classNames.hidden, false);
toggleClass(label, this.config.classNames.tooltip, true); toggleClass(label, this.config.classNames.tooltip, true);
}); });
+9 -7
View File
@@ -5,7 +5,7 @@
// ========================================================================== // ==========================================================================
import browser from './utils/browser'; import browser from './utils/browser';
import { closest,getElements, hasClass, toggleClass } from './utils/elements'; import { closest, getElements, hasClass, toggleClass } from './utils/elements';
import { on, triggerEvent } from './utils/events'; import { on, triggerEvent } from './utils/events';
import is from './utils/is'; import is from './utils/is';
import { silencePromise } from './utils/promise'; import { silencePromise } from './utils/promise';
@@ -43,17 +43,17 @@ class Fullscreen {
); );
// Fullscreen toggle on double click // Fullscreen toggle on double click
on.call(this.player, this.player.elements.container, 'dblclick', event => { on.call(this.player, this.player.elements.container, 'dblclick', (event) => {
// Ignore double click in controls // Ignore double click in controls
if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) { if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
return; return;
} }
this.toggle(); this.player.listeners.proxy(event, this.toggle, 'fullscreen');
}); });
// Tap focus when in fullscreen // Tap focus when in fullscreen
on.call(this, this.player.elements.container, 'keydown', event => this.trapFocus(event)); on.call(this, this.player.elements.container, 'keydown', (event) => this.trapFocus(event));
// Update the UI // Update the UI
this.update(); this.update();
@@ -85,7 +85,7 @@ class Fullscreen {
let value = ''; let value = '';
const prefixes = ['webkit', 'moz', 'ms']; const prefixes = ['webkit', 'moz', 'ms'];
prefixes.some(pre => { prefixes.some((pre) => {
if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) { if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {
value = pre; value = pre;
return true; return true;
@@ -145,8 +145,10 @@ class Fullscreen {
button.pressed = this.active; button.pressed = this.active;
} }
// Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up
const target = this.target === this.player.media ? this.target : this.player.elements.container;
// Trigger an event // Trigger an event
triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
} }
toggleFallback(toggle = false) { toggleFallback(toggle = false) {
@@ -189,7 +191,7 @@ class Fullscreen {
} else if (this.cleanupViewport) { } else if (this.cleanupViewport) {
viewport.content = viewport.content viewport.content = viewport.content
.split(',') .split(',')
.filter(part => part.trim() !== property) .filter((part) => part.trim() !== property)
.join(','); .join(',');
} }
} }
+4 -4
View File
@@ -18,7 +18,7 @@ const html5 = {
const sources = Array.from(this.media.querySelectorAll('source')); const sources = Array.from(this.media.querySelectorAll('source'));
// Filter out unsupported sources (if type is specified) // Filter out unsupported sources (if type is specified)
return sources.filter(source => { return sources.filter((source) => {
const type = source.getAttribute('type'); const type = source.getAttribute('type');
if (is.empty(type)) { if (is.empty(type)) {
@@ -39,7 +39,7 @@ const html5 = {
// Get sizes from <source> elements // Get sizes from <source> elements
return html5.getSources return html5.getSources
.call(this) .call(this)
.map(source => Number(source.getAttribute('size'))) .map((source) => Number(source.getAttribute('size')))
.filter(Boolean); .filter(Boolean);
}, },
@@ -63,7 +63,7 @@ const html5 = {
get() { get() {
// Get sources // Get sources
const sources = html5.getSources.call(player); const sources = html5.getSources.call(player);
const source = sources.find(s => s.getAttribute('src') === player.source); const source = sources.find((s) => s.getAttribute('src') === player.source);
// Return size, if match is found // Return size, if match is found
return source && Number(source.getAttribute('size')); return source && Number(source.getAttribute('size'));
@@ -80,7 +80,7 @@ const html5 = {
// Get sources // Get sources
const sources = html5.getSources.call(player); const sources = html5.getSources.call(player);
// Get first match for requested size // Get first match for requested size
const source = sources.find(s => Number(s.getAttribute('size')) === input); const source = sources.find((s) => Number(s.getAttribute('size')) === input);
// No matching source found // No matching source found
if (!source) { if (!source) {
+61 -38
View File
@@ -277,7 +277,7 @@ class Listeners {
player, player,
elements.container, elements.container,
'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',
event => { (event) => {
const { controls: controlsElement } = elements; const { controls: controlsElement } = elements;
// Remove button states for fullscreen // Remove button states for fullscreen
@@ -319,7 +319,7 @@ class Listeners {
}; };
// Resize on fullscreen change // Resize on fullscreen change
const setPlayerSize = measure => { const setPlayerSize = (measure) => {
// If we don't need to measure the viewport // If we don't need to measure the viewport
if (!measure) { if (!measure) {
return setAspectRatio.call(player); return setAspectRatio.call(player);
@@ -336,7 +336,7 @@ class Listeners {
timers.resized = setTimeout(setPlayerSize, 50); timers.resized = setTimeout(setPlayerSize, 50);
}; };
on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => { on.call(player, elements.container, 'enterfullscreen exitfullscreen', (event) => {
const { target, usingNative } = player.fullscreen; const { target, usingNative } = player.fullscreen;
// Ignore events not from target // Ignore events not from target
@@ -356,6 +356,11 @@ class Listeners {
// Set Vimeo gutter // Set Vimeo gutter
setGutter(ratio, padding, isEnter); setGutter(ratio, padding, isEnter);
// Horrible hack for Safari 14 not repainting properly on entering fullscreen
if (isEnter) {
setTimeout(() => repaint(elements.container), 100);
}
// If not using native browser fullscreen API, we need to check for resizes of viewport // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@@ -373,10 +378,10 @@ class Listeners {
const { elements } = player; const { elements } = player;
// Time change on media // Time change on media
on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event)); on.call(player, player.media, 'timeupdate seeking seeked', (event) => controls.timeUpdate.call(player, event));
// Display duration // Display duration
on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event => on.call(player, player.media, 'durationchange loadeddata loadedmetadata', (event) =>
controls.durationUpdate.call(player, event), controls.durationUpdate.call(player, event),
); );
@@ -393,20 +398,20 @@ class Listeners {
}); });
// Check for buffer progress // Check for buffer progress
on.call(player, player.media, 'progress playing seeking seeked', event => on.call(player, player.media, 'progress playing seeking seeked', (event) =>
controls.updateProgress.call(player, event), controls.updateProgress.call(player, event),
); );
// Handle volume changes // Handle volume changes
on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event)); on.call(player, player.media, 'volumechange', (event) => controls.updateVolume.call(player, event));
// Handle play/pause // Handle play/pause
on.call(player, player.media, 'playing play pause ended emptied timeupdate', event => on.call(player, player.media, 'playing play pause ended emptied timeupdate', (event) =>
ui.checkPlaying.call(player, event), ui.checkPlaying.call(player, event),
); );
// Loading state // Loading state
on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event)); on.call(player, player.media, 'waiting canplay seeked playing', (event) => ui.checkLoading.call(player, event));
// Click video // Click video
if (player.supported.ui && player.config.clickToPlay && !player.isAudio) { if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {
@@ -419,7 +424,7 @@ class Listeners {
} }
// On click play, pause or restart // On click play, pause or restart
on.call(player, elements.container, 'click', event => { on.call(player, elements.container, 'click', (event) => {
const targets = [elements.container, wrapper]; const targets = [elements.container, wrapper];
// Ignore if click if not container or in video wrapper // Ignore if click if not container or in video wrapper
@@ -459,7 +464,7 @@ class Listeners {
player, player,
elements.wrapper, elements.wrapper,
'contextmenu', 'contextmenu',
event => { (event) => {
event.preventDefault(); event.preventDefault();
}, },
false, false,
@@ -485,7 +490,7 @@ class Listeners {
}); });
// Quality change // Quality change
on.call(player, player.media, 'qualitychange', event => { on.call(player, player.media, 'qualitychange', (event) => {
// Update UI // Update UI
controls.updateSetting.call(player, 'quality', null, event.detail.quality); controls.updateSetting.call(player, 'quality', null, event.detail.quality);
}); });
@@ -499,7 +504,7 @@ class Listeners {
// Bubble up key events for Edge // Bubble up key events for Edge
const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' '); const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');
on.call(player, player.media, proxyEvents, event => { on.call(player, player.media, proxyEvents, (event) => {
let { detail = {} } = event; let { detail = {} } = event;
// Get error details from media // Get error details from media
@@ -539,7 +544,7 @@ class Listeners {
player, player,
element, element,
type, type,
event => this.proxy(event, defaultHandler, customHandlerKey), (event) => this.proxy(event, defaultHandler, customHandlerKey),
passive && !hasCustomHandler, passive && !hasCustomHandler,
); );
} }
@@ -553,7 +558,7 @@ class Listeners {
// Play/pause toggle // Play/pause toggle
if (elements.buttons.play) { if (elements.buttons.play) {
Array.from(elements.buttons.play).forEach(button => { Array.from(elements.buttons.play).forEach((button) => {
this.bind( this.bind(
button, button,
'click', 'click',
@@ -569,10 +574,28 @@ class Listeners {
this.bind(elements.buttons.restart, 'click', player.restart, 'restart'); this.bind(elements.buttons.restart, 'click', player.restart, 'restart');
// Rewind // Rewind
this.bind(elements.buttons.rewind, 'click', player.rewind, 'rewind'); this.bind(
elements.buttons.rewind,
'click',
() => {
// Record seek time so we can prevent hiding controls for a few seconds after rewind
player.lastSeekTime = Date.now();
player.rewind();
},
'rewind',
);
// Rewind // Rewind
this.bind(elements.buttons.fastForward, 'click', player.forward, 'fastForward'); this.bind(
elements.buttons.fastForward,
'click',
() => {
// Record seek time so we can prevent hiding controls for a few seconds after fast forward
player.lastSeekTime = Date.now();
player.forward();
},
'fastForward',
);
// Mute toggle // Mute toggle
this.bind( this.bind(
@@ -624,7 +647,7 @@ class Listeners {
this.bind( this.bind(
elements.buttons.settings, elements.buttons.settings,
'click', 'click',
event => { (event) => {
// Prevent the document click listener closing the menu // Prevent the document click listener closing the menu
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@@ -641,7 +664,7 @@ class Listeners {
this.bind( this.bind(
elements.buttons.settings, elements.buttons.settings,
'keyup', 'keyup',
event => { (event) => {
const code = event.which; const code = event.which;
// We only care about space and return // We only care about space and return
@@ -669,21 +692,21 @@ class Listeners {
); );
// Escape closes menu // Escape closes menu
this.bind(elements.settings.menu, 'keydown', event => { this.bind(elements.settings.menu, 'keydown', (event) => {
if (event.which === 27) { if (event.which === 27) {
controls.toggleMenu.call(player, event); controls.toggleMenu.call(player, event);
} }
}); });
// Set range input alternative "value", which matches the tooltip time (#954) // Set range input alternative "value", which matches the tooltip time (#954)
this.bind(elements.inputs.seek, 'mousedown mousemove', event => { this.bind(elements.inputs.seek, 'mousedown mousemove', (event) => {
const rect = elements.progress.getBoundingClientRect(); const rect = elements.progress.getBoundingClientRect();
const percent = (100 / rect.width) * (event.pageX - rect.left); const percent = (100 / rect.width) * (event.pageX - rect.left);
event.currentTarget.setAttribute('seek-value', percent); event.currentTarget.setAttribute('seek-value', percent);
}); });
// Pause while seeking // Pause while seeking
this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => { this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', (event) => {
const seek = event.currentTarget; const seek = event.currentTarget;
const code = event.keyCode ? event.keyCode : event.which; const code = event.keyCode ? event.keyCode : event.which;
const attribute = 'play-on-seeked'; const attribute = 'play-on-seeked';
@@ -715,14 +738,14 @@ class Listeners {
// it takes over further interactions on the page. This is a hack // it takes over further interactions on the page. This is a hack
if (browser.isIos) { if (browser.isIos) {
const inputs = getElements.call(player, 'input[type="range"]'); const inputs = getElements.call(player, 'input[type="range"]');
Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target))); Array.from(inputs).forEach((input) => this.bind(input, inputEvent, (event) => repaint(event.target)));
} }
// Seek // Seek
this.bind( this.bind(
elements.inputs.seek, elements.inputs.seek,
inputEvent, inputEvent,
event => { (event) => {
const seek = event.currentTarget; const seek = event.currentTarget;
// If it exists, use seek-value instead of "value" for consistency with tooltip time (#954) // If it exists, use seek-value instead of "value" for consistency with tooltip time (#954)
let seekTo = seek.getAttribute('seek-value'); let seekTo = seek.getAttribute('seek-value');
@@ -739,13 +762,13 @@ class Listeners {
); );
// Seek tooltip // Seek tooltip
this.bind(elements.progress, 'mouseenter mouseleave mousemove', event => this.bind(elements.progress, 'mouseenter mouseleave mousemove', (event) =>
controls.updateSeekTooltip.call(player, event), controls.updateSeekTooltip.call(player, event),
); );
// Preview thumbnails plugin // Preview thumbnails plugin
// TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this
this.bind(elements.progress, 'mousemove touchmove', event => { this.bind(elements.progress, 'mousemove touchmove', (event) => {
const { previewThumbnails } = player; const { previewThumbnails } = player;
if (previewThumbnails && previewThumbnails.loaded) { if (previewThumbnails && previewThumbnails.loaded) {
@@ -763,7 +786,7 @@ class Listeners {
}); });
// Show scrubbing preview // Show scrubbing preview
this.bind(elements.progress, 'mousedown touchstart', event => { this.bind(elements.progress, 'mousedown touchstart', (event) => {
const { previewThumbnails } = player; const { previewThumbnails } = player;
if (previewThumbnails && previewThumbnails.loaded) { if (previewThumbnails && previewThumbnails.loaded) {
@@ -771,7 +794,7 @@ class Listeners {
} }
}); });
this.bind(elements.progress, 'mouseup touchend', event => { this.bind(elements.progress, 'mouseup touchend', (event) => {
const { previewThumbnails } = player; const { previewThumbnails } = player;
if (previewThumbnails && previewThumbnails.loaded) { if (previewThumbnails && previewThumbnails.loaded) {
@@ -781,8 +804,8 @@ class Listeners {
// Polyfill for lower fill in <input type="range"> for webkit // Polyfill for lower fill in <input type="range"> for webkit
if (browser.isWebkit) { if (browser.isWebkit) {
Array.from(getElements.call(player, 'input[type="range"]')).forEach(element => { Array.from(getElements.call(player, 'input[type="range"]')).forEach((element) => {
this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target)); this.bind(element, 'input', (event) => controls.updateRangeFill.call(player, event.target));
}); });
} }
@@ -805,30 +828,30 @@ class Listeners {
this.bind( this.bind(
elements.inputs.volume, elements.inputs.volume,
inputEvent, inputEvent,
event => { (event) => {
player.volume = event.target.value; player.volume = event.target.value;
}, },
'volume', 'volume',
); );
// Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting) // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(elements.controls, 'mouseenter mouseleave', event => { this.bind(elements.controls, 'mouseenter mouseleave', (event) => {
elements.controls.hover = !player.touch && event.type === 'mouseenter'; elements.controls.hover = !player.touch && event.type === 'mouseenter';
}); });
// Also update controls.hover state for any non-player children of fullscreen element (as above) // Also update controls.hover state for any non-player children of fullscreen element (as above)
if (elements.fullscreen) { if (elements.fullscreen) {
Array.from(elements.fullscreen.children) Array.from(elements.fullscreen.children)
.filter(c => !c.contains(elements.container)) .filter((c) => !c.contains(elements.container))
.forEach(child => { .forEach((child) => {
this.bind(child, 'mouseenter mouseleave', event => { this.bind(child, 'mouseenter mouseleave', (event) => {
elements.controls.hover = !player.touch && event.type === 'mouseenter'; elements.controls.hover = !player.touch && event.type === 'mouseenter';
}); });
}); });
} }
// Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => { this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', (event) => {
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
}); });
@@ -861,12 +884,12 @@ class Listeners {
this.bind( this.bind(
elements.inputs.volume, elements.inputs.volume,
'wheel', 'wheel',
event => { (event) => {
// Detect "natural" scroll - suppored on OS X Safari only // Detect "natural" scroll - suppored on OS X Safari only
// Other browsers on OS X will be inverted until support improves // Other browsers on OS X will be inverted until support improves
const inverted = event.webkitDirectionInvertedFromDevice; const inverted = event.webkitDirectionInvertedFromDevice;
// Get delta from event. Invert if `inverted` is true // Get delta from event. Invert if `inverted` is true
const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value)); const [x, y] = [event.deltaX, -event.deltaY].map((value) => (inverted ? -value : value));
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta) // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y); const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
+1
View File
@@ -41,6 +41,7 @@ const media = {
// Poster image container // Poster image container
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster, class: this.config.classNames.poster,
hidden: '',
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
+10 -10
View File
@@ -15,7 +15,7 @@ import { silencePromise } from '../utils/promise';
import { formatTime } from '../utils/time'; import { formatTime } from '../utils/time';
import { buildUrlParams } from '../utils/urls'; import { buildUrlParams } from '../utils/urls';
const destroy = instance => { const destroy = (instance) => {
// Destroy our adsManager // Destroy our adsManager
if (instance.manager) { if (instance.manager) {
instance.manager.destroy(); instance.manager.destroy();
@@ -179,10 +179,10 @@ class Ads {
// Listen and respond to ads loaded and error events // Listen and respond to ads loaded and error events
this.loader.addEventListener( this.loader.addEventListener(
google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
event => this.onAdsManagerLoaded(event), (event) => this.onAdsManagerLoaded(event),
false, false,
); );
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false); this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error), false);
// Request video ads to be pre-loaded // Request video ads to be pre-loaded
this.requestAds(); this.requestAds();
@@ -264,11 +264,11 @@ class Ads {
// Add listeners to the required events // Add listeners to the required events
// Advertisement error events // Advertisement error events
this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error)); this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error));
// Advertisement regular events // Advertisement regular events
Object.keys(google.ima.AdEvent.Type).forEach(type => { Object.keys(google.ima.AdEvent.Type).forEach((type) => {
this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e)); this.manager.addEventListener(google.ima.AdEvent.Type[type], (e) => this.onAdEvent(e));
}); });
// Resolve our adsManager // Resolve our adsManager
@@ -278,7 +278,7 @@ class Ads {
addCuePoints() { addCuePoints() {
// Add advertisement cue's within the time line if available // Add advertisement cue's within the time line if available
if (!is.empty(this.cuePoints)) { if (!is.empty(this.cuePoints)) {
this.cuePoints.forEach(cuePoint => { this.cuePoints.forEach((cuePoint) => {
if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) { if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {
const seekElement = this.player.elements.progress; const seekElement = this.player.elements.progress;
@@ -310,7 +310,7 @@ class Ads {
const adData = event.getAdData(); const adData = event.getAdData();
// Proxy event // Proxy event
const dispatchEvent = type => { const dispatchEvent = (type) => {
triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`); triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);
}; };
@@ -565,7 +565,7 @@ class Ads {
} }
// Re-set our adsManager promises // Re-set our adsManager promises
this.managerPromise = new Promise(resolve => { this.managerPromise = new Promise((resolve) => {
this.on('loaded', resolve); this.on('loaded', resolve);
this.player.debug.log(this.manager); this.player.debug.log(this.manager);
}); });
@@ -586,7 +586,7 @@ class Ads {
const handlers = this.events[event]; const handlers = this.events[event];
if (is.array(handlers)) { if (is.array(handlers)) {
handlers.forEach(handler => { handlers.forEach((handler) => {
if (is.function(handler)) { if (is.function(handler)) {
handler.apply(this, args); handler.apply(this, args);
} }
+12 -12
View File
@@ -5,15 +5,15 @@ import is from '../utils/is';
import { formatTime } from '../utils/time'; import { formatTime } from '../utils/time';
// Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg" // Arg: vttDataString example: "WEBVTT\n\n1\n00:00:05.000 --> 00:00:10.000\n1080p-00001.jpg"
const parseVtt = vttDataString => { const parseVtt = (vttDataString) => {
const processedList = []; const processedList = [];
const frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/); const frames = vttDataString.split(/\r\n\r\n|\n\n|\r\r/);
frames.forEach(frame => { frames.forEach((frame) => {
const result = {}; const result = {};
const lines = frame.split(/\r\n|\n|\r/); const lines = frame.split(/\r\n|\n|\r/);
lines.forEach(line => { lines.forEach((line) => {
if (!is.number(result.startTime)) { if (!is.number(result.startTime)) {
// The line with start and end times on it is the first line of interest // The line with start and end times on it is the first line of interest
const matchTimes = line.match( const matchTimes = line.match(
@@ -130,7 +130,7 @@ class PreviewThumbnails {
// Download VTT files and parse them // Download VTT files and parse them
getThumbnails() { getThumbnails() {
return new Promise(resolve => { return new Promise((resolve) => {
const { src } = this.player.config.previewThumbnails; const { src } = this.player.config.previewThumbnails;
if (is.empty(src)) { if (is.empty(src)) {
@@ -149,7 +149,7 @@ class PreviewThumbnails {
// Via callback() // Via callback()
if (is.function(src)) { if (is.function(src)) {
src(thumbnails => { src((thumbnails) => {
this.thumbnails = thumbnails; this.thumbnails = thumbnails;
sortAndResolve(); sortAndResolve();
}); });
@@ -159,7 +159,7 @@ class PreviewThumbnails {
// If string, convert into single-element list // If string, convert into single-element list
const urls = is.string(src) ? [src] : src; const urls = is.string(src) ? [src] : src;
// Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails
const promises = urls.map(u => this.getThumbnail(u)); const promises = urls.map((u) => this.getThumbnail(u));
// Resolve // Resolve
Promise.all(promises).then(sortAndResolve); Promise.all(promises).then(sortAndResolve);
} }
@@ -168,8 +168,8 @@ class PreviewThumbnails {
// Process individual VTT file // Process individual VTT file
getThumbnail(url) { getThumbnail(url) {
return new Promise(resolve => { return new Promise((resolve) => {
fetch(url).then(response => { fetch(url).then((response) => {
const thumbnail = { const thumbnail = {
frames: parseVtt(response), frames: parseVtt(response),
height: null, height: null,
@@ -360,7 +360,7 @@ class PreviewThumbnails {
// Find the desired thumbnail index // Find the desired thumbnail index
// TODO: Handle a video longer than the thumbs where thumbNum is null // TODO: Handle a video longer than the thumbs where thumbNum is null
const thumbNum = this.thumbnails[0].frames.findIndex( const thumbNum = this.thumbnails[0].frames.findIndex(
frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime, (frame) => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,
); );
const hasThumb = thumbNum >= 0; const hasThumb = thumbNum >= 0;
let qualityIndex = 0; let qualityIndex = 0;
@@ -454,7 +454,7 @@ class PreviewThumbnails {
// Remove all preview images that aren't the designated current image // Remove all preview images that aren't the designated current image
removeOldImages(currentImage) { removeOldImages(currentImage) {
// Get a list of all images, convert it from a DOM list to an array // Get a list of all images, convert it from a DOM list to an array
Array.from(this.currentImageContainer.children).forEach(image => { Array.from(this.currentImageContainer.children).forEach((image) => {
if (image.tagName.toLowerCase() !== 'img') { if (image.tagName.toLowerCase() !== 'img') {
return; return;
} }
@@ -481,7 +481,7 @@ class PreviewThumbnails {
// Preload images before and after the current one. Only if the user is still hovering/seeking the same frame // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame
// This will only preload the lowest quality // This will only preload the lowest quality
preloadNearby(thumbNum, forward = true) { preloadNearby(thumbNum, forward = true) {
return new Promise(resolve => { return new Promise((resolve) => {
setTimeout(() => { setTimeout(() => {
const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text; const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;
@@ -496,7 +496,7 @@ class PreviewThumbnails {
let foundOne = false; let foundOne = false;
thumbnailsClone.forEach(frame => { thumbnailsClone.forEach((frame) => {
const newThumbFilename = frame.text; const newThumbFilename = frame.text;
if (newThumbFilename !== oldThumbFilename) { if (newThumbFilename !== oldThumbFilename) {
+33 -33
View File
@@ -58,7 +58,7 @@ const vimeo = {
.then(() => { .then(() => {
vimeo.ready.call(player); vimeo.ready.call(player);
}) })
.catch(error => { .catch((error) => {
player.debug.warn('Vimeo SDK (player.js) failed to load', error); player.debug.warn('Vimeo SDK (player.js) failed to load', error);
}); });
} else { } else {
@@ -112,31 +112,29 @@ const vimeo = {
} }
// Inject the package // Inject the package
const { poster } = player; if (premium || !config.customControls) {
if (premium) { iframe.setAttribute('data-poster', player.poster);
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media); player.media = replaceElement(iframe, player.media);
} else { } else {
const wrapper = createElement('div', { class: player.config.classNames.embedContainer, 'data-poster': poster }); const wrapper = createElement('div', {
class: player.config.classNames.embedContainer,
'data-poster': player.poster,
});
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); player.media = replaceElement(wrapper, player.media);
} }
// Get poster image // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(response => { if (!config.customControls) {
if (is.empty(response)) { fetch(format(player.config.urls.vimeo.api, src)).then((response) => {
return; if (is.empty(response) || !response.thumbnail_url) {
} return;
}
// Get the URL for thumbnail // Set and show poster
const url = new URL(response[0].thumbnail_large); ui.setPoster.call(player, response.thumbnail_url).catch(() => {});
});
// Get original image }
url.pathname = `${url.pathname.split('_')[0]}.jpg`;
// Set and show poster
ui.setPoster.call(player, url.href).catch(() => {});
});
// Setup instance // Setup instance
// https://github.com/vimeo/player.js // https://github.com/vimeo/player.js
@@ -269,11 +267,11 @@ const vimeo = {
let currentSrc; let currentSrc;
player.embed player.embed
.getVideoUrl() .getVideoUrl()
.then(value => { .then((value) => {
currentSrc = value; currentSrc = value;
controls.setDownloadUrl.call(player); controls.setDownloadUrl.call(player);
}) })
.catch(error => { .catch((error) => {
this.debug.warn(error); this.debug.warn(error);
}); });
@@ -291,49 +289,49 @@ const vimeo = {
}); });
// Set aspect ratio based on video size // Set aspect ratio based on video size
Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => { Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then((dimensions) => {
const [width, height] = dimensions; const [width, height] = dimensions;
player.embed.ratio = [width, height]; player.embed.ratio = [width, height];
setAspectRatio.call(this); setAspectRatio.call(this);
}); });
// Set autopause // Set autopause
player.embed.setAutopause(player.config.autopause).then(state => { player.embed.setAutopause(player.config.autopause).then((state) => {
player.config.autopause = state; player.config.autopause = state;
}); });
// Get title // Get title
player.embed.getVideoTitle().then(title => { player.embed.getVideoTitle().then((title) => {
player.config.title = title; player.config.title = title;
ui.setTitle.call(this); ui.setTitle.call(this);
}); });
// Get current time // Get current time
player.embed.getCurrentTime().then(value => { player.embed.getCurrentTime().then((value) => {
currentTime = value; currentTime = value;
triggerEvent.call(player, player.media, 'timeupdate'); triggerEvent.call(player, player.media, 'timeupdate');
}); });
// Get duration // Get duration
player.embed.getDuration().then(value => { player.embed.getDuration().then((value) => {
player.media.duration = value; player.media.duration = value;
triggerEvent.call(player, player.media, 'durationchange'); triggerEvent.call(player, player.media, 'durationchange');
}); });
// Get captions // Get captions
player.embed.getTextTracks().then(tracks => { player.embed.getTextTracks().then((tracks) => {
player.media.textTracks = tracks; player.media.textTracks = tracks;
captions.setup.call(player); captions.setup.call(player);
}); });
player.embed.on('cuechange', ({ cues = [] }) => { player.embed.on('cuechange', ({ cues = [] }) => {
const strippedCues = cues.map(cue => stripHTML(cue.text)); const strippedCues = cues.map((cue) => stripHTML(cue.text));
captions.updateCues.call(player, strippedCues); captions.updateCues.call(player, strippedCues);
}); });
player.embed.on('loaded', () => { player.embed.on('loaded', () => {
// Assure state and events are updated on autoplay // Assure state and events are updated on autoplay
player.embed.getPaused().then(paused => { player.embed.getPaused().then((paused) => {
assurePlaybackState.call(player, !paused); assurePlaybackState.call(player, !paused);
if (!paused) { if (!paused) {
triggerEvent.call(player, player.media, 'playing'); triggerEvent.call(player, player.media, 'playing');
@@ -366,13 +364,13 @@ const vimeo = {
assurePlaybackState.call(player, false); assurePlaybackState.call(player, false);
}); });
player.embed.on('timeupdate', data => { player.embed.on('timeupdate', (data) => {
player.media.seeking = false; player.media.seeking = false;
currentTime = data.seconds; currentTime = data.seconds;
triggerEvent.call(player, player.media, 'timeupdate'); triggerEvent.call(player, player.media, 'timeupdate');
}); });
player.embed.on('progress', data => { player.embed.on('progress', (data) => {
player.media.buffered = data.percent; player.media.buffered = data.percent;
triggerEvent.call(player, player.media, 'progress'); triggerEvent.call(player, player.media, 'progress');
@@ -383,7 +381,7 @@ const vimeo = {
// Get duration as if we do it before load, it gives an incorrect value // Get duration as if we do it before load, it gives an incorrect value
// https://github.com/sampotts/plyr/issues/891 // https://github.com/sampotts/plyr/issues/891
player.embed.getDuration().then(value => { player.embed.getDuration().then((value) => {
if (value !== player.media.duration) { if (value !== player.media.duration) {
player.media.duration = value; player.media.duration = value;
triggerEvent.call(player, player.media, 'durationchange'); triggerEvent.call(player, player.media, 'durationchange');
@@ -401,13 +399,15 @@ const vimeo = {
triggerEvent.call(player, player.media, 'ended'); triggerEvent.call(player, player.media, 'ended');
}); });
player.embed.on('error', detail => { player.embed.on('error', (detail) => {
player.media.error = detail; player.media.error = detail;
triggerEvent.call(player, player.media, 'error'); triggerEvent.call(player, player.media, 'error');
}); });
// Rebuild UI // Rebuild UI
setTimeout(() => ui.build.call(player), 0); if (config.customControls) {
setTimeout(() => ui.build.call(player), 0);
}
}, },
}; };
+38 -31
View File
@@ -70,7 +70,7 @@ const youtube = {
}; };
// Load the SDK // Load the SDK
loadScript(this.config.urls.youtube.sdk).catch(error => { loadScript(this.config.urls.youtube.sdk).catch((error) => {
this.debug.warn('YouTube API failed to load', error); this.debug.warn('YouTube API failed to load', error);
}); });
} }
@@ -81,7 +81,7 @@ const youtube = {
const url = format(this.config.urls.youtube.api, videoId); const url = format(this.config.urls.youtube.api, videoId);
fetch(url) fetch(url)
.then(data => { .then((data) => {
if (is.object(data)) { if (is.object(data)) {
const { title, height, width } = data; const { title, height, width } = data;
@@ -104,6 +104,7 @@ const youtube = {
// API ready // API ready
ready() { ready() {
const player = this; const player = this;
const config = player.config.youtube;
// Ignore already setup (race condition) // Ignore already setup (race condition)
const currentId = player.media && player.media.getAttribute('id'); const currentId = player.media && player.media.getAttribute('id');
if (!is.empty(currentId) && currentId.startsWith('youtube-')) { if (!is.empty(currentId) && currentId.startsWith('youtube-')) {
@@ -121,43 +122,46 @@ const youtube = {
// Replace the <iframe> with a <div> due to YouTube API issues // Replace the <iframe> with a <div> due to YouTube API issues
const videoId = parseId(source); const videoId = parseId(source);
const id = generateId(player.provider); const id = generateId(player.provider);
// Get poster, if already set
const { poster } = player;
// Replace media element // Replace media element
const container = createElement('div', { id, 'data-poster': poster }); const container = createElement('div', { id, 'data-poster': config.customControls ? player.poster : undefined });
player.media = replaceElement(container, player.media); player.media = replaceElement(container, player.media);
// Id to poster wrapper // Only load the poster when using custom controls
const posterSrc = s => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`; if (config.customControls) {
const posterSrc = (s) => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;
// Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)
loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded loadImage(posterSrc('maxres'), 121) // Higest quality and unpadded
.catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3 .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3
.catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists
.then(image => ui.setPoster.call(player, image.src)) .then((image) => ui.setPoster.call(player, image.src))
.then(src => { .then((src) => {
// If the image is padded, use background-size "cover" instead (like youtube does too with their posters) // If the image is padded, use background-size "cover" instead (like youtube does too with their posters)
if (!src.includes('maxres')) { if (!src.includes('maxres')) {
player.elements.poster.style.backgroundSize = 'cover'; player.elements.poster.style.backgroundSize = 'cover';
} }
}) })
.catch(() => {}); .catch(() => {});
}
const config = player.config.youtube;
// Setup instance // Setup instance
// https://developers.google.com/youtube/iframe_api_reference // https://developers.google.com/youtube/iframe_api_reference
player.embed = new window.YT.Player(id, { player.embed = new window.YT.Player(player.media, {
videoId, videoId,
host: getHost(config), host: getHost(config),
playerVars: extend( playerVars: extend(
{}, {},
{ {
autoplay: player.config.autoplay ? 1 : 0, // Autoplay // Autoplay
hl: player.config.hl, // iframe interface language autoplay: player.config.autoplay ? 1 : 0,
controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported // iframe interface language
disablekb: 1, // Disable keyboard as we handle it hl: player.config.hl,
playsinline: !player.config.fullscreen.iosNative ? 1 : 0, // Allow iOS inline playback // Only show controls if not fully supported or opted out
controls: player.supported.ui && config.customControls ? 0 : 1,
// Disable keyboard as we handle it
disablekb: 1,
// Allow iOS inline playback
playsinline: !player.config.fullscreen.iosNative ? 1 : 0,
// Captions are flaky on YouTube // Captions are flaky on YouTube
cc_load_policy: player.captions.active ? 1 : 0, cc_load_policy: player.captions.active ? 1 : 0,
cc_lang_pref: player.config.captions.language, cc_lang_pref: player.config.captions.language,
@@ -278,6 +282,7 @@ const youtube = {
const toggle = is.boolean(input) ? input : muted; const toggle = is.boolean(input) ? input : muted;
muted = toggle; muted = toggle;
instance[toggle ? 'mute' : 'unMute'](); instance[toggle ? 'mute' : 'unMute']();
instance.setVolume(volume * 100);
triggerEvent.call(player, player.media, 'volumechange'); triggerEvent.call(player, player.media, 'volumechange');
}, },
}); });
@@ -299,10 +304,10 @@ const youtube = {
// Get available speeds // Get available speeds
const speeds = instance.getAvailablePlaybackRates(); const speeds = instance.getAvailablePlaybackRates();
// Filter based on config // Filter based on config
player.options.speed = speeds.filter(s => player.config.speed.options.includes(s)); player.options.speed = speeds.filter((s) => player.config.speed.options.includes(s));
// Set the tabindex to avoid focus entering iframe // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) { if (player.supported.ui && config.customControls) {
player.media.setAttribute('tabindex', -1); player.media.setAttribute('tabindex', -1);
} }
@@ -335,7 +340,9 @@ const youtube = {
}, 200); }, 200);
// Rebuild UI // Rebuild UI
setTimeout(() => ui.build.call(player), 50); if (config.customControls) {
setTimeout(() => ui.build.call(player), 50);
}
}, },
onStateChange(event) { onStateChange(event) {
// Get the instance // Get the instance
@@ -386,7 +393,7 @@ const youtube = {
case 1: case 1:
// Restore paused state (YouTube starts playing on seek if the video hasn't been played yet) // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)
if (!player.config.autoplay && player.media.paused && !player.embed.hasPlayed) { if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {
player.media.pause(); player.media.pause();
} else { } else {
assurePlaybackState.call(player, true); assurePlaybackState.call(player, true);
+67 -46
View File
@@ -214,26 +214,17 @@ declare class Plyr {
/** /**
* Add an event listener for the specified event. * Add an event listener for the specified event.
*/ */
on( on<K extends keyof Plyr.PlyrEventMap>(event: K, callback: (this: this, event: Plyr.PlyrEventMap[K]) => void): void;
event: Plyr.StandardEvent | Plyr.Html5Event | Plyr.YoutubeEvent,
callback: (this: this, event: Plyr.PlyrEvent) => void,
): void;
/** /**
* Add an event listener for the specified event once. * Add an event listener for the specified event once.
*/ */
once( once<K extends keyof Plyr.PlyrEventMap>(event: K, callback: (this: this, event: Plyr.PlyrEventMap[K]) => void): void;
event: Plyr.StandardEvent | Plyr.Html5Event | Plyr.YoutubeEvent,
callback: (this: this, event: Plyr.PlyrEvent) => void,
): void;
/** /**
* Remove an event listener for the specified event. * Remove an event listener for the specified event.
*/ */
off( off<K extends keyof Plyr.PlyrEventMap>(event: K, callback: (this: this, event: Plyr.PlyrEventMap[K]) => void): void;
event: Plyr.StandardEvent | Plyr.Html5Event | Plyr.YoutubeEvent,
callback: (this: this, event: Plyr.PlyrEvent) => void,
): void;
/** /**
* Check support for a mime type. * Check support for a mime type.
@@ -249,37 +240,51 @@ declare class Plyr {
declare namespace Plyr { declare namespace Plyr {
type MediaType = 'audio' | 'video'; type MediaType = 'audio' | 'video';
type Provider = 'html5' | 'youtube' | 'vimeo'; type Provider = 'html5' | 'youtube' | 'vimeo';
type StandardEvent = type StandardEventMap = {
| 'progress' progress: PlyrEvent;
| 'playing' playing: PlyrEvent;
| 'play' play: PlyrEvent;
| 'pause' pause: PlyrEvent;
| 'timeupdate' timeupdate: PlyrEvent;
| 'volumechange' volumechange: PlyrEvent;
| 'seeking' seeking: PlyrEvent;
| 'seeked' seeked: PlyrEvent;
| 'ratechange' ratechange: PlyrEvent;
| 'ended' ended: PlyrEvent;
| 'enterfullscreen' enterfullscreen: PlyrEvent;
| 'exitfullscreen' exitfullscreen: PlyrEvent;
| 'captionsenabled' captionsenabled: PlyrEvent;
| 'captionsdisabled' captionsdisabled: PlyrEvent;
| 'languagechange' languagechange: PlyrEvent;
| 'controlshidden' controlshidden: PlyrEvent;
| 'controlsshown' controlsshown: PlyrEvent;
| 'ready'; ready: PlyrEvent;
type Html5Event = };
| 'loadstart' // For retrocompatibility, we keep StandadEvent
| 'loadeddata' type StandadEvent = keyof Plyr.StandardEventMap;
| 'loadedmetadata' type Html5EventMap = {
| 'canplay' loadstart: PlyrEvent;
| 'canplaythrough' loadeddata: PlyrEvent;
| 'stalled' loadedmetadata: PlyrEvent;
| 'waiting' canplay: PlyrEvent;
| 'emptied' canplaythrough: PlyrEvent;
| 'cuechange' stalled: PlyrEvent;
| 'error'; waiting: PlyrEvent;
type YoutubeEvent = 'statechange' | 'qualitychange' | 'qualityrequested'; emptied: PlyrEvent;
cuechange: PlyrEvent;
error: PlyrEvent;
};
// For retrocompatibility, we keep Html5Event
type Html5Event = keyof Plyr.Html5EventMap;
type YoutubeEventMap = {
statechange: PlyrStateChangeEvent;
qualitychange: PlyrEvent;
qualityrequested: PlyrEvent;
};
// For retrocompatibility, we keep YoutubeEvent
type YoutubeEvent = keyof Plyr.YoutubeEventMap;
type PlyrEventMap = StandardEventMap & Html5EventMap & YoutubeEventMap;
interface FullscreenControl { interface FullscreenControl {
/** /**
@@ -357,7 +362,7 @@ declare namespace Plyr {
/** /**
* Specify a URL or path to a blank video file used to properly cancel network requests. * Specify a URL or path to a blank video file used to properly cancel network requests.
*/ */
blankUrl?: string; blankVideo?: string;
/** /**
* Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers. * Autoplay the media on load. This is generally advised against on UX grounds. It is also disabled by default in some browsers.
@@ -534,7 +539,7 @@ declare namespace Plyr {
interface FullScreenOptions { interface FullScreenOptions {
enabled?: boolean; enabled?: boolean;
fallback?: boolean; fallback?: boolean | 'force';
allowAudio?: boolean; allowAudio?: boolean;
iosNative?: boolean; iosNative?: boolean;
} }
@@ -552,7 +557,7 @@ declare namespace Plyr {
interface PreviewThumbnailsOptions { interface PreviewThumbnailsOptions {
enabled?: boolean; enabled?: boolean;
src?: string; src?: string | string[];
} }
interface SourceInfo { interface SourceInfo {
@@ -623,6 +628,22 @@ declare namespace Plyr {
readonly detail: { readonly plyr: Plyr }; readonly detail: { readonly plyr: Plyr };
} }
enum YoutubeState {
UNSTARTED = -1,
ENDED = 0,
PLAYING = 1,
PAUSED = 2,
BUFFERING = 3,
CUED = 5,
}
interface PlyrStateChangeEvent extends CustomEvent {
readonly detail: {
readonly plyr: Plyr;
readonly code: YoutubeState;
};
}
interface Support { interface Support {
api: boolean; api: boolean;
ui: boolean; ui: boolean;
+14 -5
View File
@@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr // Plyr
// plyr.js v3.6.2 // plyr.js v3.6.3
// https://github.com/sampotts/plyr // https://github.com/sampotts/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
@@ -12,6 +12,7 @@ import { getProviderByUrl, providers, types } from './config/types';
import Console from './console'; import Console from './console';
import controls from './controls'; import controls from './controls';
import Fullscreen from './fullscreen'; import Fullscreen from './fullscreen';
import html5 from './html5';
import Listeners from './listeners'; import Listeners from './listeners';
import media from './media'; import media from './media';
import Ads from './plugins/ads'; import Ads from './plugins/ads';
@@ -281,7 +282,7 @@ class Plyr {
// Listen for events if debugging // Listen for events if debugging
if (this.config.debug) { if (this.config.debug) {
on.call(this, this.elements.container, this.config.events.join(' '), event => { on.call(this, this.elements.container, this.config.events.join(' '), (event) => {
this.debug.log(`event: ${event.type}`); this.debug.log(`event: ${event.type}`);
}); });
} }
@@ -308,7 +309,7 @@ class Plyr {
// Autoplay if required // Autoplay if required
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(() => silencePromise(this.play()), 10); this.once('canplay', () => silencePromise(this.play()));
} }
// Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -1054,7 +1055,12 @@ class Plyr {
const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);
// Close menu // Close menu
if (hiding && is.array(this.config.controls) && this.config.controls.includes('settings') && !is.empty(this.config.settings)) { if (
hiding &&
is.array(this.config.controls) &&
this.config.controls.includes('settings') &&
!is.empty(this.config.settings)
) {
controls.toggleMenu.call(this, false); controls.toggleMenu.call(this, false);
} }
@@ -1140,6 +1146,9 @@ class Plyr {
// Unbind listeners // Unbind listeners
unbindListeners.call(this); unbindListeners.call(this);
// Cancel current network requests
html5.cancelRequests.call(this);
// Replace the container with the original element provided // Replace the container with the original element provided
replaceElement(this.elements.original, this.elements.container); replaceElement(this.elements.original, this.elements.container);
@@ -1248,7 +1257,7 @@ class Plyr {
return null; return null;
} }
return targets.map(t => new Plyr(t, options)); return targets.map((t) => new Plyr(t, options));
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr Polyfilled Build // Plyr Polyfilled Build
// plyr.js v3.6.2 // plyr.js v3.6.3
// https://github.com/sampotts/plyr // https://github.com/sampotts/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
+1 -1
View File
@@ -20,7 +20,7 @@ const source = {
src: attributes, src: attributes,
}); });
} else if (is.array(attributes)) { } else if (is.array(attributes)) {
attributes.forEach(attribute => { attributes.forEach((attribute) => {
insertElement(type, this.media, attribute); insertElement(type, this.media, attribute);
}); });
} }
+8 -5
View File
@@ -135,7 +135,7 @@ const ui = {
} }
// If there's a play button, set label // If there's a play button, set label
Array.from(this.elements.buttons.play || []).forEach(button => { Array.from(this.elements.buttons.play || []).forEach((button) => {
button.setAttribute('aria-label', label); button.setAttribute('aria-label', label);
}); });
@@ -172,13 +172,16 @@ const ui = {
// Set property synchronously to respect the call order // Set property synchronously to respect the call order
this.media.setAttribute('data-poster', poster); this.media.setAttribute('data-poster', poster);
// Show the poster
this.elements.poster.removeAttribute('hidden');
// Wait until ui is ready // Wait until ui is ready
return ( return (
ready ready
.call(this) .call(this)
// Load image // Load image
.then(() => loadImage(poster)) .then(() => loadImage(poster))
.catch(err => { .catch((err) => {
// Hide poster on error unless it's been set by another call // Hide poster on error unless it's been set by another call
if (poster === this.poster) { if (poster === this.poster) {
ui.togglePoster.call(this, false); ui.togglePoster.call(this, false);
@@ -214,7 +217,7 @@ const ui = {
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
// Set state // Set state
Array.from(this.elements.buttons.play || []).forEach(target => { Array.from(this.elements.buttons.play || []).forEach((target) => {
Object.assign(target, { pressed: this.playing }); Object.assign(target, { pressed: this.playing });
target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config)); target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config));
}); });
@@ -270,8 +273,8 @@ const ui = {
// Loop through values (as they are the keys when the object is spread 🤔) // Loop through values (as they are the keys when the object is spread 🤔)
Object.values({ ...this.media.style }) Object.values({ ...this.media.style })
// We're only fussed about Plyr specific properties // We're only fussed about Plyr specific properties
.filter(key => !is.empty(key) && key.startsWith('--plyr')) .filter((key) => !is.empty(key) && is.string(key) && key.startsWith('--plyr'))
.forEach(key => { .forEach((key) => {
// Set on the container // Set on the container
this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key)); this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key));
+1 -1
View File
@@ -14,7 +14,7 @@ export const transitionEndEvent = (() => {
transition: 'transitionend', transition: 'transitionend',
}; };
const type = Object.keys(events).find(event => element.style[event] !== undefined); const type = Object.keys(events).find((event) => element.style[event] !== undefined);
return is.string(type) ? events[type] : false; return is.string(type) ? events[type] : false;
})(); })();
+2 -2
View File
@@ -138,7 +138,7 @@ export function getAttributesFromSelector(sel, existingAttributes) {
const attributes = {}; const attributes = {};
const existing = extend({}, existingAttributes); const existing = extend({}, existingAttributes);
sel.split(',').forEach(s => { sel.split(',').forEach((s) => {
// Remove whitespace // Remove whitespace
const selector = s.trim(); const selector = s.trim();
const className = selector.replace('.', ''); const className = selector.replace('.', '');
@@ -198,7 +198,7 @@ export function toggleHidden(element, hidden) {
// Mirror Element.classList.toggle, with IE compatibility for "force" argument // Mirror Element.classList.toggle, with IE compatibility for "force" argument
export function toggleClass(element, className, force) { export function toggleClass(element, className, force) {
if (is.nodeList(element)) { if (is.nodeList(element)) {
return Array.from(element).map(e => toggleClass(e, className, force)); return Array.from(element).map((e) => toggleClass(e, className, force));
} }
if (is.element(element)) { if (is.element(element)) {
+3 -3
View File
@@ -50,7 +50,7 @@ export function toggleListener(element, event, callback, toggle = false, passive
} }
// If a single node is passed, bind the event listener // If a single node is passed, bind the event listener
events.forEach(type => { events.forEach((type) => {
if (this && this.eventListeners && toggle) { if (this && this.eventListeners && toggle) {
// Cache event listener // Cache event listener
this.eventListeners.push({ element, type, callback, options }); this.eventListeners.push({ element, type, callback, options });
@@ -100,7 +100,7 @@ export function triggerEvent(element, type = '', bubbles = false, detail = {}) {
// Unbind all cached event listeners // Unbind all cached event listeners
export function unbindListeners() { export function unbindListeners() {
if (this && this.eventListeners) { if (this && this.eventListeners) {
this.eventListeners.forEach(item => { this.eventListeners.forEach((item) => {
const { element, type, callback, options } = item; const { element, type, callback, options } = item;
element.removeEventListener(type, callback, options); element.removeEventListener(type, callback, options);
}); });
@@ -111,7 +111,7 @@ export function unbindListeners() {
// Run method when / if player is ready // Run method when / if player is ready
export function ready() { export function ready() {
return new Promise(resolve => return new Promise((resolve) =>
this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve), this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),
).then(() => {}); ).then(() => {});
} }
+19 -19
View File
@@ -2,31 +2,31 @@
// Type checking utils // Type checking utils
// ========================================================================== // ==========================================================================
const getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null); const getConstructor = (input) => (input !== null && typeof input !== 'undefined' ? input.constructor : null);
const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor); const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);
const isNullOrUndefined = input => input === null || typeof input === 'undefined'; const isNullOrUndefined = (input) => input === null || typeof input === 'undefined';
const isObject = input => getConstructor(input) === Object; const isObject = (input) => getConstructor(input) === Object;
const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input); const isNumber = (input) => getConstructor(input) === Number && !Number.isNaN(input);
const isString = input => getConstructor(input) === String; const isString = (input) => getConstructor(input) === String;
const isBoolean = input => getConstructor(input) === Boolean; const isBoolean = (input) => getConstructor(input) === Boolean;
const isFunction = input => getConstructor(input) === Function; const isFunction = (input) => getConstructor(input) === Function;
const isArray = input => Array.isArray(input); const isArray = (input) => Array.isArray(input);
const isWeakMap = input => instanceOf(input, WeakMap); const isWeakMap = (input) => instanceOf(input, WeakMap);
const isNodeList = input => instanceOf(input, NodeList); const isNodeList = (input) => instanceOf(input, NodeList);
const isElement = input => instanceOf(input, Element); const isElement = (input) => instanceOf(input, Element);
const isTextNode = input => getConstructor(input) === Text; const isTextNode = (input) => getConstructor(input) === Text;
const isEvent = input => instanceOf(input, Event); const isEvent = (input) => instanceOf(input, Event);
const isKeyboardEvent = input => instanceOf(input, KeyboardEvent); const isKeyboardEvent = (input) => instanceOf(input, KeyboardEvent);
const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue); const isCue = (input) => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
const isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind)); const isTrack = (input) => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));
const isPromise = input => instanceOf(input, Promise) && isFunction(input.then); const isPromise = (input) => instanceOf(input, Promise) && isFunction(input.then);
const isEmpty = input => const isEmpty = (input) =>
isNullOrUndefined(input) || isNullOrUndefined(input) ||
((isString(input) || isArray(input) || isNodeList(input)) && !input.length) || ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||
(isObject(input) && !Object.keys(input).length); (isObject(input) && !Object.keys(input).length);
const isUrl = input => { const isUrl = (input) => {
// Accept a URL object // Accept a URL object
if (instanceOf(input, window.URL)) { if (instanceOf(input, window.URL)) {
return true; return true;
+1 -1
View File
@@ -54,7 +54,7 @@ export default function loadSprite(url, id) {
// Get the sprite // Get the sprite
fetch(url) fetch(url)
.then(result => { .then((result) => {
if (is.empty(result)) { if (is.empty(result)) {
return; return;
} }
+1 -1
View File
@@ -26,7 +26,7 @@ export function extend(target = {}, ...sources) {
return target; return target;
} }
Object.keys(source).forEach(key => { Object.keys(source).forEach((key) => {
if (is.object(source[key])) { if (is.object(source[key])) {
if (!Object.keys(target).includes(key)) { if (!Object.keys(target).includes(key)) {
Object.assign(target, { [key]: {} }); Object.assign(target, { [key]: {} });
+1 -1
View File
@@ -33,7 +33,7 @@ export const replaceAll = (input = '', find = '', replace = '') =>
// Convert to title case // Convert to title case
export const toTitleCase = (input = '') => export const toTitleCase = (input = '') =>
input.toString().replace(/\w\S*/g, text => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase()); input.toString().replace(/\w\S*/g, (text) => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase());
// Convert string to pascalCase // Convert string to pascalCase
export function toPascalCase(input = '') { export function toPascalCase(input = '') {
+6 -2
View File
@@ -27,7 +27,7 @@ export function reduceAspectRatio(ratio) {
} }
export function getAspectRatio(input) { export function getAspectRatio(input) {
const parse = ratio => (validateRatio(ratio) ? ratio.split(':').map(Number) : null); const parse = (ratio) => (validateRatio(ratio) ? ratio.split(':').map(Number) : null);
// Try provided ratio // Try provided ratio
let ratio = parse(input); let ratio = parse(input);
@@ -68,7 +68,11 @@ export function setAspectRatio(input) {
const height = (100 / this.media.offsetWidth) * parseInt(window.getComputedStyle(this.media).paddingBottom, 10); const height = (100 / this.media.offsetWidth) * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
const offset = (height - padding) / (height / 50); const offset = (height - padding) / (height / 50);
this.media.style.transform = `translateY(-${offset}%)`; if (this.fullscreen.active) {
wrapper.style.paddingBottom = null;
} else {
this.media.style.transform = `translateY(-${offset}%)`;
}
} else if (this.isHTML5) { } else if (this.isHTML5) {
wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null); wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
} }
+4 -4
View File
@@ -5,9 +5,9 @@
import is from './is'; import is from './is';
// Time helpers // Time helpers
export const getHours = value => Math.trunc((value / 60 / 60) % 60, 10); export const getHours = (value) => Math.trunc((value / 60 / 60) % 60, 10);
export const getMinutes = value => Math.trunc((value / 60) % 60, 10); export const getMinutes = (value) => Math.trunc((value / 60) % 60, 10);
export const getSeconds = value => Math.trunc(value % 60, 10); export const getSeconds = (value) => Math.trunc(value % 60, 10);
// Format time to UI friendly string // Format time to UI friendly string
export function formatTime(time = 0, displayHours = false, inverted = false) { export function formatTime(time = 0, displayHours = false, inverted = false) {
@@ -17,7 +17,7 @@ export function formatTime(time = 0, displayHours = false, inverted = false) {
} }
// Format time component to add leading zero // Format time component to add leading zero
const format = value => `0${value}`.slice(-2); const format = (value) => `0${value}`.slice(-2);
// Breakdown to hours, mins, secs // Breakdown to hours, mins, secs
let hours = getHours(time); let hours = getHours(time);
const mins = getMinutes(time); const mins = getMinutes(time);
-1
View File
@@ -12,7 +12,6 @@
font-family: $plyr-font-family; font-family: $plyr-font-family;
font-variant-numeric: tabular-nums; // Force monosace-esque number widths font-variant-numeric: tabular-nums; // Force monosace-esque number widths
font-weight: $plyr-font-weight-regular; font-weight: $plyr-font-weight-regular;
height: 100%;
line-height: $plyr-line-height; line-height: $plyr-line-height;
max-width: 100%; max-width: 100%;
min-width: 200px; min-width: 200px;
+1 -1
View File
@@ -3,7 +3,6 @@
// -------------------------------------------------------------- // --------------------------------------------------------------
.plyr--full-ui input[type='range'] { .plyr--full-ui input[type='range'] {
// WebKit
-webkit-appearance: none; /* stylelint-disable-line */ -webkit-appearance: none; /* stylelint-disable-line */
background: transparent; background: transparent;
border: 0; border: 0;
@@ -13,6 +12,7 @@
display: block; display: block;
height: calc((#{$plyr-range-thumb-active-shadow-width} * 2) + #{$plyr-range-thumb-height}); height: calc((#{$plyr-range-thumb-active-shadow-width} * 2) + #{$plyr-range-thumb-height});
margin: 0; margin: 0;
min-width: 0;
padding: 0; padding: 0;
transition: box-shadow 0.3s ease; transition: box-shadow 0.3s ease;
width: 100%; width: 100%;
+1 -1
View File
@@ -14,7 +14,7 @@
margin-right: $plyr-control-spacing; margin-right: $plyr-control-spacing;
} }
@media (max-width: calc(#{$plyr-bp-md} - 1)) { @media (max-width: calc(#{$plyr-bp-md} - 1px)) {
display: none; display: none;
} }
} }
+5 -4
View File
@@ -30,6 +30,7 @@ const plumber = require('gulp-plumber');
const size = require('gulp-size'); const size = require('gulp-size');
const sourcemaps = require('gulp-sourcemaps'); const sourcemaps = require('gulp-sourcemaps');
const browserSync = require('browser-sync').create(); const browserSync = require('browser-sync').create();
const gulpIf = require('gulp-if');
// Configs // Configs
const build = require('../build.json'); const build = require('../build.json');
// Info from package // Info from package
@@ -74,8 +75,8 @@ const tasks = {
const sizeOptions = { showFiles: true, gzip: true }; const sizeOptions = { showFiles: true, gzip: true };
// Clean out /dist // Clean out /dist
gulp.task('clean', done => { gulp.task('clean', (done) => {
const dirs = [paths.plyr.output, paths.demo.output].map(dir => path.join(dir, '**/*')); const dirs = [paths.plyr.output, paths.demo.output].map((dir) => path.join(dir, '**/*'));
// Don't delete the mp4 // Don't delete the mp4
dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`); dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`);
@@ -89,7 +90,7 @@ gulp.task('clean', done => {
Object.entries(build.js).forEach(([filename, entry]) => { Object.entries(build.js).forEach(([filename, entry]) => {
const { dist, formats, namespace, polyfill, src } = entry; const { dist, formats, namespace, polyfill, src } = entry;
formats.forEach(format => { formats.forEach((format) => {
const name = `js:${filename}:${format}`; const name = `js:${filename}:${format}`;
const extension = format === 'es' ? 'mjs' : 'js'; const extension = format === 'es' ? 'mjs' : 'js';
tasks.js.push(name); tasks.js.push(name);
@@ -128,7 +129,7 @@ Object.entries(build.js).forEach(([filename, entry]) => {
}, },
), ),
) )
.pipe(header('typeof navigator === "object" && ')) // "Support" SSR (#935) .pipe(gulpIf(() => extension !== 'mjs', header('typeof navigator === "object" && '))) // "Support" SSR (#935)
.pipe( .pipe(
rename({ rename({
extname: `.${extension}`, extname: `.${extension}`,
+8 -8
View File
@@ -27,7 +27,7 @@ const { version } = pkg;
const minSuffix = '.min'; const minSuffix = '.min';
// Get AWS config // Get AWS config
Object.values(deploy).forEach(target => { Object.values(deploy).forEach((target) => {
Object.assign(target, { Object.assign(target, {
publisher: publish.create({ publisher: publish.create({
region: target.region, region: target.region,
@@ -102,7 +102,7 @@ const localPath = new RegExp('(../)?dist/', 'gi');
const versionPath = `https://${deploy.cdn.domain}/${version}/`; const versionPath = `https://${deploy.cdn.domain}/${version}/`;
const cdnpath = new RegExp(`${deploy.cdn.domain}/${regex}/`, 'gi'); const cdnpath = new RegExp(`${deploy.cdn.domain}/${regex}/`, 'gi');
const renameFile = rename(p => { const renameFile = rename((p) => {
p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line
p.dirname = p.dirname.replace('.', version); // eslint-disable-line p.dirname = p.dirname.replace('.', version); // eslint-disable-line
}); });
@@ -120,7 +120,7 @@ const canDeploy = () => {
return true; return true;
}; };
gulp.task('version', done => { gulp.task('version', (done) => {
if (!canDeploy()) { if (!canDeploy()) {
done(); done();
return null; return null;
@@ -135,7 +135,7 @@ gulp.task('version', done => {
return gulp return gulp
.src( .src(
files.map(file => path.join(root, `src/js/${file}`)), files.map((file) => path.join(root, `src/js/${file}`)),
{ base: '.' }, { base: '.' },
) )
.pipe(replace(semver, `v${version}`)) .pipe(replace(semver, `v${version}`))
@@ -144,7 +144,7 @@ gulp.task('version', done => {
}); });
// Publish version to CDN bucket // Publish version to CDN bucket
gulp.task('cdn', done => { gulp.task('cdn', (done) => {
if (!canDeploy()) { if (!canDeploy()) {
done(); done();
return null; return null;
@@ -198,7 +198,7 @@ gulp.task('purge', () => {
.on('end', () => { .on('end', () => {
const purge = new FastlyPurge(fastly.token); const purge = new FastlyPurge(fastly.token);
list.forEach(url => { list.forEach((url) => {
log(`Purging ${ansi.cyan(url)}...`); log(`Purging ${ansi.cyan(url)}...`);
purge.url(url, (error, result) => { purge.url(url, (error, result) => {
@@ -213,7 +213,7 @@ gulp.task('purge', () => {
}); });
// Publish to demo bucket // Publish to demo bucket
gulp.task('demo', done => { gulp.task('demo', (done) => {
if (!canDeploy()) { if (!canDeploy()) {
done(); done();
return null; return null;
@@ -248,7 +248,7 @@ gulp.task('demo', done => {
.src(pages) .src(pages)
.pipe(replace(localPath, versionPath)) .pipe(replace(localPath, versionPath))
.pipe( .pipe(
rename(p => { rename((p) => {
if (options.demo.uploadPath) { if (options.demo.uploadPath) {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
p.dirname += options.demo.uploadPath; p.dirname += options.demo.uploadPath;
+2077 -889
View File
File diff suppressed because it is too large Load Diff