Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32444c9851 | |||
| b93dcc43ad | |||
| 6ff6ff1673 | |||
| e1ff86820c | |||
| 7d22c361d1 | |||
| 951cccb6b0 | |||
| 438e425838 | |||
| ddb5ad071e | |||
| 38060d986c | |||
| 8c74396459 | |||
| a09d63e8f8 | |||
| d74af9a73d | |||
| 60310693d3 | |||
| 5d08821c9b | |||
| 3316e40e7b | |||
| dfe5985326 | |||
| b27ad17c59 | |||
| 14b8b24e14 | |||
| 711fc5835f | |||
| 028be22dec | |||
| 3b5dc09285 | |||
| 8596e05df3 | |||
| 1aee8f53a7 | |||
| a187d07807 | |||
| 3096dd9513 | |||
| 150b07f3ef | |||
| ad7778e78d | |||
| c8e776bbea | |||
| c66dc8bf95 | |||
| ea87b9c788 | |||
| aa3378fd73 | |||
| 2cebf9b8a3 | |||
| 572aeacf5b | |||
| b5592b0fb5 | |||
| 9adf35a444 | |||
| 39ff31e3e3 | |||
| 7e82ec6d70 | |||
| f4d6a243cd | |||
| 31b5027b1e | |||
| 7750314058 | |||
| 16c134fc1e | |||
| f00e81a976 | |||
| 32a4039f7c | |||
| ba09bc32d3 | |||
| d7195d5276 | |||
| 6a6fb8d41a | |||
| c853adc760 | |||
| ca041f2e0d | |||
| 87078d7a44 | |||
| c300df5742 | |||
| 2ba56fda15 | |||
| 36b53d2cf0 | |||
| 2d4686a5f3 | |||
| 31861bd475 | |||
| c3e163741f | |||
| 1c715bc889 | |||
| 35ef42246b | |||
| cd3962ca32 | |||
| da16c55427 | |||
| bd8bacb6d5 | |||
| 0d393a5c92 | |||
| 136bb525a5 | |||
| e85737d855 | |||
| 8882317080 | |||
| 5c02205a4f | |||
| 45f7e20233 | |||
| b116e62f37 | |||
| fa6282d0e2 | |||
| 80bdf04fde | |||
| 3caa37fdf2 | |||
| 807efcbc46 | |||
| 03d1e3d3e8 | |||
| 664e2b4893 | |||
| 4cf36bf203 | |||
| 92f3728d80 | |||
| 29d3ae0b67 | |||
| df91f7faac | |||
| 9a69ae2599 | |||
| 02321c35bc | |||
| 7c6316d824 | |||
| 776b0c4036 | |||
| fa653a8859 | |||
| b6b7db7327 | |||
| d4b4303b8e | |||
| 102fb1a32f | |||
| c77ba3ecf0 | |||
| 760f5f9469 | |||
| 0135e9c7f4 | |||
| 2426c256cc | |||
| 93eed08d14 | |||
| 5a164780d8 | |||
| 272d39c1d1 | |||
| 828abc8308 | |||
| 6455a6acc0 | |||
| 51cb03dc32 | |||
| 4d25a33cb0 | |||
| 18b3f23c69 | |||
| 11e48b0181 | |||
| 3a07669e30 | |||
| b3d390076b | |||
| f75820fbd3 | |||
| 8b0d84a9a4 | |||
| d582e43413 | |||
| 75082bc73f | |||
| f7e9ee56d2 | |||
| 22af7f16ea | |||
| 9076d054b9 | |||
| 4eaa1a72b5 | |||
| 4c1ae8f3ce | |||
| 0733133510 | |||
| 423b7b276f | |||
| cbd4a7cef4 | |||
| 8ce7425f73 | |||
| 1f63806c3f | |||
| 6cb822d56f | |||
| 9dee5acec6 |
@@ -1,8 +1,3 @@
|
|||||||
### Link to related issue (if applicable)
|
### Link to related issue (if applicable)
|
||||||
|
|
||||||
### Summary of proposed changes
|
### Summary of proposed changes
|
||||||
|
|
||||||
### Checklist
|
|
||||||
- [ ] Use `develop` as the base branch
|
|
||||||
- [ ] Exclude the gulp build (`/dist` changes) from the PR
|
|
||||||
- [ ] Test on [supported browsers](https://github.com/sampotts/plyr#browser-support)
|
|
||||||
|
|||||||
+1
-1
@@ -2,8 +2,8 @@ node_modules
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
credentials.json
|
credentials.json
|
||||||
*.mp4
|
*.mp4
|
||||||
!dist/blank.mp4
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
*.webm
|
*.webm
|
||||||
.idea/
|
.idea/
|
||||||
|
dist/
|
||||||
|
|||||||
+1
-1
@@ -7,6 +7,6 @@ credentials.json
|
|||||||
deploy.json
|
deploy.json
|
||||||
yarn.lock
|
yarn.lock
|
||||||
package-lock.json
|
package-lock.json
|
||||||
*.mp4
|
|
||||||
*.webm
|
*.webm
|
||||||
|
*.mp4
|
||||||
!dist/blank.mp4
|
!dist/blank.mp4
|
||||||
|
|||||||
@@ -2,7 +2,5 @@ language: node_js
|
|||||||
node_js: lts/*
|
node_js: lts/*
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- bash .travis/prevent-base-master.sh
|
|
||||||
- bash .travis/omit-dist.sh
|
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm run build
|
- npm run build
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
if [ $TRAVIS_BRANCH == "develop" ] && $(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qE "^(demo/)?dist/"); then
|
|
||||||
echo 'Build output ("dist" and "demo/dist") not permitted in develop' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ $TRAVIS_BRANCH == "master" ] && $(git diff --name-only $TRAVIS_COMMIT_RANGE | grep -q "^src/"); then
|
|
||||||
echo 'The base branch for pull requests must be "develop"' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,3 +1,33 @@
|
|||||||
|
### v3.6.7
|
||||||
|
|
||||||
|
- Fix: remove regression caused by optional chaining and nullish coalescing in check for `window.CSS` check for aspect-ratio (fixes #2174)
|
||||||
|
|
||||||
|
### v3.6.6
|
||||||
|
|
||||||
|
- Improvements to how aspect ratio is handled. Use `aspect-ratio` CSS property instead of the legacy method (still used as fallback). Also automatically determined aspect ratios are rounded to the nearast standard ratio. This fixes issues with the YouTube embeds showing a 1-2px black bar.
|
||||||
|
- Hide the YouTube poster image container when paused so that the controls underneath can be used.
|
||||||
|
|
||||||
|
### v3.6.5
|
||||||
|
|
||||||
|
- Migrate color formatting to colorette (thanks @jorgebucaran)
|
||||||
|
- Fix: issue with IE detection
|
||||||
|
- Fix: missing styles for embeds
|
||||||
|
- Fix: regression regarding poster image
|
||||||
|
- Add all required props to vimeo iframe allow attribute - fixes #2151 (thanks @didrip)
|
||||||
|
|
||||||
|
### v3.6.4
|
||||||
|
|
||||||
|
- Remove unnecessary calc from media query (thanks @naomiaz)
|
||||||
|
- Enhance types (thanks @lunika)
|
||||||
|
- Fix: Object.values for the providers must be used (thanks @syteknet-core)
|
||||||
|
- Fix: Improve support inside iframes (thanks @ajgagnon)
|
||||||
|
- Added --plyr-video-background for having control over the background of a video with alpha channel (webm) or a poster image with alpha channel (thanks @nepomuc)
|
||||||
|
- Fix issue with not entering iosfullscreen of vimeo videos with playsinline=true (thanks @lordon and @Frosch)
|
||||||
|
- fix: use new syntax for iframe allow attribute
|
||||||
|
- chore: package updates
|
||||||
|
- chore: add @babel/plugin-proposal-class-properties
|
||||||
|
- fix: use bound arrow functions in classes
|
||||||
|
|
||||||
### v3.6.3
|
### v3.6.3
|
||||||
|
|
||||||
- Fix volume when unmuting from volume 0 using YouTube (thanks @stephanefbouchard)
|
- Fix volume when unmuting from volume 0 using YouTube (thanks @stephanefbouchard)
|
||||||
|
|||||||
+3
-3
@@ -36,8 +36,8 @@ Please follow the instructions in our issue templates. Don't use github issues t
|
|||||||
You can use Gitpod (a free online VS Code-like IDE) for contributing. With a single click it will launch a workspace and automatically:
|
You can use Gitpod (a free online VS Code-like IDE) for contributing. With a single click it will launch a workspace and automatically:
|
||||||
|
|
||||||
- clone the plyr repo.
|
- clone the plyr repo.
|
||||||
- install the dependencies.
|
- install the dependencies with `yarn install` in root directory and "demo" directory.
|
||||||
- run `gulp` to the start the server.
|
- run `gulp` in root directory to start the dev server.
|
||||||
|
|
||||||
So that you can start straight away.
|
So that you can start straight away.
|
||||||
|
|
||||||
@@ -49,6 +49,6 @@ So that you can start straight away.
|
|||||||
|
|
||||||
- If your modifications changes the documented behavior or add new features, document these changes in [README.md](README.md).
|
- If your modifications changes the documented behavior or add new features, document these changes in [README.md](README.md).
|
||||||
|
|
||||||
- When finished, push the changes to your GitHub repository and send a pull request to **develop**. Describe what your PR does.
|
- When finished, push the changes to your GitHub repository and send a pull request. Describe what your PR does.
|
||||||
|
|
||||||
- If the Travis build fails, or if you get a code review with change requests, you can fix these by pushing new or rebased commits to the branch.
|
- If the Travis build fails, or if you get a code review with change requests, you can fix these by pushing new or rebased commits to the branch.
|
||||||
|
|||||||
@@ -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.3/plyr.js"></script>
|
<script src="https://cdn.plyr.io/3.6.7/plyr.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
...or...
|
...or...
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.plyr.io/3.6.3/plyr.polyfilled.js"></script>
|
<script src="https://cdn.plyr.io/3.6.7/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.3/plyr.css" />
|
<link rel="stylesheet" href="https://cdn.plyr.io/3.6.7/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.3/plyr.svg`.
|
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.6.7/plyr.svg`.
|
||||||
|
|
||||||
# Ads
|
# Ads
|
||||||
|
|
||||||
@@ -185,6 +185,7 @@ Here's a list of the properties and what they are used for:
|
|||||||
| Name | Description | Default / Fallback |
|
| Name | Description | Default / Fallback |
|
||||||
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||||
| `--plyr-color-main` | The primary UI color. |  `#00b3ff` |
|
| `--plyr-color-main` | The primary UI color. |  `#00b3ff` |
|
||||||
|
| `--plyr-video-background` | The background color of video and poster wrappers for using alpha channel videos and poster images. | `rgba(0, 0, 0, 1)` |
|
||||||
| `--plyr-tab-focus-color` | The color used for the dotted outline when an element is `:focus-visible` (equivalent) keyboard focus. | `--plyr-color-main` |
|
| `--plyr-tab-focus-color` | The color used for the dotted outline when an element is `:focus-visible` (equivalent) keyboard focus. | `--plyr-color-main` |
|
||||||
| `--plyr-badge-background` | The background color for badges in the menu. |  `#4a5464` |
|
| `--plyr-badge-background` | The background color for badges in the menu. |  `#4a5464` |
|
||||||
| `--plyr-badge-text-color` | The text color for badges. |  `#ffffff` |
|
| `--plyr-badge-text-color` | The text color for badges. |  `#ffffff` |
|
||||||
@@ -838,6 +839,7 @@ Plyr costs money to run, not only my time. I donate my time for free as I enjoy
|
|||||||
- [Rutheneum-Bote](https://gymnasium-rutheneum.de/content/newspaper/kreativwettbewerb.php)
|
- [Rutheneum-Bote](https://gymnasium-rutheneum.de/content/newspaper/kreativwettbewerb.php)
|
||||||
- [pressakey.com | Blog-Magazin für Videospiele](https://pressakey.com)
|
- [pressakey.com | Blog-Magazin für Videospiele](https://pressakey.com)
|
||||||
- [STROLLÿN: Work with a View](https://strollyn.com)
|
- [STROLLÿN: Work with a View](https://strollyn.com)
|
||||||
|
- [CFDA Runway360](https://runway360.cfda.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 😎
|
||||||
|
|
||||||
|
|||||||
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-29688
File diff suppressed because it is too large
Load Diff
Vendored
-19
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 5.6 KiB |
Vendored
-1
File diff suppressed because one or more lines are too long
@@ -2,4 +2,4 @@
|
|||||||
// Layout
|
// Layout
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$container-max-width: 1260px;
|
$container-max-width: 1240px;
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-9349
File diff suppressed because it is too large
Load Diff
Vendored
-4
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-3
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-9341
File diff suppressed because it is too large
Load Diff
Vendored
-15829
File diff suppressed because it is too large
Load Diff
Vendored
-4
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-3
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
-15821
File diff suppressed because it is too large
Load Diff
Vendored
-1
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 5.6 KiB |
+23
-24
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "plyr",
|
"name": "plyr",
|
||||||
"version": "3.6.3",
|
"version": "3.6.7",
|
||||||
"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>",
|
||||||
@@ -39,18 +39,19 @@
|
|||||||
"start": "gulp"
|
"start": "gulp"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sampotts/eslint-config": "1.1.5",
|
"@sampotts/eslint-config": "1.1.7",
|
||||||
"ansi-colors": "^4.1.1",
|
"autoprefixer": "^10.2.5",
|
||||||
"autoprefixer": "^10.0.2",
|
"aws-sdk": "^2.888.0",
|
||||||
"aws-sdk": "^2.773.0",
|
"@babel/core": "^7.13.15",
|
||||||
"@babel/core": "^7.12.3",
|
"@babel/preset-env": "^7.13.15",
|
||||||
"@babel/preset-env": "^7.12.1",
|
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"browser-sync": "^2.26.13",
|
"browser-sync": "^2.26.14",
|
||||||
|
"colorette": "1.2.2",
|
||||||
|
"cssnano": "^5.0.1",
|
||||||
"del": "^6.0.0",
|
"del": "^6.0.0",
|
||||||
"eslint": "^7.3.1",
|
"eslint": "^7.23.0",
|
||||||
"fancy-log": "^1.3.3",
|
"fancy-log": "^1.3.3",
|
||||||
"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.2",
|
"gulp-awspublish": "^4.1.2",
|
||||||
@@ -69,29 +70,27 @@
|
|||||||
"gulp-size": "^3.0.0",
|
"gulp-size": "^3.0.0",
|
||||||
"gulp-sourcemaps": "^3.0.0",
|
"gulp-sourcemaps": "^3.0.0",
|
||||||
"gulp-svgstore": "^7.0.1",
|
"gulp-svgstore": "^7.0.1",
|
||||||
"gulp-terser": "^1.4.1",
|
"gulp-terser": "^2.0.1",
|
||||||
"postcss": "^8.1.7",
|
"postcss": "^8.2.10",
|
||||||
"postcss-clean": "^1.1.0",
|
"postcss-custom-properties": "^11.0.0",
|
||||||
"postcss-custom-properties": "^10.0.0",
|
"prettier-eslint": "^12.0.0",
|
||||||
"prettier-eslint": "^11.0.0",
|
|
||||||
"prettier-stylelint": "^0.4.2",
|
"prettier-stylelint": "^0.4.2",
|
||||||
"remark-cli": "^9.0.0",
|
"remark-cli": "^9.0.0",
|
||||||
"remark-validate-links": "^10.0.2",
|
"remark-validate-links": "^10.0.4",
|
||||||
"rollup": "^2.33.1",
|
"rollup": "^2.45.2",
|
||||||
"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.7.2",
|
"stylelint": "^13.12.0",
|
||||||
"stylelint-config-prettier": "^8.0.2",
|
"stylelint-config-prettier": "^8.0.2",
|
||||||
"stylelint-config-recommended": "^3.0.0",
|
"stylelint-config-recommended": "^4.0.0",
|
||||||
"stylelint-config-sass-guidelines": "^7.1.0",
|
"stylelint-config-sass-guidelines": "^8.0.0",
|
||||||
"stylelint-order": "^4.1.0",
|
"stylelint-order": "^4.1.0",
|
||||||
"stylelint-scss": "^3.18.0",
|
"stylelint-scss": "^3.19.0",
|
||||||
"stylelint-selector-bem-pattern": "^2.1.0",
|
"stylelint-selector-bem-pattern": "^2.1.0"
|
||||||
"through2": "^4.0.2"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.7.0",
|
"core-js": "^3.10.1",
|
||||||
"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",
|
||||||
|
|||||||
@@ -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.3/plyr.svg',
|
iconUrl: 'https://cdn.plyr.io/3.6.7/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',
|
||||||
|
|||||||
+21
-15
@@ -57,6 +57,8 @@ class Fullscreen {
|
|||||||
|
|
||||||
// Update the UI
|
// Update the UI
|
||||||
this.update();
|
this.update();
|
||||||
|
|
||||||
|
// this.toggle = this.toggle.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if native supported
|
// Determine if native supported
|
||||||
@@ -134,7 +136,7 @@ class Fullscreen {
|
|||||||
: this.player.elements.fullscreen || this.player.elements.container;
|
: this.player.elements.fullscreen || this.player.elements.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange() {
|
onChange = () => {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -149,9 +151,9 @@ class Fullscreen {
|
|||||||
const target = this.target === this.player.media ? this.target : this.player.elements.container;
|
const target = this.target === this.player.media ? this.target : this.player.elements.container;
|
||||||
// Trigger an event
|
// Trigger an event
|
||||||
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
|
triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
|
||||||
}
|
};
|
||||||
|
|
||||||
toggleFallback(toggle = false) {
|
toggleFallback = (toggle = false) => {
|
||||||
// Store or restore scroll position
|
// Store or restore scroll position
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
this.scrollPosition = {
|
this.scrollPosition = {
|
||||||
@@ -198,10 +200,10 @@ class Fullscreen {
|
|||||||
|
|
||||||
// Toggle button and fire events
|
// Toggle button and fire events
|
||||||
this.onChange();
|
this.onChange();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Trap focus inside container
|
// Trap focus inside container
|
||||||
trapFocus(event) {
|
trapFocus = (event) => {
|
||||||
// Bail if iOS, not active, not the tab key
|
// Bail if iOS, not active, not the tab key
|
||||||
if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {
|
if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {
|
||||||
return;
|
return;
|
||||||
@@ -222,10 +224,10 @@ class Fullscreen {
|
|||||||
last.focus();
|
last.focus();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
update() {
|
update = () => {
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
let mode;
|
let mode;
|
||||||
|
|
||||||
@@ -244,17 +246,21 @@ class Fullscreen {
|
|||||||
|
|
||||||
// Add styling hook to show button
|
// Add styling hook to show button
|
||||||
toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);
|
toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.enabled);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Make an element fullscreen
|
// Make an element fullscreen
|
||||||
enter() {
|
enter = () => {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iOS native fullscreen doesn't need the request step
|
// iOS native fullscreen doesn't need the request step
|
||||||
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
if (browser.isIos && this.player.config.fullscreen.iosNative) {
|
||||||
this.target.webkitEnterFullscreen();
|
if (this.player.isVimeo) {
|
||||||
|
this.player.embed.requestFullscreen();
|
||||||
|
} else {
|
||||||
|
this.target.webkitEnterFullscreen();
|
||||||
|
}
|
||||||
} else if (!Fullscreen.native || this.forceFallback) {
|
} else if (!Fullscreen.native || this.forceFallback) {
|
||||||
this.toggleFallback(true);
|
this.toggleFallback(true);
|
||||||
} else if (!this.prefix) {
|
} else if (!this.prefix) {
|
||||||
@@ -262,10 +268,10 @@ class Fullscreen {
|
|||||||
} else if (!is.empty(this.prefix)) {
|
} else if (!is.empty(this.prefix)) {
|
||||||
this.target[`${this.prefix}Request${this.property}`]();
|
this.target[`${this.prefix}Request${this.property}`]();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Bail from fullscreen
|
// Bail from fullscreen
|
||||||
exit() {
|
exit = () => {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -282,16 +288,16 @@ class Fullscreen {
|
|||||||
const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
||||||
document[`${this.prefix}${action}${this.property}`]();
|
document[`${this.prefix}${action}${this.property}`]();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Toggle state
|
// Toggle state
|
||||||
toggle() {
|
toggle = () => {
|
||||||
if (!this.active) {
|
if (!this.active) {
|
||||||
this.enter();
|
this.enter();
|
||||||
} else {
|
} else {
|
||||||
this.exit();
|
this.exit();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Fullscreen;
|
export default Fullscreen;
|
||||||
|
|||||||
+16
-16
@@ -183,7 +183,7 @@ class Listeners {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Device is touch enabled
|
// Device is touch enabled
|
||||||
firstTouch() {
|
firstTouch = () => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const { elements } = player;
|
const { elements } = player;
|
||||||
|
|
||||||
@@ -191,9 +191,9 @@ class Listeners {
|
|||||||
|
|
||||||
// Add touch class
|
// Add touch class
|
||||||
toggleClass(elements.container, player.config.classNames.isTouch, true);
|
toggleClass(elements.container, player.config.classNames.isTouch, true);
|
||||||
}
|
};
|
||||||
|
|
||||||
setTabFocus(event) {
|
setTabFocus = (event) => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const { elements } = player;
|
const { elements } = player;
|
||||||
|
|
||||||
@@ -241,10 +241,10 @@ class Listeners {
|
|||||||
toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
|
toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Global window & document listeners
|
// Global window & document listeners
|
||||||
global(toggle = true) {
|
global = (toggle = true) => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
|
|
||||||
// Keyboard shortcuts
|
// Keyboard shortcuts
|
||||||
@@ -260,10 +260,10 @@ class Listeners {
|
|||||||
|
|
||||||
// Tab focus detection
|
// Tab focus detection
|
||||||
toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
|
toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Container listeners
|
// Container listeners
|
||||||
container() {
|
container = () => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const { config, elements, timers } = player;
|
const { config, elements, timers } = player;
|
||||||
|
|
||||||
@@ -370,10 +370,10 @@ class Listeners {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Listen for media events
|
// Listen for media events
|
||||||
media() {
|
media = () => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const { elements } = player;
|
const { elements } = player;
|
||||||
|
|
||||||
@@ -514,10 +514,10 @@ class Listeners {
|
|||||||
|
|
||||||
triggerEvent.call(player, elements.container, event.type, true, detail);
|
triggerEvent.call(player, elements.container, event.type, true, detail);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Run default and custom handlers
|
// Run default and custom handlers
|
||||||
proxy(event, defaultHandler, customHandlerKey) {
|
proxy = (event, defaultHandler, customHandlerKey) => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const customHandler = player.config.listeners[customHandlerKey];
|
const customHandler = player.config.listeners[customHandlerKey];
|
||||||
const hasCustomHandler = is.function(customHandler);
|
const hasCustomHandler = is.function(customHandler);
|
||||||
@@ -532,10 +532,10 @@ class Listeners {
|
|||||||
if (returned !== false && is.function(defaultHandler)) {
|
if (returned !== false && is.function(defaultHandler)) {
|
||||||
defaultHandler.call(player, event);
|
defaultHandler.call(player, event);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Trigger custom and default handlers
|
// Trigger custom and default handlers
|
||||||
bind(element, type, defaultHandler, customHandlerKey, passive = true) {
|
bind = (element, type, defaultHandler, customHandlerKey, passive = true) => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const customHandler = player.config.listeners[customHandlerKey];
|
const customHandler = player.config.listeners[customHandlerKey];
|
||||||
const hasCustomHandler = is.function(customHandler);
|
const hasCustomHandler = is.function(customHandler);
|
||||||
@@ -547,10 +547,10 @@ class Listeners {
|
|||||||
(event) => this.proxy(event, defaultHandler, customHandlerKey),
|
(event) => this.proxy(event, defaultHandler, customHandlerKey),
|
||||||
passive && !hasCustomHandler,
|
passive && !hasCustomHandler,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Listen for control events
|
// Listen for control events
|
||||||
controls() {
|
controls = () => {
|
||||||
const { player } = this;
|
const { player } = this;
|
||||||
const { elements } = player;
|
const { elements } = player;
|
||||||
// IE doesn't support input event, so we fallback to change
|
// IE doesn't support input event, so we fallback to change
|
||||||
@@ -905,7 +905,7 @@ class Listeners {
|
|||||||
'volume',
|
'volume',
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Listeners;
|
export default Listeners;
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ 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);
|
||||||
|
|||||||
+38
-38
@@ -77,7 +77,7 @@ class Ads {
|
|||||||
/**
|
/**
|
||||||
* Load the IMA SDK
|
* Load the IMA SDK
|
||||||
*/
|
*/
|
||||||
load() {
|
load = () => {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,12 +95,12 @@ class Ads {
|
|||||||
} else {
|
} else {
|
||||||
this.ready();
|
this.ready();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ads instance ready
|
* Get the ads instance ready
|
||||||
*/
|
*/
|
||||||
ready() {
|
ready = () => {
|
||||||
// Double check we're enabled
|
// Double check we're enabled
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
destroy(this);
|
destroy(this);
|
||||||
@@ -120,7 +120,7 @@ class Ads {
|
|||||||
|
|
||||||
// Setup the IMA SDK
|
// Setup the IMA SDK
|
||||||
this.setupIMA();
|
this.setupIMA();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Build the tag URL
|
// Build the tag URL
|
||||||
get tagUrl() {
|
get tagUrl() {
|
||||||
@@ -153,7 +153,7 @@ class Ads {
|
|||||||
* properly place mid-rolls. After we create the ad display container, we initialize it. On
|
* properly place mid-rolls. After we create the ad display container, we initialize it. On
|
||||||
* mobile devices, this initialization is done as the result of a user action.
|
* mobile devices, this initialization is done as the result of a user action.
|
||||||
*/
|
*/
|
||||||
setupIMA() {
|
setupIMA = () => {
|
||||||
// Create the container for our advertisements
|
// Create the container for our advertisements
|
||||||
this.elements.container = createElement('div', {
|
this.elements.container = createElement('div', {
|
||||||
class: this.player.config.classNames.ads,
|
class: this.player.config.classNames.ads,
|
||||||
@@ -186,12 +186,12 @@ class Ads {
|
|||||||
|
|
||||||
// Request video ads to be pre-loaded
|
// Request video ads to be pre-loaded
|
||||||
this.requestAds();
|
this.requestAds();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request advertisements
|
* Request advertisements
|
||||||
*/
|
*/
|
||||||
requestAds() {
|
requestAds = () => {
|
||||||
const { container } = this.player.elements;
|
const { container } = this.player.elements;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -216,13 +216,13 @@ class Ads {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.onAdError(e);
|
this.onAdError(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the ad countdown
|
* Update the ad countdown
|
||||||
* @param {Boolean} start
|
* @param {Boolean} start
|
||||||
*/
|
*/
|
||||||
pollCountdown(start = false) {
|
pollCountdown = (start = false) => {
|
||||||
if (!start) {
|
if (!start) {
|
||||||
clearInterval(this.countdownTimer);
|
clearInterval(this.countdownTimer);
|
||||||
this.elements.container.removeAttribute('data-badge-text');
|
this.elements.container.removeAttribute('data-badge-text');
|
||||||
@@ -236,13 +236,13 @@ class Ads {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.countdownTimer = setInterval(update, 100);
|
this.countdownTimer = setInterval(update, 100);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called whenever the ads are ready inside the AdDisplayContainer
|
* This method is called whenever the ads are ready inside the AdDisplayContainer
|
||||||
* @param {Event} adsManagerLoadedEvent
|
* @param {Event} adsManagerLoadedEvent
|
||||||
*/
|
*/
|
||||||
onAdsManagerLoaded(event) {
|
onAdsManagerLoaded = (event) => {
|
||||||
// Load could occur after a source change (race condition)
|
// Load could occur after a source change (race condition)
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
@@ -273,9 +273,9 @@ class Ads {
|
|||||||
|
|
||||||
// Resolve our adsManager
|
// Resolve our adsManager
|
||||||
this.trigger('loaded');
|
this.trigger('loaded');
|
||||||
}
|
};
|
||||||
|
|
||||||
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) => {
|
||||||
@@ -294,7 +294,7 @@ class Ads {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is where all the event handling takes place. Retrieve the ad from the event. Some
|
* This is where all the event handling takes place. Retrieve the ad from the event. Some
|
||||||
@@ -302,7 +302,7 @@ class Ads {
|
|||||||
* https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type
|
* https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type
|
||||||
* @param {Event} event
|
* @param {Event} event
|
||||||
*/
|
*/
|
||||||
onAdEvent(event) {
|
onAdEvent = (event) => {
|
||||||
const { container } = this.player.elements;
|
const { container } = this.player.elements;
|
||||||
// Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)
|
// Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)
|
||||||
// don't have ad object associated
|
// don't have ad object associated
|
||||||
@@ -410,23 +410,23 @@ class Ads {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any ad error handling comes through here
|
* Any ad error handling comes through here
|
||||||
* @param {Event} event
|
* @param {Event} event
|
||||||
*/
|
*/
|
||||||
onAdError(event) {
|
onAdError = (event) => {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
this.player.debug.warn('Ads error', event);
|
this.player.debug.warn('Ads error', event);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events. This ensures
|
* Setup hooks for Plyr and window events. This ensures
|
||||||
* the mid- and post-roll launch at the correct time. And
|
* the mid- and post-roll launch at the correct time. And
|
||||||
* resize the advertisement when the player resizes
|
* resize the advertisement when the player resizes
|
||||||
*/
|
*/
|
||||||
listeners() {
|
listeners = () => {
|
||||||
const { container } = this.player.elements;
|
const { container } = this.player.elements;
|
||||||
let time;
|
let time;
|
||||||
|
|
||||||
@@ -464,12 +464,12 @@ class Ads {
|
|||||||
this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);
|
this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the adsManager and start playing advertisements
|
* Initialize the adsManager and start playing advertisements
|
||||||
*/
|
*/
|
||||||
play() {
|
play = () => {
|
||||||
const { container } = this.player.elements;
|
const { container } = this.player.elements;
|
||||||
|
|
||||||
if (!this.managerPromise) {
|
if (!this.managerPromise) {
|
||||||
@@ -503,12 +503,12 @@ class Ads {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume our video
|
* Resume our video
|
||||||
*/
|
*/
|
||||||
resumeContent() {
|
resumeContent = () => {
|
||||||
// Hide the advertisement container
|
// Hide the advertisement container
|
||||||
this.elements.container.style.zIndex = '';
|
this.elements.container.style.zIndex = '';
|
||||||
|
|
||||||
@@ -517,12 +517,12 @@ class Ads {
|
|||||||
|
|
||||||
// Play video
|
// Play video
|
||||||
silencePromise(this.player.media.play());
|
silencePromise(this.player.media.play());
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause our video
|
* Pause our video
|
||||||
*/
|
*/
|
||||||
pauseContent() {
|
pauseContent = () => {
|
||||||
// Show the advertisement container
|
// Show the advertisement container
|
||||||
this.elements.container.style.zIndex = 3;
|
this.elements.container.style.zIndex = 3;
|
||||||
|
|
||||||
@@ -531,7 +531,7 @@ class Ads {
|
|||||||
|
|
||||||
// Pause our video.
|
// Pause our video.
|
||||||
this.player.media.pause();
|
this.player.media.pause();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy the adsManager so we can grab new ads after this. If we don't then we're not
|
* Destroy the adsManager so we can grab new ads after this. If we don't then we're not
|
||||||
@@ -539,7 +539,7 @@ class Ads {
|
|||||||
* video requests. https://developers.google.com/interactive-
|
* video requests. https://developers.google.com/interactive-
|
||||||
* media-ads/docs/sdks/android/faq#8
|
* media-ads/docs/sdks/android/faq#8
|
||||||
*/
|
*/
|
||||||
cancel() {
|
cancel = () => {
|
||||||
// Pause our video
|
// Pause our video
|
||||||
if (this.initialized) {
|
if (this.initialized) {
|
||||||
this.resumeContent();
|
this.resumeContent();
|
||||||
@@ -550,12 +550,12 @@ class Ads {
|
|||||||
|
|
||||||
// Re-create our adsManager
|
// Re-create our adsManager
|
||||||
this.loadAds();
|
this.loadAds();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-create our adsManager
|
* Re-create our adsManager
|
||||||
*/
|
*/
|
||||||
loadAds() {
|
loadAds = () => {
|
||||||
// Tell our adsManager to go bye bye
|
// Tell our adsManager to go bye bye
|
||||||
this.managerPromise
|
this.managerPromise
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -576,13 +576,13 @@ class Ads {
|
|||||||
this.requestAds();
|
this.requestAds();
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles callbacks after an ad event was invoked
|
* Handles callbacks after an ad event was invoked
|
||||||
* @param {String} event - Event type
|
* @param {String} event - Event type
|
||||||
*/
|
*/
|
||||||
trigger(event, ...args) {
|
trigger = (event, ...args) => {
|
||||||
const handlers = this.events[event];
|
const handlers = this.events[event];
|
||||||
|
|
||||||
if (is.array(handlers)) {
|
if (is.array(handlers)) {
|
||||||
@@ -592,7 +592,7 @@ class Ads {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add event listeners
|
* Add event listeners
|
||||||
@@ -600,7 +600,7 @@ class Ads {
|
|||||||
* @param {Function} callback - Callback for when event occurs
|
* @param {Function} callback - Callback for when event occurs
|
||||||
* @return {Ads}
|
* @return {Ads}
|
||||||
*/
|
*/
|
||||||
on(event, callback) {
|
on = (event, callback) => {
|
||||||
if (!is.array(this.events[event])) {
|
if (!is.array(this.events[event])) {
|
||||||
this.events[event] = [];
|
this.events[event] = [];
|
||||||
}
|
}
|
||||||
@@ -608,7 +608,7 @@ class Ads {
|
|||||||
this.events[event].push(callback);
|
this.events[event].push(callback);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a safety timer for when the ad network doesn't respond for whatever reason.
|
* Setup a safety timer for when the ad network doesn't respond for whatever reason.
|
||||||
@@ -618,27 +618,27 @@ class Ads {
|
|||||||
* @param {Number} time
|
* @param {Number} time
|
||||||
* @param {String} from
|
* @param {String} from
|
||||||
*/
|
*/
|
||||||
startSafetyTimer(time, from) {
|
startSafetyTimer = (time, from) => {
|
||||||
this.player.debug.log(`Safety timer invoked from: ${from}`);
|
this.player.debug.log(`Safety timer invoked from: ${from}`);
|
||||||
|
|
||||||
this.safetyTimer = setTimeout(() => {
|
this.safetyTimer = setTimeout(() => {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
this.clearSafetyTimer('startSafetyTimer()');
|
this.clearSafetyTimer('startSafetyTimer()');
|
||||||
}, time);
|
}, time);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear our safety timer(s)
|
* Clear our safety timer(s)
|
||||||
* @param {String} from
|
* @param {String} from
|
||||||
*/
|
*/
|
||||||
clearSafetyTimer(from) {
|
clearSafetyTimer = (from) => {
|
||||||
if (!is.nullOrUndefined(this.safetyTimer)) {
|
if (!is.nullOrUndefined(this.safetyTimer)) {
|
||||||
this.player.debug.log(`Safety timer cleared from: ${from}`);
|
this.player.debug.log(`Safety timer cleared from: ${from}`);
|
||||||
|
|
||||||
clearTimeout(this.safetyTimer);
|
clearTimeout(this.safetyTimer);
|
||||||
this.safetyTimer = null;
|
this.safetyTimer = null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Ads;
|
export default Ads;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class PreviewThumbnails {
|
|||||||
return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;
|
return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
load = () => {
|
||||||
// Toggle the regular seek tooltip
|
// Toggle the regular seek tooltip
|
||||||
if (this.player.elements.display.seekTooltip) {
|
if (this.player.elements.display.seekTooltip) {
|
||||||
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
this.player.elements.display.seekTooltip.hidden = this.enabled;
|
||||||
@@ -126,10 +126,10 @@ class PreviewThumbnails {
|
|||||||
|
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
||||||
@@ -164,10 +164,10 @@ class PreviewThumbnails {
|
|||||||
Promise.all(promises).then(sortAndResolve);
|
Promise.all(promises).then(sortAndResolve);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// 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 = {
|
||||||
@@ -202,9 +202,9 @@ class PreviewThumbnails {
|
|||||||
tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;
|
tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
startMove(event) {
|
startMove = (event) => {
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -245,13 +245,13 @@ class PreviewThumbnails {
|
|||||||
|
|
||||||
// Download and show image
|
// Download and show image
|
||||||
this.showImageAtCurrentTime();
|
this.showImageAtCurrentTime();
|
||||||
}
|
};
|
||||||
|
|
||||||
endMove() {
|
endMove = () => {
|
||||||
this.toggleThumbContainer(false, true);
|
this.toggleThumbContainer(false, true);
|
||||||
}
|
};
|
||||||
|
|
||||||
startScrubbing(event) {
|
startScrubbing = (event) => {
|
||||||
// Only act on left mouse button (0), or touch device (event.button does not exist or is false)
|
// Only act on left mouse button (0), or touch device (event.button does not exist or is false)
|
||||||
if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {
|
if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {
|
||||||
this.mouseDown = true;
|
this.mouseDown = true;
|
||||||
@@ -265,9 +265,9 @@ class PreviewThumbnails {
|
|||||||
this.showImageAtCurrentTime();
|
this.showImageAtCurrentTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
endScrubbing() {
|
endScrubbing = () => {
|
||||||
this.mouseDown = false;
|
this.mouseDown = false;
|
||||||
|
|
||||||
// Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
// Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview
|
||||||
@@ -283,12 +283,12 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup hooks for Plyr and window events
|
* Setup hooks for Plyr and window events
|
||||||
*/
|
*/
|
||||||
listeners() {
|
listeners = () => {
|
||||||
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
// Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering
|
||||||
this.player.on('play', () => {
|
this.player.on('play', () => {
|
||||||
this.toggleThumbContainer(false, true);
|
this.toggleThumbContainer(false, true);
|
||||||
@@ -301,12 +301,12 @@ class PreviewThumbnails {
|
|||||||
this.player.on('timeupdate', () => {
|
this.player.on('timeupdate', () => {
|
||||||
this.lastTime = this.player.media.currentTime;
|
this.lastTime = this.player.media.currentTime;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create HTML elements for image containers
|
* Create HTML elements for image containers
|
||||||
*/
|
*/
|
||||||
render() {
|
render = () => {
|
||||||
// Create HTML element: plyr__preview-thumbnail-container
|
// Create HTML element: plyr__preview-thumbnail-container
|
||||||
this.elements.thumb.container = createElement('div', {
|
this.elements.thumb.container = createElement('div', {
|
||||||
class: this.player.config.classNames.previewThumbnails.thumbContainer,
|
class: this.player.config.classNames.previewThumbnails.thumbContainer,
|
||||||
@@ -339,18 +339,18 @@ class PreviewThumbnails {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);
|
this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);
|
||||||
}
|
};
|
||||||
|
|
||||||
destroy() {
|
destroy = () => {
|
||||||
if (this.elements.thumb.container) {
|
if (this.elements.thumb.container) {
|
||||||
this.elements.thumb.container.remove();
|
this.elements.thumb.container.remove();
|
||||||
}
|
}
|
||||||
if (this.elements.scrubbing.container) {
|
if (this.elements.scrubbing.container) {
|
||||||
this.elements.scrubbing.container.remove();
|
this.elements.scrubbing.container.remove();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
showImageAtCurrentTime() {
|
showImageAtCurrentTime = () => {
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
this.setScrubbingContainerSize();
|
this.setScrubbingContainerSize();
|
||||||
} else {
|
} else {
|
||||||
@@ -387,10 +387,10 @@ class PreviewThumbnails {
|
|||||||
this.showingThumb = thumbNum;
|
this.showingThumb = thumbNum;
|
||||||
this.loadImage(qualityIndex);
|
this.loadImage(qualityIndex);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Show the image that's currently specified in this.showingThumb
|
// Show the image that's currently specified in this.showingThumb
|
||||||
loadImage(qualityIndex = 0) {
|
loadImage = (qualityIndex = 0) => {
|
||||||
const thumbNum = this.showingThumb;
|
const thumbNum = this.showingThumb;
|
||||||
const thumbnail = this.thumbnails[qualityIndex];
|
const thumbnail = this.thumbnails[qualityIndex];
|
||||||
const { urlPrefix } = thumbnail;
|
const { urlPrefix } = thumbnail;
|
||||||
@@ -426,9 +426,9 @@ class PreviewThumbnails {
|
|||||||
this.currentImageElement.dataset.index = thumbNum;
|
this.currentImageElement.dataset.index = thumbNum;
|
||||||
this.removeOldImages(this.currentImageElement);
|
this.removeOldImages(this.currentImageElement);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) {
|
showImage = (previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) => {
|
||||||
this.player.debug.log(
|
this.player.debug.log(
|
||||||
`Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,
|
`Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,
|
||||||
);
|
);
|
||||||
@@ -449,10 +449,10 @@ class PreviewThumbnails {
|
|||||||
this.preloadNearby(thumbNum, true)
|
this.preloadNearby(thumbNum, true)
|
||||||
.then(this.preloadNearby(thumbNum, false))
|
.then(this.preloadNearby(thumbNum, false))
|
||||||
.then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));
|
.then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));
|
||||||
}
|
};
|
||||||
|
|
||||||
// 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') {
|
||||||
@@ -476,11 +476,11 @@ class PreviewThumbnails {
|
|||||||
}, removeDelay);
|
}, removeDelay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -527,10 +527,10 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// If user has been hovering current image for half a second, look for a higher quality one
|
// If user has been hovering current image for half a second, look for a higher quality one
|
||||||
getHigherQuality(currentQualityIndex, previewImage, frame, thumbFilename) {
|
getHigherQuality = (currentQualityIndex, previewImage, frame, thumbFilename) => {
|
||||||
if (currentQualityIndex < this.thumbnails.length - 1) {
|
if (currentQualityIndex < this.thumbnails.length - 1) {
|
||||||
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
// Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container
|
||||||
let previewImageHeight = previewImage.naturalHeight;
|
let previewImageHeight = previewImage.naturalHeight;
|
||||||
@@ -550,7 +550,7 @@ class PreviewThumbnails {
|
|||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
get currentImageContainer() {
|
get currentImageContainer() {
|
||||||
if (this.mouseDown) {
|
if (this.mouseDown) {
|
||||||
@@ -605,7 +605,7 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleThumbContainer(toggle = false, clearShowing = false) {
|
toggleThumbContainer = (toggle = false, clearShowing = false) => {
|
||||||
const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;
|
const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;
|
||||||
this.elements.thumb.container.classList.toggle(className, toggle);
|
this.elements.thumb.container.classList.toggle(className, toggle);
|
||||||
|
|
||||||
@@ -613,9 +613,9 @@ class PreviewThumbnails {
|
|||||||
this.showingThumb = null;
|
this.showingThumb = null;
|
||||||
this.showingThumbFilename = null;
|
this.showingThumbFilename = null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
toggleScrubbingContainer(toggle = false) {
|
toggleScrubbingContainer = (toggle = false) => {
|
||||||
const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;
|
const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;
|
||||||
this.elements.scrubbing.container.classList.toggle(className, toggle);
|
this.elements.scrubbing.container.classList.toggle(className, toggle);
|
||||||
|
|
||||||
@@ -623,17 +623,17 @@ class PreviewThumbnails {
|
|||||||
this.showingThumb = null;
|
this.showingThumb = null;
|
||||||
this.showingThumbFilename = null;
|
this.showingThumbFilename = null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
determineContainerAutoSizing() {
|
determineContainerAutoSizing = () => {
|
||||||
if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {
|
if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {
|
||||||
// This will prevent auto sizing in this.setThumbContainerSizeAndPos()
|
// This will prevent auto sizing in this.setThumbContainerSizeAndPos()
|
||||||
this.sizeSpecifiedInCSS = true;
|
this.sizeSpecifiedInCSS = true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS
|
// Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS
|
||||||
setThumbContainerSizeAndPos() {
|
setThumbContainerSizeAndPos = () => {
|
||||||
if (!this.sizeSpecifiedInCSS) {
|
if (!this.sizeSpecifiedInCSS) {
|
||||||
const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);
|
const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);
|
||||||
this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;
|
this.elements.thumb.imageContainer.style.height = `${this.thumbContainerHeight}px`;
|
||||||
@@ -653,9 +653,9 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setThumbContainerPos();
|
this.setThumbContainerPos();
|
||||||
}
|
};
|
||||||
|
|
||||||
setThumbContainerPos() {
|
setThumbContainerPos = () => {
|
||||||
const seekbarRect = this.player.elements.progress.getBoundingClientRect();
|
const seekbarRect = this.player.elements.progress.getBoundingClientRect();
|
||||||
const plyrRect = this.player.elements.container.getBoundingClientRect();
|
const plyrRect = this.player.elements.container.getBoundingClientRect();
|
||||||
const { container } = this.elements.thumb;
|
const { container } = this.elements.thumb;
|
||||||
@@ -674,20 +674,20 @@ class PreviewThumbnails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
container.style.left = `${previewPos}px`;
|
container.style.left = `${previewPos}px`;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Can't use 100% width, in case the video is a different aspect ratio to the video container
|
// Can't use 100% width, in case the video is a different aspect ratio to the video container
|
||||||
setScrubbingContainerSize() {
|
setScrubbingContainerSize = () => {
|
||||||
const { width, height } = fitRatio(this.thumbAspectRatio, {
|
const { width, height } = fitRatio(this.thumbAspectRatio, {
|
||||||
width: this.player.media.clientWidth,
|
width: this.player.media.clientWidth,
|
||||||
height: this.player.media.clientHeight,
|
height: this.player.media.clientHeight,
|
||||||
});
|
});
|
||||||
this.elements.scrubbing.container.style.width = `${width}px`;
|
this.elements.scrubbing.container.style.width = `${width}px`;
|
||||||
this.elements.scrubbing.container.style.height = `${height}px`;
|
this.elements.scrubbing.container.style.height = `${height}px`;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Sprites need to be offset to the correct location
|
// Sprites need to be offset to the correct location
|
||||||
setImageSizeAndOffset(previewImage, frame) {
|
setImageSizeAndOffset = (previewImage, frame) => {
|
||||||
if (!this.usingSprites) {
|
if (!this.usingSprites) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -703,7 +703,7 @@ class PreviewThumbnails {
|
|||||||
previewImage.style.left = `-${frame.x * multiplier}px`;
|
previewImage.style.left = `-${frame.x * multiplier}px`;
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
previewImage.style.top = `-${frame.y * multiplier}px`;
|
previewImage.style.top = `-${frame.y * multiplier}px`;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PreviewThumbnails;
|
export default PreviewThumbnails;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import fetch from '../utils/fetch';
|
|||||||
import is from '../utils/is';
|
import is from '../utils/is';
|
||||||
import loadScript from '../utils/load-script';
|
import loadScript from '../utils/load-script';
|
||||||
import { format, stripHTML } from '../utils/strings';
|
import { format, stripHTML } from '../utils/strings';
|
||||||
import { setAspectRatio } from '../utils/style';
|
import { roundAspectRatio, setAspectRatio } from '../utils/style';
|
||||||
import { buildUrlParams } from '../utils/urls';
|
import { buildUrlParams } from '../utils/urls';
|
||||||
|
|
||||||
// Parse Vimeo ID from URL
|
// Parse Vimeo ID from URL
|
||||||
@@ -104,7 +104,10 @@ const vimeo = {
|
|||||||
const src = format(player.config.urls.vimeo.iframe, id, params);
|
const src = format(player.config.urls.vimeo.iframe, id, params);
|
||||||
iframe.setAttribute('src', src);
|
iframe.setAttribute('src', src);
|
||||||
iframe.setAttribute('allowfullscreen', '');
|
iframe.setAttribute('allowfullscreen', '');
|
||||||
iframe.setAttribute('allow', 'autoplay,fullscreen,picture-in-picture');
|
iframe.setAttribute(
|
||||||
|
'allow',
|
||||||
|
['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; '),
|
||||||
|
);
|
||||||
|
|
||||||
// Set the referrer policy if required
|
// Set the referrer policy if required
|
||||||
if (!is.empty(referrerPolicy)) {
|
if (!is.empty(referrerPolicy)) {
|
||||||
@@ -291,7 +294,7 @@ 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 = roundAspectRatio(width, height);
|
||||||
setAspectRatio.call(this);
|
setAspectRatio.call(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import loadImage from '../utils/load-image';
|
|||||||
import loadScript from '../utils/load-script';
|
import loadScript from '../utils/load-script';
|
||||||
import { extend } from '../utils/objects';
|
import { extend } from '../utils/objects';
|
||||||
import { format, generateId } from '../utils/strings';
|
import { format, generateId } from '../utils/strings';
|
||||||
import { setAspectRatio } from '../utils/style';
|
import { roundAspectRatio, setAspectRatio } from '../utils/style';
|
||||||
|
|
||||||
// Parse YouTube ID from URL
|
// Parse YouTube ID from URL
|
||||||
function parseId(url) {
|
function parseId(url) {
|
||||||
@@ -90,7 +90,7 @@ const youtube = {
|
|||||||
ui.setTitle.call(this);
|
ui.setTitle.call(this);
|
||||||
|
|
||||||
// Set aspect ratio
|
// Set aspect ratio
|
||||||
this.embed.ratio = [width, height];
|
this.embed.ratio = roundAspectRatio(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAspectRatio.call(this);
|
setAspectRatio.call(this);
|
||||||
|
|||||||
Vendored
+29
-1
@@ -138,10 +138,15 @@ declare class Plyr {
|
|||||||
*/
|
*/
|
||||||
ratio?: string;
|
ratio?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access Elements cache
|
||||||
|
*/
|
||||||
|
elements: Plyr.Elements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current video Provider
|
* Returns the current video Provider
|
||||||
*/
|
*/
|
||||||
readonly provider: 'html5' | 'vimeo' | 'youtube';
|
readonly provider: Plyr.Provider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the native API for Vimeo or Youtube players
|
* Returns the native API for Vimeo or Youtube players
|
||||||
@@ -510,6 +515,8 @@ declare namespace Plyr {
|
|||||||
|
|
||||||
interface QualityOptions {
|
interface QualityOptions {
|
||||||
default: number;
|
default: number;
|
||||||
|
forced?: boolean;
|
||||||
|
onChange?: (quality: number) => void;
|
||||||
options: number[];
|
options: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,6 +567,27 @@ declare namespace Plyr {
|
|||||||
src?: string | string[];
|
src?: string | string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Elements {
|
||||||
|
buttons: {
|
||||||
|
airplay?: HTMLButtonElement;
|
||||||
|
captions?: HTMLButtonElement;
|
||||||
|
download?: HTMLButtonElement;
|
||||||
|
fastForward?: HTMLButtonElement;
|
||||||
|
fullscreen?: HTMLButtonElement;
|
||||||
|
mute?: HTMLButtonElement;
|
||||||
|
pip?: HTMLButtonElement;
|
||||||
|
play?: HTMLButtonElement | HTMLButtonElement[];
|
||||||
|
restart?: HTMLButtonElement;
|
||||||
|
rewind?: HTMLButtonElement;
|
||||||
|
settings?: HTMLButtonElement;
|
||||||
|
};
|
||||||
|
captions: HTMLElement | null;
|
||||||
|
container: HTMLElement | null;
|
||||||
|
controls: HTMLElement | null;
|
||||||
|
fullscreen: HTMLElement | null;
|
||||||
|
wrapper: HTMLElement | null;
|
||||||
|
}
|
||||||
|
|
||||||
interface SourceInfo {
|
interface SourceInfo {
|
||||||
/**
|
/**
|
||||||
* Note: YouTube and Vimeo are currently not supported as audio sources.
|
* Note: YouTube and Vimeo are currently not supported as audio sources.
|
||||||
|
|||||||
+36
-38
@@ -1,6 +1,6 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Plyr
|
// Plyr
|
||||||
// plyr.js v3.6.3
|
// plyr.js v3.6.7
|
||||||
// https://github.com/sampotts/plyr
|
// https://github.com/sampotts/plyr
|
||||||
// License: The MIT License (MIT)
|
// License: The MIT License (MIT)
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@@ -29,7 +29,7 @@ import loadSprite from './utils/load-sprite';
|
|||||||
import { clamp } from './utils/numbers';
|
import { clamp } from './utils/numbers';
|
||||||
import { cloneDeep, extend } from './utils/objects';
|
import { cloneDeep, extend } from './utils/objects';
|
||||||
import { silencePromise } from './utils/promise';
|
import { silencePromise } from './utils/promise';
|
||||||
import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateRatio } from './utils/style';
|
import { getAspectRatio, reduceAspectRatio, setAspectRatio, validateAspectRatio } from './utils/style';
|
||||||
import { parseUrl } from './utils/urls';
|
import { parseUrl } from './utils/urls';
|
||||||
|
|
||||||
// Private properties
|
// Private properties
|
||||||
@@ -206,7 +206,7 @@ class Plyr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unsupported or missing provider
|
// Unsupported or missing provider
|
||||||
if (is.empty(this.provider) || !Object.keys(providers).includes(this.provider)) {
|
if (is.empty(this.provider) || !Object.values(providers).includes(this.provider)) {
|
||||||
this.debug.error('Setup failed: Invalid provider');
|
this.debug.error('Setup failed: Invalid provider');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -355,7 +355,7 @@ class Plyr {
|
|||||||
/**
|
/**
|
||||||
* Play the media, or play the advertisement (if they are not blocked)
|
* Play the media, or play the advertisement (if they are not blocked)
|
||||||
*/
|
*/
|
||||||
play() {
|
play = () => {
|
||||||
if (!is.function(this.media.play)) {
|
if (!is.function(this.media.play)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -367,18 +367,18 @@ class Plyr {
|
|||||||
|
|
||||||
// Return the promise (for HTML5)
|
// Return the promise (for HTML5)
|
||||||
return this.media.play();
|
return this.media.play();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause the media
|
* Pause the media
|
||||||
*/
|
*/
|
||||||
pause() {
|
pause = () => {
|
||||||
if (!this.playing || !is.function(this.media.pause)) {
|
if (!this.playing || !is.function(this.media.pause)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.media.pause();
|
return this.media.pause();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get playing state
|
* Get playing state
|
||||||
@@ -412,7 +412,7 @@ class Plyr {
|
|||||||
* Toggle playback based on current status
|
* Toggle playback based on current status
|
||||||
* @param {Boolean} input
|
* @param {Boolean} input
|
||||||
*/
|
*/
|
||||||
togglePlay(input) {
|
togglePlay = (input) => {
|
||||||
// Toggle based on current state if nothing passed
|
// Toggle based on current state if nothing passed
|
||||||
const toggle = is.boolean(input) ? input : !this.playing;
|
const toggle = is.boolean(input) ? input : !this.playing;
|
||||||
|
|
||||||
@@ -421,42 +421,42 @@ class Plyr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.pause();
|
return this.pause();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop playback
|
* Stop playback
|
||||||
*/
|
*/
|
||||||
stop() {
|
stop = () => {
|
||||||
if (this.isHTML5) {
|
if (this.isHTML5) {
|
||||||
this.pause();
|
this.pause();
|
||||||
this.restart();
|
this.restart();
|
||||||
} else if (is.function(this.media.stop)) {
|
} else if (is.function(this.media.stop)) {
|
||||||
this.media.stop();
|
this.media.stop();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restart playback
|
* Restart playback
|
||||||
*/
|
*/
|
||||||
restart() {
|
restart = () => {
|
||||||
this.currentTime = 0;
|
this.currentTime = 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewind
|
* Rewind
|
||||||
* @param {Number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime
|
* @param {Number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime
|
||||||
*/
|
*/
|
||||||
rewind(seekTime) {
|
rewind = (seekTime) => {
|
||||||
this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;
|
this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fast forward
|
* Fast forward
|
||||||
* @param {Number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime
|
* @param {Number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime
|
||||||
*/
|
*/
|
||||||
forward(seekTime) {
|
forward = (seekTime) => {
|
||||||
this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;
|
this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seek to a time
|
* Seek to a time
|
||||||
@@ -582,18 +582,18 @@ class Plyr {
|
|||||||
* Increase volume
|
* Increase volume
|
||||||
* @param {Boolean} step - How much to decrease by (between 0 and 1)
|
* @param {Boolean} step - How much to decrease by (between 0 and 1)
|
||||||
*/
|
*/
|
||||||
increaseVolume(step) {
|
increaseVolume = (step) => {
|
||||||
const volume = this.media.muted ? 0 : this.volume;
|
const volume = this.media.muted ? 0 : this.volume;
|
||||||
this.volume = volume + (is.number(step) ? step : 0);
|
this.volume = volume + (is.number(step) ? step : 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrease volume
|
* Decrease volume
|
||||||
* @param {Boolean} step - How much to decrease by (between 0 and 1)
|
* @param {Boolean} step - How much to decrease by (between 0 and 1)
|
||||||
*/
|
*/
|
||||||
decreaseVolume(step) {
|
decreaseVolume = (step) => {
|
||||||
this.increaseVolume(-step);
|
this.increaseVolume(-step);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set muted state
|
* Set muted state
|
||||||
@@ -916,12 +916,12 @@ class Plyr {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is.string(input) || !validateRatio(input)) {
|
if (!is.string(input) || !validateAspectRatio(input)) {
|
||||||
this.debug.error(`Invalid aspect ratio specified (${input})`);
|
this.debug.error(`Invalid aspect ratio specified (${input})`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.config.ratio = input;
|
this.config.ratio = reduceAspectRatio(input);
|
||||||
|
|
||||||
setAspectRatio.call(this);
|
setAspectRatio.call(this);
|
||||||
}
|
}
|
||||||
@@ -1033,18 +1033,18 @@ class Plyr {
|
|||||||
* Trigger the airplay dialog
|
* Trigger the airplay dialog
|
||||||
* TODO: update player with state, support, enabled
|
* TODO: update player with state, support, enabled
|
||||||
*/
|
*/
|
||||||
airplay() {
|
airplay = () => {
|
||||||
// Show dialog if supported
|
// Show dialog if supported
|
||||||
if (support.airplay) {
|
if (support.airplay) {
|
||||||
this.media.webkitShowPlaybackTargetPicker();
|
this.media.webkitShowPlaybackTargetPicker();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the player controls
|
* Toggle the player controls
|
||||||
* @param {Boolean} [toggle] - Whether to show the controls
|
* @param {Boolean} [toggle] - Whether to show the controls
|
||||||
*/
|
*/
|
||||||
toggleControls(toggle) {
|
toggleControls = (toggle) => {
|
||||||
// Don't toggle if missing UI support or if it's audio
|
// Don't toggle if missing UI support or if it's audio
|
||||||
if (this.supported.ui && !this.isAudio) {
|
if (this.supported.ui && !this.isAudio) {
|
||||||
// Get state before change
|
// Get state before change
|
||||||
@@ -1074,34 +1074,34 @@ class Plyr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add event listeners
|
* Add event listeners
|
||||||
* @param {String} event - Event type
|
* @param {String} event - Event type
|
||||||
* @param {Function} callback - Callback for when event occurs
|
* @param {Function} callback - Callback for when event occurs
|
||||||
*/
|
*/
|
||||||
on(event, callback) {
|
on = (event, callback) => {
|
||||||
on.call(this, this.elements.container, event, callback);
|
on.call(this, this.elements.container, event, callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add event listeners once
|
* Add event listeners once
|
||||||
* @param {String} event - Event type
|
* @param {String} event - Event type
|
||||||
* @param {Function} callback - Callback for when event occurs
|
* @param {Function} callback - Callback for when event occurs
|
||||||
*/
|
*/
|
||||||
once(event, callback) {
|
once = (event, callback) => {
|
||||||
once.call(this, this.elements.container, event, callback);
|
once.call(this, this.elements.container, event, callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove event listeners
|
* Remove event listeners
|
||||||
* @param {String} event - Event type
|
* @param {String} event - Event type
|
||||||
* @param {Function} callback - Callback for when event occurs
|
* @param {Function} callback - Callback for when event occurs
|
||||||
*/
|
*/
|
||||||
off(event, callback) {
|
off = (event, callback) => {
|
||||||
off(this.elements.container, event, callback);
|
off(this.elements.container, event, callback);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy an instance
|
* Destroy an instance
|
||||||
@@ -1110,7 +1110,7 @@ class Plyr {
|
|||||||
* @param {Function} callback - Callback for when destroy is complete
|
* @param {Function} callback - Callback for when destroy is complete
|
||||||
* @param {Boolean} soft - Whether it's a soft destroy (for source changes etc)
|
* @param {Boolean} soft - Whether it's a soft destroy (for source changes etc)
|
||||||
*/
|
*/
|
||||||
destroy(callback, soft = false) {
|
destroy = (callback, soft = false) => {
|
||||||
if (!this.ready) {
|
if (!this.ready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1208,15 +1208,13 @@ class Plyr {
|
|||||||
// Vimeo does not always return
|
// Vimeo does not always return
|
||||||
setTimeout(done, 200);
|
setTimeout(done, 200);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for support for a mime type (HTML5 only)
|
* Check for support for a mime type (HTML5 only)
|
||||||
* @param {String} type - Mime type
|
* @param {String} type - Mime type
|
||||||
*/
|
*/
|
||||||
supports(type) {
|
supports = (type) => support.mime.call(this, type);
|
||||||
return support.mime.call(this, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for support
|
* Check for support
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Plyr Polyfilled Build
|
// Plyr Polyfilled Build
|
||||||
// plyr.js v3.6.3
|
// plyr.js v3.6.7
|
||||||
// https://github.com/sampotts/plyr
|
// https://github.com/sampotts/plyr
|
||||||
// License: The MIT License (MIT)
|
// License: The MIT License (MIT)
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|||||||
+4
-4
@@ -31,7 +31,7 @@ class Storage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(key) {
|
get = (key) => {
|
||||||
if (!Storage.supported || !this.enabled) {
|
if (!Storage.supported || !this.enabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -45,9 +45,9 @@ class Storage {
|
|||||||
const json = JSON.parse(store);
|
const json = JSON.parse(store);
|
||||||
|
|
||||||
return is.string(key) && key.length ? json[key] : json;
|
return is.string(key) && key.length ? json[key] : json;
|
||||||
}
|
};
|
||||||
|
|
||||||
set(object) {
|
set = (object) => {
|
||||||
// Bail if we don't have localStorage support or it's disabled
|
// Bail if we don't have localStorage support or it's disabled
|
||||||
if (!Storage.supported || !this.enabled) {
|
if (!Storage.supported || !this.enabled) {
|
||||||
return;
|
return;
|
||||||
@@ -71,7 +71,7 @@ class Storage {
|
|||||||
|
|
||||||
// Update storage
|
// Update storage
|
||||||
window.localStorage.setItem(this.key, JSON.stringify(storage));
|
window.localStorage.setItem(this.key, JSON.stringify(storage));
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Storage;
|
export default Storage;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
const browser = {
|
const browser = {
|
||||||
isIE: /* @cc_on!@ */ false || !!document.documentMode,
|
isIE: Boolean(window.document.documentMode),
|
||||||
isEdge: window.navigator.userAgent.includes('Edge'),
|
isEdge: window.navigator.userAgent.includes('Edge'),
|
||||||
isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
|
isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),
|
||||||
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
|
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
|
||||||
|
|||||||
+7
-1
@@ -13,7 +13,6 @@ 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 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);
|
||||||
@@ -21,6 +20,13 @@ const isCue = (input) => instanceOf(input, window.TextTrackCue) || instanceOf(in
|
|||||||
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 isElement = (input) =>
|
||||||
|
input !== null &&
|
||||||
|
typeof input === 'object' &&
|
||||||
|
input.nodeType === 1 &&
|
||||||
|
typeof input.style === 'object' &&
|
||||||
|
typeof input.ownerDocument === 'object';
|
||||||
|
|
||||||
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) ||
|
||||||
|
|||||||
+52
-5
@@ -2,9 +2,30 @@
|
|||||||
// Style utils
|
// Style utils
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
|
import { closest } from './arrays';
|
||||||
import is from './is';
|
import is from './is';
|
||||||
|
|
||||||
export function validateRatio(input) {
|
// Standard/common aspect ratios
|
||||||
|
const standardRatios = [
|
||||||
|
[1, 1],
|
||||||
|
[4, 3],
|
||||||
|
[3, 4],
|
||||||
|
[5, 4],
|
||||||
|
[4, 5],
|
||||||
|
[3, 2],
|
||||||
|
[2, 3],
|
||||||
|
[16, 10],
|
||||||
|
[10, 16],
|
||||||
|
[16, 9],
|
||||||
|
[9, 16],
|
||||||
|
[21, 9],
|
||||||
|
[9, 21],
|
||||||
|
[32, 9],
|
||||||
|
[9, 32],
|
||||||
|
].reduce((out, [x, y]) => ({ ...out, [x / y]: [x, y] }), {});
|
||||||
|
|
||||||
|
// Validate an aspect ratio
|
||||||
|
export function validateAspectRatio(input) {
|
||||||
if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {
|
if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -14,6 +35,7 @@ export function validateRatio(input) {
|
|||||||
return ratio.map(Number).every(is.number);
|
return ratio.map(Number).every(is.number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reduce an aspect ratio to it's lowest form
|
||||||
export function reduceAspectRatio(ratio) {
|
export function reduceAspectRatio(ratio) {
|
||||||
if (!is.array(ratio) || !ratio.every(is.number)) {
|
if (!is.array(ratio) || !ratio.every(is.number)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -26,8 +48,9 @@ export function reduceAspectRatio(ratio) {
|
|||||||
return [width / divider, height / divider];
|
return [width / divider, height / divider];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate an aspect ratio
|
||||||
export function getAspectRatio(input) {
|
export function getAspectRatio(input) {
|
||||||
const parse = (ratio) => (validateRatio(ratio) ? ratio.split(':').map(Number) : null);
|
const parse = (ratio) => (validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null);
|
||||||
// Try provided ratio
|
// Try provided ratio
|
||||||
let ratio = parse(input);
|
let ratio = parse(input);
|
||||||
|
|
||||||
@@ -58,10 +81,20 @@ export function setAspectRatio(input) {
|
|||||||
|
|
||||||
const { wrapper } = this.elements;
|
const { wrapper } = this.elements;
|
||||||
const ratio = getAspectRatio.call(this, input);
|
const ratio = getAspectRatio.call(this, input);
|
||||||
const [w, h] = is.array(ratio) ? ratio : [0, 0];
|
|
||||||
const padding = (100 / w) * h;
|
|
||||||
|
|
||||||
wrapper.style.paddingBottom = `${padding}%`;
|
if (!is.array(ratio)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const [x, y] = ratio;
|
||||||
|
const useNative = window.CSS ? window.CSS.supports(`aspect-ratio: ${x}/${y}`) : false;
|
||||||
|
const padding = (100 / x) * y;
|
||||||
|
|
||||||
|
if (useNative) {
|
||||||
|
wrapper.style.aspectRatio = `${x}/${y}`;
|
||||||
|
} else {
|
||||||
|
wrapper.style.paddingBottom = `${padding}%`;
|
||||||
|
}
|
||||||
|
|
||||||
// For Vimeo we have an extra <div> to hide the standard controls and UI
|
// For Vimeo we have an extra <div> to hide the standard controls and UI
|
||||||
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
|
if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
|
||||||
@@ -80,4 +113,18 @@ export function setAspectRatio(input) {
|
|||||||
return { padding, ratio };
|
return { padding, ratio };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Round an aspect ratio to closest standard ratio
|
||||||
|
export function roundAspectRatio(x, y, tolerance = 0.05) {
|
||||||
|
const ratio = x / y;
|
||||||
|
const closestRatio = closest(Object.keys(standardRatios), ratio);
|
||||||
|
|
||||||
|
// Check match is within tolerance
|
||||||
|
if (Math.abs(closestRatio - ratio) <= tolerance) {
|
||||||
|
return standardRatios[closestRatio];
|
||||||
|
}
|
||||||
|
|
||||||
|
// No match
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
|
||||||
export default { setAspectRatio };
|
export default { setAspectRatio };
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
.plyr__poster {
|
.plyr__poster {
|
||||||
background-color: #000;
|
background-color: var(--plyr-video-background, $plyr-video-background);
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
@@ -20,3 +20,8 @@
|
|||||||
.plyr--stopped.plyr__poster-enabled .plyr__poster {
|
.plyr--stopped.plyr__poster-enabled .plyr__poster {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow interaction with YouTube controls while paused
|
||||||
|
.plyr--youtube.plyr--paused.plyr__poster-enabled:not(.plyr--stopped) .plyr__poster {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
margin-right: $plyr-control-spacing;
|
margin-right: $plyr-control-spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: calc(#{$plyr-bp-md} - 1px)) {
|
@media (max-width: ($plyr-bp-md - 1px)) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
$plyr-color-main: var(--plyr-color-main, hsl(198, 100%, 50%)) !default;
|
$plyr-color-main: var(--plyr-color-main, hsl(198, 100%, 50%)) !default;
|
||||||
|
$plyr-video-background: var(--plyr-video-background, rgba(0,0,0,1)) !default;
|
||||||
|
|
||||||
// Grayscale
|
// Grayscale
|
||||||
$plyr-color-gray-900: hsl(216, 15%, 16%) !default;
|
$plyr-color-gray-900: hsl(216, 15%, 16%) !default;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// Container
|
// Container
|
||||||
.plyr--video {
|
.plyr--video {
|
||||||
background: #000;
|
background: var(--plyr-video-background, $plyr-video-background);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&.plyr--menu-open {
|
&.plyr--menu-open {
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.plyr__video-wrapper {
|
.plyr__video-wrapper {
|
||||||
background: #000;
|
background: var(--plyr-video-background, $plyr-video-background);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -26,16 +26,23 @@ $embed-padding: ((100 / 16) * 9);
|
|||||||
|
|
||||||
.plyr__video-embed,
|
.plyr__video-embed,
|
||||||
.plyr__video-wrapper--fixed-ratio {
|
.plyr__video-wrapper--fixed-ratio {
|
||||||
height: 0;
|
@supports not (aspect-ratio: 16 / 9) {
|
||||||
padding-bottom: to-percentage($embed-padding);
|
height: 0;
|
||||||
|
padding-bottom: to-percentage($embed-padding);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plyr__video-embed iframe,
|
.plyr__video-embed iframe,
|
||||||
.plyr__video-wrapper--fixed-ratio video {
|
.plyr__video-wrapper--fixed-ratio video {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
height: 100%;
|
||||||
left: 0;
|
left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the full custom UI is supported
|
// If the full custom UI is supported
|
||||||
|
|||||||
+11
-2
@@ -16,7 +16,7 @@ const resolve = require('rollup-plugin-node-resolve');
|
|||||||
const sass = require('gulp-sass');
|
const sass = require('gulp-sass');
|
||||||
const postcss = require('gulp-postcss');
|
const postcss = require('gulp-postcss');
|
||||||
const autoprefixer = require('autoprefixer');
|
const autoprefixer = require('autoprefixer');
|
||||||
const clean = require('postcss-clean');
|
const cssnano = require('cssnano');
|
||||||
const customprops = require('postcss-custom-properties');
|
const customprops = require('postcss-custom-properties');
|
||||||
// Images
|
// Images
|
||||||
const svgstore = require('gulp-svgstore');
|
const svgstore = require('gulp-svgstore');
|
||||||
@@ -118,6 +118,7 @@ Object.entries(build.js).forEach(([filename, entry]) => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
plugins: ['@babel/plugin-proposal-class-properties'],
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
exclude: [/\/core-js\//],
|
exclude: [/\/core-js\//],
|
||||||
}),
|
}),
|
||||||
@@ -157,7 +158,15 @@ Object.entries(build.css).forEach(([filename, entry]) => {
|
|||||||
.src(src)
|
.src(src)
|
||||||
.pipe(plumber())
|
.pipe(plumber())
|
||||||
.pipe(sass())
|
.pipe(sass())
|
||||||
.pipe(postcss([customprops(), autoprefixer(), clean()]))
|
.pipe(
|
||||||
|
postcss([
|
||||||
|
customprops(),
|
||||||
|
autoprefixer(),
|
||||||
|
cssnano({
|
||||||
|
preset: 'default',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
)
|
||||||
.pipe(size(sizeOptions))
|
.pipe(size(sizeOptions))
|
||||||
.pipe(gulp.dest(dist)),
|
.pipe(gulp.dest(dist)),
|
||||||
);
|
);
|
||||||
|
|||||||
+5
-50
@@ -10,15 +10,13 @@ const gulp = require('gulp');
|
|||||||
const gitbranch = require('git-branch');
|
const gitbranch = require('git-branch');
|
||||||
const rename = require('gulp-rename');
|
const rename = require('gulp-rename');
|
||||||
const replace = require('gulp-replace');
|
const replace = require('gulp-replace');
|
||||||
const ansi = require('ansi-colors');
|
const { green, cyan, bold } = require('colorette');
|
||||||
const log = require('fancy-log');
|
const log = require('fancy-log');
|
||||||
const open = require('gulp-open');
|
const open = require('gulp-open');
|
||||||
const size = require('gulp-size');
|
const size = require('gulp-size');
|
||||||
const through = require('through2');
|
|
||||||
// Deployment
|
// Deployment
|
||||||
const aws = require('aws-sdk');
|
const aws = require('aws-sdk');
|
||||||
const publish = require('gulp-awspublish');
|
const publish = require('gulp-awspublish');
|
||||||
const FastlyPurge = require('fastly-purge');
|
|
||||||
// Configs
|
// Configs
|
||||||
const pkg = require('../package.json');
|
const pkg = require('../package.json');
|
||||||
const deploy = require('../deploy.json');
|
const deploy = require('../deploy.json');
|
||||||
@@ -53,14 +51,6 @@ const paths = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get credentials
|
|
||||||
let credentials = {};
|
|
||||||
try {
|
|
||||||
credentials = require('../credentials.json'); //eslint-disable-line
|
|
||||||
} catch (e) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get branch info
|
// Get branch info
|
||||||
const branch = {
|
const branch = {
|
||||||
current: gitbranch.sync(),
|
current: gitbranch.sync(),
|
||||||
@@ -128,7 +118,7 @@ gulp.task('version', (done) => {
|
|||||||
|
|
||||||
const { domain } = deploy.cdn;
|
const { domain } = deploy.cdn;
|
||||||
|
|
||||||
log(`Updating version in files to ${ansi.green.bold(version)}...`);
|
log(`Updating version in files to ${green(bold(version))}...`);
|
||||||
|
|
||||||
// Replace versioned URLs in source
|
// Replace versioned URLs in source
|
||||||
const files = ['plyr.js', 'plyr.polyfilled.js', 'config/defaults.js'];
|
const files = ['plyr.js', 'plyr.polyfilled.js', 'config/defaults.js'];
|
||||||
@@ -156,7 +146,7 @@ gulp.task('cdn', (done) => {
|
|||||||
throw new Error('No publisher instance. Check AWS configuration.');
|
throw new Error('No publisher instance. Check AWS configuration.');
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`);
|
log(`Uploading ${green(bold(pkg.version))} to ${cyan(domain)}...`);
|
||||||
|
|
||||||
// Upload to CDN
|
// Upload to CDN
|
||||||
return (
|
return (
|
||||||
@@ -177,41 +167,6 @@ gulp.task('cdn', (done) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Purge the fastly cache incase any 403/404 are cached
|
|
||||||
gulp.task('purge', () => {
|
|
||||||
if (!Object.keys(credentials).includes('fastly')) {
|
|
||||||
throw new Error('Fastly credentials required to purge cache.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { fastly } = credentials;
|
|
||||||
const list = [];
|
|
||||||
|
|
||||||
return gulp
|
|
||||||
.src(paths.upload)
|
|
||||||
.pipe(
|
|
||||||
through.obj((file, enc, cb) => {
|
|
||||||
const filename = file.path.split('/').pop();
|
|
||||||
list.push(`${versionPath}${filename.replace(minSuffix, '')}`);
|
|
||||||
cb(null);
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.on('end', () => {
|
|
||||||
const purge = new FastlyPurge(fastly.token);
|
|
||||||
|
|
||||||
list.forEach((url) => {
|
|
||||||
log(`Purging ${ansi.cyan(url)}...`);
|
|
||||||
|
|
||||||
purge.url(url, (error, result) => {
|
|
||||||
if (error) {
|
|
||||||
log.error(error);
|
|
||||||
} else if (result) {
|
|
||||||
log(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Publish to demo bucket
|
// Publish to demo bucket
|
||||||
gulp.task('demo', (done) => {
|
gulp.task('demo', (done) => {
|
||||||
if (!canDeploy()) {
|
if (!canDeploy()) {
|
||||||
@@ -226,7 +181,7 @@ gulp.task('demo', (done) => {
|
|||||||
throw new Error('No publisher instance. Check AWS configuration.');
|
throw new Error('No publisher instance. Check AWS configuration.');
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`Uploading ${ansi.green.bold(pkg.version)} to ${ansi.cyan(domain)}...`);
|
log(`Uploading ${green(bold(pkg.version))} to ${cyan(domain)}...`);
|
||||||
|
|
||||||
// Replace versioned files in README.md
|
// Replace versioned files in README.md
|
||||||
gulp
|
gulp
|
||||||
@@ -271,4 +226,4 @@ gulp.task('open', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Do everything
|
// Do everything
|
||||||
gulp.task('deploy', gulp.series('cdn', 'demo', 'purge', 'open'));
|
gulp.task('deploy', gulp.series('cdn', 'demo', 'open'));
|
||||||
|
|||||||
Reference in New Issue
Block a user