Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2679c5898e | |||
| efb7401e6d | |||
| 60a0f0c979 | |||
| 5d168d0e14 | |||
| f964e34d8c | |||
| 021ba0b8e9 | |||
| 96d371546c | |||
| e1780a4df0 | |||
| e5e169a1e2 | |||
| 5eda498516 | |||
| 44b5d9f6b9 | |||
| 24deff0e2d | |||
| 0933b48c2a | |||
| 71578e07ec | |||
| 671325dd17 | |||
| ad1989e45e | |||
| f9ac98bc6d | |||
| 544ab0086b | |||
| 13bf80d372 | |||
| e2fb922d73 | |||
| a6cc85c437 | |||
| d061be5d2b | |||
| dc2feedd79 | |||
| f8e4ba36e5 | |||
| f3d5389587 | |||
| d9ffb10b93 | |||
| 1186377b25 | |||
| 8616895e57 | |||
| 2cf5a22c85 | |||
| 763eb2df80 | |||
| 8bbf66a0fb | |||
| 676b46e4a7 | |||
| 82a119c67f | |||
| 6fd4389887 | |||
| 1e1a548459 | |||
| 8db9b53a8f | |||
| ba33fd8277 | |||
| 8071feda18 | |||
| a49b73cd01 | |||
| 8226493a9e | |||
| 38a8a0e8a1 | |||
| 6eeca8b5d1 | |||
| bf51ce4414 | |||
| 5ad614e251 | |||
| 93c890603d | |||
| 29fb4dfc2b | |||
| 7de9fd1d65 | |||
| 566c059832 | |||
| 0c9572f0a1 | |||
| c99607c85a | |||
| e2010bcd1a | |||
| e9f1b55f51 | |||
| 4f5152f526 | |||
| de9b53045a | |||
| df458c5e7a | |||
| e206554146 | |||
| e422806c44 | |||
| b6ddf144f4 | |||
| 86406ee59a | |||
| 81c5477f1d | |||
| ac64350a5f | |||
| 333619f1e3 | |||
| 17dcb63c26 | |||
| e04b90c9c0 | |||
| f62e1da01a | |||
| 2fe949629f | |||
| 20f2ddc11d | |||
| 004528a65c | |||
| 39c7bd40c2 | |||
| 43879e08f4 | |||
| 5ed7aa6620 | |||
| 47750b6aad | |||
| de7832eb8b | |||
| 52ea5bd0ab | |||
| 457d112df7 | |||
| 22cdec9d38 | |||
| d72e502107 | |||
| 94055f0772 | |||
| ede9323524 | |||
| c45f428f61 | |||
| b61ba02f3d | |||
| ea4d91d2a0 | |||
| 22d524ac9d | |||
| 8584f6a1db |
+7
-12
@@ -5,8 +5,12 @@
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"globals": { "Plyr": false, "jQuery": false },
|
||||
"globals": {
|
||||
"Plyr": false,
|
||||
"jQuery": false
|
||||
},
|
||||
"rules": {
|
||||
"import/no-cycle": 1,
|
||||
"no-const-assign": 1,
|
||||
"no-shadow": 0,
|
||||
"no-this-before-super": 1,
|
||||
@@ -21,17 +25,8 @@
|
||||
"eqeqeq": [2, "always"],
|
||||
"one-var": [2, "never"],
|
||||
"comma-dangle": [2, "always-multiline"],
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{
|
||||
"name": "event",
|
||||
"message": "Use local parameter instead."
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"message": "Use local parameter instead."
|
||||
}
|
||||
],
|
||||
"spaced-comment": [2, "always"],
|
||||
"no-restricted-globals": 2,
|
||||
"no-param-reassign": [2, { "props": false }]
|
||||
},
|
||||
"parserOptions": {
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report an issue or unexpected behaviour with Plyr
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
Before creating the issue, please make sure that...
|
||||
|
||||
* You aren't getting any errors in your own code, causing the problem.
|
||||
* You are using the latest version of Plyr.
|
||||
* There isn't already an open issue for your problem.
|
||||
* You are following the documentation correctly (https://github.com/sampotts/plyr/)
|
||||
* Your problem doesn't happen if you remove Plyr and use native HTML5 media (when applicable).
|
||||
|
||||
For problems with autoplay, see our FAQ (https://github.com/sampotts/plyr/wiki/FAQ)
|
||||
|
||||
If you have multiple unrelated problems, create separate issues rather than combining them into one.
|
||||
|
||||
Note that leaving sections blank or being vague will make it difficult for us to troubleshoot and we may close the issue.
|
||||
-->
|
||||
|
||||
### Expected behaviour
|
||||
|
||||
### Actual behaviour
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
### Environment
|
||||
|
||||
- Browser:
|
||||
- Version:
|
||||
- Operating System:
|
||||
- Version:
|
||||
|
||||
### Console errors (if any)
|
||||
|
||||
### Link to where the bug is happening
|
||||
|
||||
<!--
|
||||
This link can be either to our demo at https://plyr.io/ if the problem can be observed there, or to a code playground with a **minimal** test case that demonstrates the problem.
|
||||
|
||||
You can use one of our prepared templates to get started creating the test case:
|
||||
|
||||
* HTML5 video: https://codepen.io/pen?template=bKeqpr
|
||||
* HTML5 audio: https://codepen.io/pen?template=rKLywR
|
||||
* YouTube: https://codepen.io/pen?template=GGqbbJ
|
||||
* Vimeo: https://codepen.io/pen?template=bKeXNq
|
||||
* Dash.js integration: https://codepen.io/pen?template=zaBgBy
|
||||
* Hls.js integration: https://codepen.io/pen?template=oyLKQb
|
||||
* Shaka Player integration: https://codepen.io/pen?template=ZRpzZO
|
||||
|
||||
It's important that you keep the issue description and replication demo **minimal**. If your replication includes frameworks, libraries or customizations, this makes it much harder to understand the problem and find the bug. For more help on how to create the demo, see https://github.com/sampotts/plyr/wiki/Writing-helpful-issue-descriptions
|
||||
|
||||
-->
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: New feature
|
||||
about: Request new functionality
|
||||
---
|
||||
|
||||
<!--
|
||||
Please describe the behaviour that you want to add, and why. Be as clear as possible to avoid confusion.
|
||||
|
||||
If you want to request multiple features that aren't directly related, then create one issue per feature.
|
||||
-->
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Improvement
|
||||
about: Request a change that isn't a bug or new feature
|
||||
---
|
||||
|
||||
<!--
|
||||
Please describe the behaviour that you want to change, and why. Be as clear as possible to avoid confusion.
|
||||
|
||||
If you want to request multiple changes that aren't directly related, then create one issue per change.
|
||||
-->
|
||||
@@ -1,17 +1,3 @@
|
||||
<!---
|
||||
Please use this issue template as it makes replicating and fixing the issue easier!
|
||||
--->
|
||||
PLEASE USE OUR SPECIFIC ISSUE TEMPLATES for bug reports, features and improvement suggestions.
|
||||
|
||||
### Expected behaviour
|
||||
|
||||
### Actual behaviour
|
||||
|
||||
### Environment
|
||||
|
||||
- Browser:
|
||||
- Version:
|
||||
- Operating System:
|
||||
- Version:
|
||||
|
||||
### Steps to reproduce
|
||||
-
|
||||
Our issue tracker is not for support questions. If you need help, follow our support instructions: https://github.com/sampotts/plyr/blob/master/contributing.md#support
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
|
||||
### Checklist
|
||||
- [ ] Use `develop` as the base branch
|
||||
- [ ] Exclude the gulp build from the PR
|
||||
- [ ] Exclude the gulp build (`/dist` changes) from the PR
|
||||
- [ ] Test on [supported browsers](https://github.com/sampotts/plyr#browser-support)
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
aws.json
|
||||
credentials.json
|
||||
*.mp4
|
||||
!dist/blank.mp4
|
||||
index-*.html
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
package-lock.json
|
||||
*.webm
|
||||
/package-lock.json
|
||||
.idea/
|
||||
|
||||
.idea/
|
||||
@@ -2,3 +2,10 @@ demo
|
||||
.github
|
||||
.vscode
|
||||
*.code-workspace
|
||||
credentials.json
|
||||
bundles.json
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
*.mp4
|
||||
*.webm
|
||||
!dist/blank.mp4
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 4,
|
||||
"printWidth": 120,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
linters:
|
||||
eslint:
|
||||
files:
|
||||
ignore:
|
||||
- 'node_modules/*'
|
||||
+5
-4
@@ -1,7 +1,8 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 'lts/*'
|
||||
node_js: lts/*
|
||||
|
||||
script:
|
||||
- npm run lint
|
||||
- npm run build
|
||||
- bash .travis/prevent-base-master.sh
|
||||
- bash .travis/omit-dist.sh
|
||||
- npm run lint
|
||||
- npm run build
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/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
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/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,61 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
We welcome bug reports, feature requests and pull requests. If you want to help us out, please follow these guidelines, in order to avoid redundant work.
|
||||
|
||||
## Commenting
|
||||
When commenting, keep a civil tone and stay on topic. Don't ask for support (use [Stack Overflow](https://stackoverflow.com/) or [our Slack](https://bit.ly/plyr-chat) for that), or post "+1" or "I agree" type of comments. Use the emojis instead.
|
||||
|
||||
Asking for the status on issues is discouraged. Unless someone has explicitly said in an issue that it's work in progress, most likely that means no one is working on it. We have a lot to do, and it may not be a top priority for us.
|
||||
|
||||
We *may* moderate discussions. We do this to avoid threads being "hijacked", to avoid confusion in case the content is misleading or outdated, and to avoid bothering people with github notifications.
|
||||
|
||||
## Reporting issues
|
||||
|
||||
Our GitHub issue tracker is for bug reports and feature requests. Don't ask for support here. Use [Stack Overflow](https://stackoverflow.com/) or [our Slack](https://bit.ly/plyr-chat) for that.
|
||||
|
||||
Please verify that your issue hasn't already been answered by our [FAQ](https://github.com/sampotts/plyr/wiki/FAQ), and that there isn't already an open issue for it.
|
||||
|
||||
When applicable, check that your problem doesn't happen without Plyr (see [FAQ#1](https://github.com/sampotts/plyr/wiki/FAQ#1-does-plyr-work-with--)).
|
||||
|
||||
Verify that you are following the documentation, are using the latest version of Plyr, and aren't getting any errors in your own code, causing the issues.
|
||||
|
||||
Create one issue per problem or request (i.e. don't combine multiple problems to one git issue). Describe the issue as detailed as possible (see [Replication](#replication))
|
||||
|
||||
## Replication
|
||||
|
||||
In order to solve a problem, we first need to understand it. Please answer these questions when reporting issues or asking for help in [our Slack](https://bit.ly/plyr-chat).
|
||||
|
||||
* Does it happen only with specific options and/or specific browsers?
|
||||
* Does is happen only with HTML5 video, audio, YouTube, Vimeo or a specific library?
|
||||
* Does the issue happen on [our demo](https://plyr.io/)? If not, please recreate it with a **minimal** example online. You can use our Codepen templates to get started:
|
||||
* [HTML5 video](https://codepen.io/pen?template=bKeqpr)
|
||||
* [HTML5 audio](https://codepen.io/pen?template=rKLywR)
|
||||
* [YouTube](https://codepen.io/pen?template=GGqbbJ)
|
||||
* [Vimeo](https://codepen.io/pen?template=bKeXNq)
|
||||
* [Dash.js integration](https://codepen.io/pen?template=zaBgBy)
|
||||
* [Hls.js integration](https://codepen.io/pen?template=oyLKQb)
|
||||
* [Shaka Player integration](https://codepen.io/pen?template=ZRpzZO)
|
||||
|
||||
It's important that you keep the issue description and replication demo **minimal**. If your replication includes frameworks, libraries or customizations, this makes it harder to debug and understand the issue. While it may be relevant to bring this up (ex: "I need Plyr to trigger the event sooner or it breaks Framework X"), please keep these out of your replication demo if they aren't strictly needed to reproduce the issue. If the issue is caused by something a library does that Plyr doesn't handle, it's more helpful for us if you find out what it is, and replicate the same problem without the library. Otherwise any developer who is willing to help out with the issue has to understand the frameworks, libraries and customizations of *your* choice, or no one will try to fix your issue because it's too much work.
|
||||
|
||||
## Requesting features and improvements
|
||||
|
||||
If you are missing something in Plyr, you can create a GitHub issue for this as well. Since we prioritize fixing bugs first, and may have a lot of other suggestions and architectural changes to work on as well, these may not be at the top of our list.
|
||||
|
||||
If your suggestion is important or urgent to you, you may want to first ensure it's something we want to have in Plyr, and then contribute it as a pull request. [Our Slack](https://bit.ly/plyr-chat) is the best place for questions like this.
|
||||
|
||||
## Contributing features and documentation
|
||||
|
||||
* Fork Plyr, and create a new branch in your fork, based on the **develop** branch
|
||||
|
||||
* To test locally, you can use the demo. First make sure you have installed the dependencies with `npm install` or `yarn`. Run `gulp` to build while you are working, and run a local server from the repository root directory. If you have Python installed, this command should work: `python -m SimpleHTTPServer 8080`. Then go to `http://localhost:8080/demo/`
|
||||
|
||||
* Develop and test your modifications.
|
||||
|
||||
* Preferably commit your changes as independent logical chunks, with meaningful messages. Make sure you do not commit unnecessary files or changes, such as the build output, or logging and breakpoints you added for testing.
|
||||
|
||||
* If your modifications changes the documented behavior or add new features, document these changes in readme.md.
|
||||
|
||||
* When finished, push the changes to your GitHub repository and send a pull request to **develop**. 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.
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"name": "plyr",
|
||||
"description": "A simple HTML5 media player using custom controls",
|
||||
"homepage": "http://plyr.io",
|
||||
"keywords": [
|
||||
"Audio",
|
||||
"Video",
|
||||
"HTML5 Audio",
|
||||
"HTML5 Video"
|
||||
],
|
||||
"authors": [
|
||||
"Sam Potts <sam@potts.es>"
|
||||
],
|
||||
"dependencies": {},
|
||||
"main": [
|
||||
"dist/plyr.css",
|
||||
"dist/plyr.js",
|
||||
"dist/plyr.svg",
|
||||
"src/less/plyr.less",
|
||||
"src/scss/plyr.scss",
|
||||
"src/js/plyr.js"
|
||||
],
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
".gitignore"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/sampotts/plyr.git"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -1,3 +1,53 @@
|
||||
# v3.3.23
|
||||
|
||||
- Add support for YouTube's hl param (thanks @renaudleo)
|
||||
- Fix for captions positioning when no controls (thanks @friday and @mjfwebb)
|
||||
- Fix #1108: Make sure youtube.onReady doesn't run twice (thanks @friday)
|
||||
- Fix for WebKit redraw loop on the `<input type="range">` elements
|
||||
|
||||
# v3.3.22
|
||||
|
||||
- Travis & CI improvements (thanks @friday)
|
||||
- Add navigator.languages fallback for iOS 9 (thanks @friday)
|
||||
|
||||
# v3.3.21
|
||||
|
||||
- Hide currentTime and progress for streams (thanks @mimse)
|
||||
- Fixed condition check (thanks @mimse)
|
||||
- Handle undefined this.player.elements.buttons.play (thanks @klassicd)
|
||||
- Fix captions.toggle() if there is no toggle button (thanks @friday)
|
||||
|
||||
# v3.3.20
|
||||
|
||||
- Fix for bug where controls wouldn't show on hover over YouTube video
|
||||
|
||||
# v3.3.19
|
||||
|
||||
- Remove `pointer-events: none` on embed `<iframe>` to comply with YouTube ToS
|
||||
|
||||
# 3.3.18
|
||||
|
||||
- Ads are now only supported on HTML5 videos as it violates terms of service for YouTube and Vimeo 😢
|
||||
- Fix i18n defaults path on README (thanks @meyt!)
|
||||
- Minor increaseVolume and decreaseVolume changes (thanks @friday!)
|
||||
|
||||
# v3.3.17
|
||||
|
||||
- Fix YouTube muting after seeking with the progress slider (thanks @friday!)
|
||||
- Respect preload="none" when setting quality if the media hasn't been loaded some other way (thanks @friday!)
|
||||
|
||||
# v3.3.16
|
||||
|
||||
- Fixed regression relating the play button status (fixes #1048)
|
||||
|
||||
# v3.3.15
|
||||
|
||||
- Fix for error relating to play buttons when switching source
|
||||
|
||||
# v3.3.14
|
||||
|
||||
- Fix sprite loading regression
|
||||
|
||||
# v3.3.13
|
||||
|
||||
You guessed it, a load of awesome changes from contributors:
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Contributing
|
||||
|
||||
We welcome bug reports, feature requests and pull requests. If you want to help us out, please follow these guidelines, in order to avoid redundant work.
|
||||
|
||||
## Support
|
||||
|
||||
Before asking questions, read our [documentation](https://github.com/sampotts/plyr) and [FAQ](https://github.com/sampotts/plyr/wiki/FAQ).
|
||||
|
||||
If these doesn't answer your question
|
||||
* Use [Stack Overflow](https://stackoverflow.com/) for questions that doesn't directly involve Plyr. This includes for example how to use Javascript, CSS or HTML5 media in general, and how to use other frameworks, libraries and technology.
|
||||
* Use [our Slack](https://bit.ly/plyr-chat) if you need help using Plyr or have questions about Plyr.
|
||||
|
||||
## Commenting
|
||||
When commenting, keep a civil tone and stay on topic. Don't ask for [support](#support), or post "+1" or "I agree" type of comments. Use the emojis instead.
|
||||
|
||||
Asking for the status on issues is discouraged. Unless someone has explicitly said in an issue that it's work in progress, most likely that means no one is working on it. We have a lot to do, and it may not be a top priority for us.
|
||||
|
||||
We *may* moderate discussions. We do this to avoid threads being "hijacked", to avoid confusion in case the content is misleading or outdated, and to avoid bothering people with github notifications.
|
||||
|
||||
## Creating issues
|
||||
|
||||
Please follow the instructions in our issue templates. Don't use github issues to ask for [support](#support).
|
||||
|
||||
## Contributing features and documentation
|
||||
|
||||
* If you want to add a feature or make critical changes, you may want to ensure that this is something we also want (so you don't waste your time). Ask us about this in the corresponding issue if there is one, or on [our Slack](https://bit.ly/plyr-chat) otherwise.
|
||||
|
||||
* Fork Plyr, and create a new branch in your fork, based on the **develop** branch
|
||||
|
||||
* To test locally, you can use the demo. First make sure you have installed the dependencies with `npm install` or `yarn`. Run `gulp` to build while you are working, and run a local server from the repository root directory. If you have Python installed, this command should work: `python -m SimpleHTTPServer 8080`. Then go to `http://localhost:8080/demo/`
|
||||
|
||||
* Develop and test your modifications.
|
||||
|
||||
* Preferably commit your changes as independent logical chunks, with meaningful messages. Make sure you do not commit unnecessary files or changes, such as the build output, or logging and breakpoints you added for testing.
|
||||
|
||||
* If your modifications changes the documented behavior or add new features, document these changes in readme.md.
|
||||
|
||||
* When finished, push the changes to your GitHub repository and send a pull request to **develop**. 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.
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+10
-2
@@ -1874,7 +1874,7 @@ typeof navigator === "object" && (function () {
|
||||
// webpack (using a build step causes webpack #1617). Grunt verifies that
|
||||
// this value matches package.json during build.
|
||||
// See: https://github.com/getsentry/raven-js/issues/465
|
||||
VERSION: '3.26.2',
|
||||
VERSION: '3.26.3',
|
||||
|
||||
debug: false,
|
||||
|
||||
@@ -2351,7 +2351,9 @@ typeof navigator === "object" && (function () {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._globalOptions.stacktrace || (options && options.stacktrace)) {
|
||||
// Always attempt to get stacktrace if message is empty.
|
||||
// It's the only way to provide any helpful information to the user.
|
||||
if (this._globalOptions.stacktrace || options.stacktrace || data.message === '') {
|
||||
// fingerprint on msg, not stack trace (legacy behavior, could be revisited)
|
||||
data.fingerprint = data.fingerprint == null ? msg : data.fingerprint;
|
||||
|
||||
@@ -3508,6 +3510,11 @@ typeof navigator === "object" && (function () {
|
||||
options
|
||||
);
|
||||
|
||||
var ex = data.exception.values[0];
|
||||
if (ex.type == null && ex.value === '') {
|
||||
ex.value = 'Unrecoverable error caught';
|
||||
}
|
||||
|
||||
// Move mechanism from options to exception interface
|
||||
// We do this, as requiring user to pass `{exception:{mechanism:{ ... }}}` would be
|
||||
// too much
|
||||
@@ -4130,6 +4137,7 @@ typeof navigator === "object" && (function () {
|
||||
tooltips: {
|
||||
controls: true
|
||||
},
|
||||
clickToPlay: false,
|
||||
/* controls: [
|
||||
'play-large',
|
||||
'restart',
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -96,7 +96,7 @@
|
||||
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" type="video/mp4" size="576">
|
||||
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4" type="video/mp4" size="720">
|
||||
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4" type="video/mp4" size="1080">
|
||||
<source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4" type="video/mp4" size="1440">
|
||||
<!-- <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1440p.mp4" type="video/mp4" size="1440"> -->
|
||||
|
||||
<!-- Caption files -->
|
||||
<track kind="captions" label="English" srclang="en" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt"
|
||||
|
||||
+18
-9
@@ -57,6 +57,7 @@ import Raven from 'raven-js';
|
||||
tooltips: {
|
||||
controls: true,
|
||||
},
|
||||
clickToPlay: false,
|
||||
/* controls: [
|
||||
'play-large',
|
||||
'restart',
|
||||
@@ -143,7 +144,11 @@ import Raven from 'raven-js';
|
||||
// Set a new source
|
||||
function newSource(type, init) {
|
||||
// Bail if new type isn't known, it's the current type, or current type is empty (video is default) and new type is video
|
||||
if (!(type in types) || (!init && type === currentType) || (!currentType.length && type === types.video)) {
|
||||
if (
|
||||
!(type in types) ||
|
||||
(!init && type === currentType) ||
|
||||
(!currentType.length && type === types.video)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -215,10 +220,12 @@ import Raven from 'raven-js';
|
||||
case types.youtube:
|
||||
player.source = {
|
||||
type: 'video',
|
||||
sources: [{
|
||||
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
|
||||
provider: 'youtube',
|
||||
}],
|
||||
sources: [
|
||||
{
|
||||
src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
|
||||
provider: 'youtube',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
break;
|
||||
@@ -226,10 +233,12 @@ import Raven from 'raven-js';
|
||||
case types.vimeo:
|
||||
player.source = {
|
||||
type: 'video',
|
||||
sources: [{
|
||||
src: 'https://vimeo.com/76979871',
|
||||
provider: 'vimeo',
|
||||
}],
|
||||
sources: [
|
||||
{
|
||||
src: 'https://vimeo.com/76979871',
|
||||
provider: 'vimeo',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+214
-170
@@ -11,60 +11,92 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var getConstructor = function getConstructor(input) {
|
||||
return input !== null && typeof input !== 'undefined' ? input.constructor : null;
|
||||
};
|
||||
|
||||
var instanceOf = function instanceOf(input, constructor) {
|
||||
return Boolean(input && constructor && input instanceof constructor);
|
||||
};
|
||||
var isNullOrUndefined = function isNullOrUndefined(input) {
|
||||
return input === null || typeof input === 'undefined';
|
||||
};
|
||||
var isObject = function isObject(input) {
|
||||
return getConstructor(input) === Object;
|
||||
};
|
||||
var isNumber = function isNumber(input) {
|
||||
return getConstructor(input) === Number && !Number.isNaN(input);
|
||||
};
|
||||
var isString = function isString(input) {
|
||||
return getConstructor(input) === String;
|
||||
};
|
||||
var isBoolean = function isBoolean(input) {
|
||||
return getConstructor(input) === Boolean;
|
||||
};
|
||||
var isFunction = function isFunction(input) {
|
||||
return getConstructor(input) === Function;
|
||||
};
|
||||
var isArray = function isArray(input) {
|
||||
return Array.isArray(input);
|
||||
};
|
||||
var isWeakMap = function isWeakMap(input) {
|
||||
return instanceOf(input, WeakMap);
|
||||
};
|
||||
var isNodeList = function isNodeList(input) {
|
||||
return instanceOf(input, NodeList);
|
||||
};
|
||||
var isElement = function isElement(input) {
|
||||
return instanceOf(input, Element);
|
||||
};
|
||||
var isTextNode = function isTextNode(input) {
|
||||
return getConstructor(input) === Text;
|
||||
};
|
||||
var isEvent = function isEvent(input) {
|
||||
return instanceOf(input, Event);
|
||||
};
|
||||
var isCue = function isCue(input) {
|
||||
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
||||
};
|
||||
var isTrack = function isTrack(input) {
|
||||
return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);
|
||||
};
|
||||
|
||||
var isEmpty = function isEmpty(input) {
|
||||
return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;
|
||||
};
|
||||
|
||||
var isUrl = function isUrl(input) {
|
||||
// Accept a URL object
|
||||
if (instanceOf(input, window.URL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add the protocol if required
|
||||
var string = input;
|
||||
if (!input.startsWith('http://') || !input.startsWith('https://')) {
|
||||
string = 'http://' + input;
|
||||
}
|
||||
|
||||
try {
|
||||
return !isEmpty(new URL(string).hostname);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var is = {
|
||||
object: function object(input) {
|
||||
return getConstructor(input) === Object;
|
||||
},
|
||||
number: function number(input) {
|
||||
return getConstructor(input) === Number && !Number.isNaN(input);
|
||||
},
|
||||
string: function string(input) {
|
||||
return getConstructor(input) === String;
|
||||
},
|
||||
boolean: function boolean(input) {
|
||||
return getConstructor(input) === Boolean;
|
||||
},
|
||||
function: function _function(input) {
|
||||
return getConstructor(input) === Function;
|
||||
},
|
||||
array: function array(input) {
|
||||
return !is.nullOrUndefined(input) && Array.isArray(input);
|
||||
},
|
||||
weakMap: function weakMap(input) {
|
||||
return instanceOf(input, WeakMap);
|
||||
},
|
||||
nodeList: function nodeList(input) {
|
||||
return instanceOf(input, NodeList);
|
||||
},
|
||||
element: function element(input) {
|
||||
return instanceOf(input, Element);
|
||||
},
|
||||
textNode: function textNode(input) {
|
||||
return getConstructor(input) === Text;
|
||||
},
|
||||
event: function event(input) {
|
||||
return instanceOf(input, Event);
|
||||
},
|
||||
cue: function cue(input) {
|
||||
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
||||
},
|
||||
track: function track(input) {
|
||||
return instanceOf(input, TextTrack) || !is.nullOrUndefined(input) && is.string(input.kind);
|
||||
},
|
||||
url: function url(input) {
|
||||
return !is.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
|
||||
},
|
||||
nullOrUndefined: function nullOrUndefined(input) {
|
||||
return input === null || typeof input === 'undefined';
|
||||
},
|
||||
empty: function empty(input) {
|
||||
return is.nullOrUndefined(input) || (is.string(input) || is.array(input) || is.nodeList(input)) && !input.length || is.object(input) && !Object.keys(input).length;
|
||||
}
|
||||
nullOrUndefined: isNullOrUndefined,
|
||||
object: isObject,
|
||||
number: isNumber,
|
||||
string: isString,
|
||||
boolean: isBoolean,
|
||||
function: isFunction,
|
||||
array: isArray,
|
||||
weakMap: isWeakMap,
|
||||
nodeList: isNodeList,
|
||||
element: isElement,
|
||||
textNode: isTextNode,
|
||||
event: isEvent,
|
||||
cue: isCue,
|
||||
track: isTrack,
|
||||
url: isUrl,
|
||||
empty: isEmpty
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
@@ -769,22 +801,17 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Quality
|
||||
Object.defineProperty(player.media, 'quality', {
|
||||
get: function get$$1() {
|
||||
get: function get() {
|
||||
// Get sources
|
||||
var sources = html5.getSources.call(player);
|
||||
|
||||
var _sources$filter = sources.filter(function (source) {
|
||||
var source = sources.find(function (source) {
|
||||
return source.getAttribute('src') === player.source;
|
||||
}),
|
||||
_sources$filter2 = slicedToArray(_sources$filter, 1),
|
||||
source = _sources$filter2[0];
|
||||
});
|
||||
|
||||
// Return size, if match is found
|
||||
|
||||
|
||||
return source && Number(source.getAttribute('size'));
|
||||
},
|
||||
set: function set$$1(input) {
|
||||
set: function set(input) {
|
||||
// Get sources
|
||||
var sources = html5.getSources.call(player);
|
||||
|
||||
@@ -799,25 +826,30 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// Get current state
|
||||
var currentTime = player.currentTime,
|
||||
playing = player.playing;
|
||||
var _player$media = player.media,
|
||||
currentTime = _player$media.currentTime,
|
||||
paused = _player$media.paused,
|
||||
preload = _player$media.preload,
|
||||
readyState = _player$media.readyState;
|
||||
|
||||
// Set new source
|
||||
|
||||
player.media.src = source.getAttribute('src');
|
||||
|
||||
// Restore time
|
||||
var onLoadedMetaData = function onLoadedMetaData() {
|
||||
player.currentTime = currentTime;
|
||||
};
|
||||
player.once('loadedmetadata', onLoadedMetaData);
|
||||
// Prevent loading if preload="none" and the current source isn't loaded (#1044)
|
||||
if (preload !== 'none' || readyState) {
|
||||
// Restore time
|
||||
player.once('loadedmetadata', function () {
|
||||
player.currentTime = currentTime;
|
||||
|
||||
// Load new source
|
||||
player.media.load();
|
||||
// Resume playing
|
||||
if (!paused) {
|
||||
player.play();
|
||||
}
|
||||
});
|
||||
|
||||
// Resume playing
|
||||
if (playing) {
|
||||
player.play();
|
||||
// Load new source
|
||||
player.media.load();
|
||||
}
|
||||
|
||||
// Trigger change event
|
||||
@@ -1137,6 +1169,51 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return Storage;
|
||||
}();
|
||||
|
||||
// ==========================================================================
|
||||
// Fetch wrapper
|
||||
// Using XHR to avoid issues with older browsers
|
||||
// ==========================================================================
|
||||
|
||||
function fetch(url) {
|
||||
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
// Check for CORS support
|
||||
if (!('withCredentials' in request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
request.addEventListener('load', function () {
|
||||
if (responseType === 'text') {
|
||||
try {
|
||||
resolve(JSON.parse(request.responseText));
|
||||
} catch (e) {
|
||||
resolve(request.responseText);
|
||||
}
|
||||
} else {
|
||||
resolve(request.response);
|
||||
}
|
||||
});
|
||||
|
||||
request.addEventListener('error', function () {
|
||||
throw new Error(request.status);
|
||||
});
|
||||
|
||||
request.open('GET', url, true);
|
||||
|
||||
// Set the required response type
|
||||
request.responseType = responseType;
|
||||
|
||||
request.send();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
// Load an external SVG sprite
|
||||
@@ -1406,7 +1483,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
if ('class' in attributes) {
|
||||
if (attributes.class.includes(this.config.classNames.control)) {
|
||||
if (!attributes.class.includes(this.config.classNames.control)) {
|
||||
attributes.class += ' ' + this.config.classNames.control;
|
||||
}
|
||||
} else {
|
||||
@@ -1855,6 +1932,16 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.
|
||||
// https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415
|
||||
// https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062
|
||||
// https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338
|
||||
if (this.duration >= Math.pow(2, 32)) {
|
||||
toggleHidden(this.elements.display.currentTime, true);
|
||||
toggleHidden(this.elements.progress, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update ARIA values
|
||||
if (is.element(this.elements.inputs.seek)) {
|
||||
this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);
|
||||
@@ -2675,12 +2762,9 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
target = this.elements.container;
|
||||
}
|
||||
|
||||
// Inject controls HTML
|
||||
if (is.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
// Inject controls HTML (needs to be before captions, hence "afterbegin")
|
||||
var insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';
|
||||
target[insertMethod]('afterbegin', container);
|
||||
|
||||
// Find the elements if need be
|
||||
if (!is.element(this.elements.controls)) {
|
||||
@@ -2709,51 +2793,6 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
// Fetch wrapper
|
||||
// Using XHR to avoid issues with older browsers
|
||||
// ==========================================================================
|
||||
|
||||
function fetch$1(url) {
|
||||
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
// Check for CORS support
|
||||
if (!('withCredentials' in request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
request.addEventListener('load', function () {
|
||||
if (responseType === 'text') {
|
||||
try {
|
||||
resolve(JSON.parse(request.responseText));
|
||||
} catch (e) {
|
||||
resolve(request.responseText);
|
||||
}
|
||||
} else {
|
||||
resolve(request.response);
|
||||
}
|
||||
});
|
||||
|
||||
request.addEventListener('error', function () {
|
||||
throw new Error(request.statusText);
|
||||
});
|
||||
|
||||
request.open('GET', url, true);
|
||||
|
||||
// Set the required response type
|
||||
request.responseType = responseType;
|
||||
|
||||
request.send();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
@@ -2833,7 +2872,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var url = parseUrl(src);
|
||||
|
||||
if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {
|
||||
fetch$1(src, 'blob').then(function (blob) {
|
||||
fetch(src, 'blob').then(function (blob) {
|
||||
track.setAttribute('src', window.URL.createObjectURL(blob));
|
||||
}).catch(function () {
|
||||
removeElement(track);
|
||||
@@ -2849,7 +2888,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// * active: The state preferred by user settings or config
|
||||
// * toggled: The real captions state
|
||||
|
||||
var languages = dedupe(Array.from(navigator.languages || navigator.userLanguage).map(function (language) {
|
||||
var languages = dedupe(Array.from(navigator.languages || navigator.language || navigator.userLanguage).map(function (language) {
|
||||
return language.split('-')[0];
|
||||
}));
|
||||
|
||||
@@ -2977,8 +3016,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle state
|
||||
this.elements.buttons.captions.pressed = active;
|
||||
// Toggle button if it's enabled
|
||||
if (this.elements.buttons.captions) {
|
||||
this.elements.buttons.captions.pressed = active;
|
||||
}
|
||||
|
||||
// Add class hook
|
||||
toggleClass(this.elements.container, activeClass, active);
|
||||
@@ -3997,11 +4038,9 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// If there's a play button, set label
|
||||
if (is.nodeList(this.elements.buttons.play)) {
|
||||
Array.from(this.elements.buttons.play).forEach(function (button) {
|
||||
button.setAttribute('aria-label', label);
|
||||
});
|
||||
}
|
||||
Array.from(this.elements.buttons.play || []).forEach(function (button) {
|
||||
button.setAttribute('aria-label', label);
|
||||
});
|
||||
|
||||
// Set iframe title
|
||||
// https://github.com/sampotts/plyr/issues/124
|
||||
@@ -4081,7 +4120,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
|
||||
|
||||
// Set state
|
||||
Array.from(this.elements.buttons.play).forEach(function (target) {
|
||||
Array.from(this.elements.buttons.play || []).forEach(function (target) {
|
||||
target.pressed = _this3.playing;
|
||||
});
|
||||
|
||||
@@ -4575,9 +4614,11 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
};
|
||||
|
||||
// Play/pause toggle
|
||||
Array.from(this.player.elements.buttons.play).forEach(function (button) {
|
||||
bind(button, 'click', _this4.player.togglePlay, 'play');
|
||||
});
|
||||
if (this.player.elements.buttons.play) {
|
||||
Array.from(this.player.elements.buttons.play).forEach(function (button) {
|
||||
bind(button, 'click', _this4.player.togglePlay, 'play');
|
||||
});
|
||||
}
|
||||
|
||||
// Pause
|
||||
bind(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');
|
||||
@@ -4779,33 +4820,28 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Detect "natural" scroll - suppored on OS X Safari only
|
||||
// Other browsers on OS X will be inverted until support improves
|
||||
var inverted = event.webkitDirectionInvertedFromDevice;
|
||||
var step = 1 / 50;
|
||||
var direction = 0;
|
||||
|
||||
// Scroll down (or up on natural) to decrease
|
||||
if (event.deltaY < 0 || event.deltaX > 0) {
|
||||
if (inverted) {
|
||||
_this4.player.decreaseVolume(step);
|
||||
direction = -1;
|
||||
} else {
|
||||
_this4.player.increaseVolume(step);
|
||||
direction = 1;
|
||||
}
|
||||
}
|
||||
// Get delta from event. Invert if `inverted` is true
|
||||
|
||||
// Scroll up (or down on natural) to increase
|
||||
if (event.deltaY > 0 || event.deltaX < 0) {
|
||||
if (inverted) {
|
||||
_this4.player.increaseVolume(step);
|
||||
direction = 1;
|
||||
} else {
|
||||
_this4.player.decreaseVolume(step);
|
||||
direction = -1;
|
||||
}
|
||||
}
|
||||
var _map = [event.deltaX, -event.deltaY].map(function (value) {
|
||||
return inverted ? -value : value;
|
||||
}),
|
||||
_map2 = slicedToArray(_map, 2),
|
||||
x = _map2[0],
|
||||
y = _map2[1];
|
||||
|
||||
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
|
||||
|
||||
|
||||
var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
|
||||
|
||||
// Change the volume by 2%
|
||||
_this4.player.increaseVolume(direction / 50);
|
||||
|
||||
// Don't break page scrolling at max and min
|
||||
if (direction === 1 && _this4.player.media.volume < 1 || direction === -1 && _this4.player.media.volume > 0) {
|
||||
var volume = _this4.player.media.volume;
|
||||
|
||||
if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}, 'volume', false);
|
||||
@@ -5253,7 +5289,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
player.media = replaceElement(wrapper, player.media);
|
||||
|
||||
// Get poster image
|
||||
fetch$1(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
|
||||
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
|
||||
if (is.empty(response)) {
|
||||
return;
|
||||
}
|
||||
@@ -5668,7 +5704,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
if (is.string(key) && !is.empty(key)) {
|
||||
var url = format(this.config.urls.youtube.api, videoId, key);
|
||||
|
||||
fetch$1(url).then(function (result) {
|
||||
fetch(url).then(function (result) {
|
||||
if (is.object(result)) {
|
||||
_this2.config.title = result.items[0].snippet.title;
|
||||
ui.setTitle.call(_this2);
|
||||
@@ -5743,6 +5779,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
videoId: videoId,
|
||||
playerVars: {
|
||||
autoplay: player.config.autoplay ? 1 : 0, // Autoplay
|
||||
hl: player.config.hl, // iframe interface language
|
||||
controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported
|
||||
rel: 0, // No related vids
|
||||
showinfo: 0, // Hide info
|
||||
@@ -5793,6 +5830,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
triggerEvent.call(player, player.media, 'ratechange');
|
||||
},
|
||||
onReady: function onReady(event) {
|
||||
// Bail if onReady has already been called. See issue #1108
|
||||
if (is.function(player.media.play)) {
|
||||
return;
|
||||
}
|
||||
// Get the instance
|
||||
var instance = event.target;
|
||||
|
||||
@@ -5824,8 +5865,8 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return Number(instance.getCurrentTime());
|
||||
},
|
||||
set: function set(time) {
|
||||
// If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
|
||||
if (player.paused) {
|
||||
// If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
|
||||
if (player.paused && !player.embed.hasPlayed) {
|
||||
player.embed.mute();
|
||||
}
|
||||
|
||||
@@ -6744,7 +6785,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}, {
|
||||
key: 'enabled',
|
||||
get: function get$$1() {
|
||||
return this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId);
|
||||
return this.player.isHTML5 && this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId);
|
||||
}
|
||||
}, {
|
||||
key: 'tagUrl',
|
||||
@@ -6752,7 +6793,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var params = {
|
||||
AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',
|
||||
AV_CHANNELID: '5a0458dc28a06145e4519d21',
|
||||
AV_URL: location.hostname,
|
||||
AV_URL: window.location.hostname,
|
||||
cb: Date.now(),
|
||||
AV_WIDTH: 640,
|
||||
AV_HEIGHT: 480,
|
||||
@@ -7048,7 +7089,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
this.elements.container.className = '';
|
||||
|
||||
// Get attributes from URL and set config
|
||||
if (url.searchParams.length) {
|
||||
if (url.search.length) {
|
||||
var truthy = ['1', 'true'];
|
||||
|
||||
if (truthy.includes(url.searchParams.get('autoplay'))) {
|
||||
@@ -7062,6 +7103,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// YouTube requires the playsinline in the URL
|
||||
if (this.isYouTube) {
|
||||
this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));
|
||||
this.config.hl = url.searchParams.get('hl');
|
||||
} else {
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
@@ -7301,7 +7343,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
*/
|
||||
value: function increaseVolume(step) {
|
||||
var volume = this.media.muted ? 0 : this.volume;
|
||||
this.volume = volume + (is.number(step) ? step : 1);
|
||||
this.volume = volume + (is.number(step) ? step : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7312,8 +7354,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}, {
|
||||
key: 'decreaseVolume',
|
||||
value: function decreaseVolume(step) {
|
||||
var volume = this.media.muted ? 0 : this.volume;
|
||||
this.volume = volume - (is.number(step) ? step : 1);
|
||||
this.increaseVolume(-step);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7397,6 +7438,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
value: function on$$1(event, callback) {
|
||||
on.call(this, this.elements.container, event, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add event listeners once
|
||||
* @param {string} event - Event type
|
||||
@@ -7408,6 +7450,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
value: function once$$1(event, callback) {
|
||||
once.call(this, this.elements.container, event, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove event listeners
|
||||
* @param {string} event - Event type
|
||||
@@ -7683,8 +7726,9 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Faux duration set via config
|
||||
var fauxDuration = parseFloat(this.config.duration);
|
||||
|
||||
// Media duration can be NaN before the media has loaded
|
||||
var duration = (this.media || {}).duration || 0;
|
||||
// Media duration can be NaN or Infinity before the media has loaded
|
||||
var realDuration = (this.media || {}).duration;
|
||||
var duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;
|
||||
|
||||
// If config duration is funky, use regular duration
|
||||
return fauxDuration || duration;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+212
-168
@@ -5397,60 +5397,92 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var getConstructor = function getConstructor(input) {
|
||||
return input !== null && typeof input !== 'undefined' ? input.constructor : null;
|
||||
};
|
||||
|
||||
var instanceOf = function instanceOf(input, constructor) {
|
||||
return Boolean(input && constructor && input instanceof constructor);
|
||||
};
|
||||
var isNullOrUndefined = function isNullOrUndefined(input) {
|
||||
return input === null || typeof input === 'undefined';
|
||||
};
|
||||
var isObject = function isObject(input) {
|
||||
return getConstructor(input) === Object;
|
||||
};
|
||||
var isNumber = function isNumber(input) {
|
||||
return getConstructor(input) === Number && !Number.isNaN(input);
|
||||
};
|
||||
var isString = function isString(input) {
|
||||
return getConstructor(input) === String;
|
||||
};
|
||||
var isBoolean = function isBoolean(input) {
|
||||
return getConstructor(input) === Boolean;
|
||||
};
|
||||
var isFunction = function isFunction(input) {
|
||||
return getConstructor(input) === Function;
|
||||
};
|
||||
var isArray = function isArray(input) {
|
||||
return Array.isArray(input);
|
||||
};
|
||||
var isWeakMap = function isWeakMap(input) {
|
||||
return instanceOf(input, WeakMap);
|
||||
};
|
||||
var isNodeList = function isNodeList(input) {
|
||||
return instanceOf(input, NodeList);
|
||||
};
|
||||
var isElement = function isElement(input) {
|
||||
return instanceOf(input, Element);
|
||||
};
|
||||
var isTextNode = function isTextNode(input) {
|
||||
return getConstructor(input) === Text;
|
||||
};
|
||||
var isEvent = function isEvent(input) {
|
||||
return instanceOf(input, Event);
|
||||
};
|
||||
var isCue = function isCue(input) {
|
||||
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
||||
};
|
||||
var isTrack = function isTrack(input) {
|
||||
return instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);
|
||||
};
|
||||
|
||||
var isEmpty = function isEmpty(input) {
|
||||
return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;
|
||||
};
|
||||
|
||||
var isUrl = function isUrl(input) {
|
||||
// Accept a URL object
|
||||
if (instanceOf(input, window.URL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add the protocol if required
|
||||
var string = input;
|
||||
if (!input.startsWith('http://') || !input.startsWith('https://')) {
|
||||
string = 'http://' + input;
|
||||
}
|
||||
|
||||
try {
|
||||
return !isEmpty(new URL(string).hostname);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var is$1 = {
|
||||
object: function object(input) {
|
||||
return getConstructor(input) === Object;
|
||||
},
|
||||
number: function number(input) {
|
||||
return getConstructor(input) === Number && !Number.isNaN(input);
|
||||
},
|
||||
string: function string(input) {
|
||||
return getConstructor(input) === String;
|
||||
},
|
||||
boolean: function boolean(input) {
|
||||
return getConstructor(input) === Boolean;
|
||||
},
|
||||
function: function _function(input) {
|
||||
return getConstructor(input) === Function;
|
||||
},
|
||||
array: function array(input) {
|
||||
return !is$1.nullOrUndefined(input) && Array.isArray(input);
|
||||
},
|
||||
weakMap: function weakMap(input) {
|
||||
return instanceOf(input, WeakMap);
|
||||
},
|
||||
nodeList: function nodeList(input) {
|
||||
return instanceOf(input, NodeList);
|
||||
},
|
||||
element: function element(input) {
|
||||
return instanceOf(input, Element);
|
||||
},
|
||||
textNode: function textNode(input) {
|
||||
return getConstructor(input) === Text;
|
||||
},
|
||||
event: function event(input) {
|
||||
return instanceOf(input, Event);
|
||||
},
|
||||
cue: function cue(input) {
|
||||
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
||||
},
|
||||
track: function track(input) {
|
||||
return instanceOf(input, TextTrack) || !is$1.nullOrUndefined(input) && is$1.string(input.kind);
|
||||
},
|
||||
url: function url(input) {
|
||||
return !is$1.nullOrUndefined(input) && /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input);
|
||||
},
|
||||
nullOrUndefined: function nullOrUndefined(input) {
|
||||
return input === null || typeof input === 'undefined';
|
||||
},
|
||||
empty: function empty(input) {
|
||||
return is$1.nullOrUndefined(input) || (is$1.string(input) || is$1.array(input) || is$1.nodeList(input)) && !input.length || is$1.object(input) && !Object.keys(input).length;
|
||||
}
|
||||
nullOrUndefined: isNullOrUndefined,
|
||||
object: isObject,
|
||||
number: isNumber,
|
||||
string: isString,
|
||||
boolean: isBoolean,
|
||||
function: isFunction,
|
||||
array: isArray,
|
||||
weakMap: isWeakMap,
|
||||
nodeList: isNodeList,
|
||||
element: isElement,
|
||||
textNode: isTextNode,
|
||||
event: isEvent,
|
||||
cue: isCue,
|
||||
track: isTrack,
|
||||
url: isUrl,
|
||||
empty: isEmpty
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
@@ -6158,16 +6190,11 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
get: function get() {
|
||||
// Get sources
|
||||
var sources = html5.getSources.call(player);
|
||||
|
||||
var _sources$filter = sources.filter(function (source) {
|
||||
var source = sources.find(function (source) {
|
||||
return source.getAttribute('src') === player.source;
|
||||
}),
|
||||
_sources$filter2 = slicedToArray(_sources$filter, 1),
|
||||
source = _sources$filter2[0];
|
||||
});
|
||||
|
||||
// Return size, if match is found
|
||||
|
||||
|
||||
return source && Number(source.getAttribute('size'));
|
||||
},
|
||||
set: function set(input) {
|
||||
@@ -6185,25 +6212,30 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// Get current state
|
||||
var currentTime = player.currentTime,
|
||||
playing = player.playing;
|
||||
var _player$media = player.media,
|
||||
currentTime = _player$media.currentTime,
|
||||
paused = _player$media.paused,
|
||||
preload = _player$media.preload,
|
||||
readyState = _player$media.readyState;
|
||||
|
||||
// Set new source
|
||||
|
||||
player.media.src = source.getAttribute('src');
|
||||
|
||||
// Restore time
|
||||
var onLoadedMetaData = function onLoadedMetaData() {
|
||||
player.currentTime = currentTime;
|
||||
};
|
||||
player.once('loadedmetadata', onLoadedMetaData);
|
||||
// Prevent loading if preload="none" and the current source isn't loaded (#1044)
|
||||
if (preload !== 'none' || readyState) {
|
||||
// Restore time
|
||||
player.once('loadedmetadata', function () {
|
||||
player.currentTime = currentTime;
|
||||
|
||||
// Load new source
|
||||
player.media.load();
|
||||
// Resume playing
|
||||
if (!paused) {
|
||||
player.play();
|
||||
}
|
||||
});
|
||||
|
||||
// Resume playing
|
||||
if (playing) {
|
||||
player.play();
|
||||
// Load new source
|
||||
player.media.load();
|
||||
}
|
||||
|
||||
// Trigger change event
|
||||
@@ -6523,6 +6555,51 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return Storage;
|
||||
}();
|
||||
|
||||
// ==========================================================================
|
||||
// Fetch wrapper
|
||||
// Using XHR to avoid issues with older browsers
|
||||
// ==========================================================================
|
||||
|
||||
function fetch(url) {
|
||||
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
// Check for CORS support
|
||||
if (!('withCredentials' in request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
request.addEventListener('load', function () {
|
||||
if (responseType === 'text') {
|
||||
try {
|
||||
resolve(JSON.parse(request.responseText));
|
||||
} catch (e) {
|
||||
resolve(request.responseText);
|
||||
}
|
||||
} else {
|
||||
resolve(request.response);
|
||||
}
|
||||
});
|
||||
|
||||
request.addEventListener('error', function () {
|
||||
throw new Error(request.status);
|
||||
});
|
||||
|
||||
request.open('GET', url, true);
|
||||
|
||||
// Set the required response type
|
||||
request.responseType = responseType;
|
||||
|
||||
request.send();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
// Load an external SVG sprite
|
||||
@@ -6792,7 +6869,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
if ('class' in attributes) {
|
||||
if (attributes.class.includes(this.config.classNames.control)) {
|
||||
if (!attributes.class.includes(this.config.classNames.control)) {
|
||||
attributes.class += ' ' + this.config.classNames.control;
|
||||
}
|
||||
} else {
|
||||
@@ -7241,6 +7318,16 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.
|
||||
// https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415
|
||||
// https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062
|
||||
// https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338
|
||||
if (this.duration >= Math.pow(2, 32)) {
|
||||
toggleHidden(this.elements.display.currentTime, true);
|
||||
toggleHidden(this.elements.progress, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update ARIA values
|
||||
if (is$1.element(this.elements.inputs.seek)) {
|
||||
this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);
|
||||
@@ -8061,12 +8148,9 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
target = this.elements.container;
|
||||
}
|
||||
|
||||
// Inject controls HTML
|
||||
if (is$1.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
// Inject controls HTML (needs to be before captions, hence "afterbegin")
|
||||
var insertMethod = is$1.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';
|
||||
target[insertMethod]('afterbegin', container);
|
||||
|
||||
// Find the elements if need be
|
||||
if (!is$1.element(this.elements.controls)) {
|
||||
@@ -8095,51 +8179,6 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================================================
|
||||
// Fetch wrapper
|
||||
// Using XHR to avoid issues with older browsers
|
||||
// ==========================================================================
|
||||
|
||||
function fetch$1(url) {
|
||||
var responseType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'text';
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
// Check for CORS support
|
||||
if (!('withCredentials' in request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
request.addEventListener('load', function () {
|
||||
if (responseType === 'text') {
|
||||
try {
|
||||
resolve(JSON.parse(request.responseText));
|
||||
} catch (e) {
|
||||
resolve(request.responseText);
|
||||
}
|
||||
} else {
|
||||
resolve(request.response);
|
||||
}
|
||||
});
|
||||
|
||||
request.addEventListener('error', function () {
|
||||
throw new Error(request.statusText);
|
||||
});
|
||||
|
||||
request.open('GET', url, true);
|
||||
|
||||
// Set the required response type
|
||||
request.responseType = responseType;
|
||||
|
||||
request.send();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
@@ -8219,7 +8258,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var url = parseUrl(src);
|
||||
|
||||
if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {
|
||||
fetch$1(src, 'blob').then(function (blob) {
|
||||
fetch(src, 'blob').then(function (blob) {
|
||||
track.setAttribute('src', window.URL.createObjectURL(blob));
|
||||
}).catch(function () {
|
||||
removeElement(track);
|
||||
@@ -8235,7 +8274,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// * active: The state preferred by user settings or config
|
||||
// * toggled: The real captions state
|
||||
|
||||
var languages = dedupe(Array.from(navigator.languages || navigator.userLanguage).map(function (language) {
|
||||
var languages = dedupe(Array.from(navigator.languages || navigator.language || navigator.userLanguage).map(function (language) {
|
||||
return language.split('-')[0];
|
||||
}));
|
||||
|
||||
@@ -8363,8 +8402,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle state
|
||||
this.elements.buttons.captions.pressed = active;
|
||||
// Toggle button if it's enabled
|
||||
if (this.elements.buttons.captions) {
|
||||
this.elements.buttons.captions.pressed = active;
|
||||
}
|
||||
|
||||
// Add class hook
|
||||
toggleClass(this.elements.container, activeClass, active);
|
||||
@@ -9383,11 +9424,9 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// If there's a play button, set label
|
||||
if (is$1.nodeList(this.elements.buttons.play)) {
|
||||
Array.from(this.elements.buttons.play).forEach(function (button) {
|
||||
button.setAttribute('aria-label', label);
|
||||
});
|
||||
}
|
||||
Array.from(this.elements.buttons.play || []).forEach(function (button) {
|
||||
button.setAttribute('aria-label', label);
|
||||
});
|
||||
|
||||
// Set iframe title
|
||||
// https://github.com/sampotts/plyr/issues/124
|
||||
@@ -9467,7 +9506,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
|
||||
|
||||
// Set state
|
||||
Array.from(this.elements.buttons.play).forEach(function (target) {
|
||||
Array.from(this.elements.buttons.play || []).forEach(function (target) {
|
||||
target.pressed = _this3.playing;
|
||||
});
|
||||
|
||||
@@ -9961,9 +10000,11 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
};
|
||||
|
||||
// Play/pause toggle
|
||||
Array.from(this.player.elements.buttons.play).forEach(function (button) {
|
||||
bind(button, 'click', _this4.player.togglePlay, 'play');
|
||||
});
|
||||
if (this.player.elements.buttons.play) {
|
||||
Array.from(this.player.elements.buttons.play).forEach(function (button) {
|
||||
bind(button, 'click', _this4.player.togglePlay, 'play');
|
||||
});
|
||||
}
|
||||
|
||||
// Pause
|
||||
bind(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');
|
||||
@@ -10165,33 +10206,28 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Detect "natural" scroll - suppored on OS X Safari only
|
||||
// Other browsers on OS X will be inverted until support improves
|
||||
var inverted = event.webkitDirectionInvertedFromDevice;
|
||||
var step = 1 / 50;
|
||||
var direction = 0;
|
||||
|
||||
// Scroll down (or up on natural) to decrease
|
||||
if (event.deltaY < 0 || event.deltaX > 0) {
|
||||
if (inverted) {
|
||||
_this4.player.decreaseVolume(step);
|
||||
direction = -1;
|
||||
} else {
|
||||
_this4.player.increaseVolume(step);
|
||||
direction = 1;
|
||||
}
|
||||
}
|
||||
// Get delta from event. Invert if `inverted` is true
|
||||
|
||||
// Scroll up (or down on natural) to increase
|
||||
if (event.deltaY > 0 || event.deltaX < 0) {
|
||||
if (inverted) {
|
||||
_this4.player.increaseVolume(step);
|
||||
direction = 1;
|
||||
} else {
|
||||
_this4.player.decreaseVolume(step);
|
||||
direction = -1;
|
||||
}
|
||||
}
|
||||
var _map = [event.deltaX, -event.deltaY].map(function (value) {
|
||||
return inverted ? -value : value;
|
||||
}),
|
||||
_map2 = slicedToArray(_map, 2),
|
||||
x = _map2[0],
|
||||
y = _map2[1];
|
||||
|
||||
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
|
||||
|
||||
|
||||
var direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
|
||||
|
||||
// Change the volume by 2%
|
||||
_this4.player.increaseVolume(direction / 50);
|
||||
|
||||
// Don't break page scrolling at max and min
|
||||
if (direction === 1 && _this4.player.media.volume < 1 || direction === -1 && _this4.player.media.volume > 0) {
|
||||
var volume = _this4.player.media.volume;
|
||||
|
||||
if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}, 'volume', false);
|
||||
@@ -10633,7 +10669,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
player.media = replaceElement(wrapper, player.media);
|
||||
|
||||
// Get poster image
|
||||
fetch$1(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
|
||||
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
|
||||
if (is$1.empty(response)) {
|
||||
return;
|
||||
}
|
||||
@@ -11048,7 +11084,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
if (is$1.string(key) && !is$1.empty(key)) {
|
||||
var url = format(this.config.urls.youtube.api, videoId, key);
|
||||
|
||||
fetch$1(url).then(function (result) {
|
||||
fetch(url).then(function (result) {
|
||||
if (is$1.object(result)) {
|
||||
_this2.config.title = result.items[0].snippet.title;
|
||||
ui.setTitle.call(_this2);
|
||||
@@ -11123,6 +11159,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
videoId: videoId,
|
||||
playerVars: {
|
||||
autoplay: player.config.autoplay ? 1 : 0, // Autoplay
|
||||
hl: player.config.hl, // iframe interface language
|
||||
controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported
|
||||
rel: 0, // No related vids
|
||||
showinfo: 0, // Hide info
|
||||
@@ -11173,6 +11210,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
triggerEvent.call(player, player.media, 'ratechange');
|
||||
},
|
||||
onReady: function onReady(event) {
|
||||
// Bail if onReady has already been called. See issue #1108
|
||||
if (is$1.function(player.media.play)) {
|
||||
return;
|
||||
}
|
||||
// Get the instance
|
||||
var instance = event.target;
|
||||
|
||||
@@ -11204,8 +11245,8 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
return Number(instance.getCurrentTime());
|
||||
},
|
||||
set: function set(time) {
|
||||
// If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
|
||||
if (player.paused) {
|
||||
// If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
|
||||
if (player.paused && !player.embed.hasPlayed) {
|
||||
player.embed.mute();
|
||||
}
|
||||
|
||||
@@ -12124,7 +12165,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}, {
|
||||
key: 'enabled',
|
||||
get: function get() {
|
||||
return this.player.isVideo && this.player.config.ads.enabled && !is$1.empty(this.publisherId);
|
||||
return this.player.isHTML5 && this.player.isVideo && this.player.config.ads.enabled && !is$1.empty(this.publisherId);
|
||||
}
|
||||
}, {
|
||||
key: 'tagUrl',
|
||||
@@ -12132,7 +12173,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var params = {
|
||||
AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',
|
||||
AV_CHANNELID: '5a0458dc28a06145e4519d21',
|
||||
AV_URL: location.hostname,
|
||||
AV_URL: window.location.hostname,
|
||||
cb: Date.now(),
|
||||
AV_WIDTH: 640,
|
||||
AV_HEIGHT: 480,
|
||||
@@ -12428,7 +12469,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
this.elements.container.className = '';
|
||||
|
||||
// Get attributes from URL and set config
|
||||
if (url.searchParams.length) {
|
||||
if (url.search.length) {
|
||||
var truthy = ['1', 'true'];
|
||||
|
||||
if (truthy.includes(url.searchParams.get('autoplay'))) {
|
||||
@@ -12442,6 +12483,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// YouTube requires the playsinline in the URL
|
||||
if (this.isYouTube) {
|
||||
this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));
|
||||
this.config.hl = url.searchParams.get('hl');
|
||||
} else {
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
@@ -12681,7 +12723,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
*/
|
||||
value: function increaseVolume(step) {
|
||||
var volume = this.media.muted ? 0 : this.volume;
|
||||
this.volume = volume + (is$1.number(step) ? step : 1);
|
||||
this.volume = volume + (is$1.number(step) ? step : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -12692,8 +12734,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}, {
|
||||
key: 'decreaseVolume',
|
||||
value: function decreaseVolume(step) {
|
||||
var volume = this.media.muted ? 0 : this.volume;
|
||||
this.volume = volume - (is$1.number(step) ? step : 1);
|
||||
this.increaseVolume(-step);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -12777,6 +12818,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
value: function on$$1(event, callback) {
|
||||
on.call(this, this.elements.container, event, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add event listeners once
|
||||
* @param {string} event - Event type
|
||||
@@ -12788,6 +12830,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
value: function once$$1(event, callback) {
|
||||
once.call(this, this.elements.container, event, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove event listeners
|
||||
* @param {string} event - Event type
|
||||
@@ -13063,8 +13106,9 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Faux duration set via config
|
||||
var fauxDuration = parseFloat(this.config.duration);
|
||||
|
||||
// Media duration can be NaN before the media has loaded
|
||||
var duration = (this.media || {}).duration || 0;
|
||||
// Media duration can be NaN or Infinity before the media has loaded
|
||||
var realDuration = (this.media || {}).duration;
|
||||
var duration = !is$1.number(realDuration) || realDuration === Infinity ? 0 : realDuration;
|
||||
|
||||
// If config duration is funky, use regular duration
|
||||
return fauxDuration || duration;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+125
-62
@@ -29,18 +29,12 @@ const sourcemaps = require('gulp-sourcemaps');
|
||||
const uglify = require('gulp-uglify-es').default;
|
||||
const commonjs = require('rollup-plugin-commonjs');
|
||||
const resolve = require('rollup-plugin-node-resolve');
|
||||
const FastlyPurge = require('fastly-purge');
|
||||
const through = require('through2');
|
||||
|
||||
const bundles = require('./bundles.json');
|
||||
const pkg = require('./package.json');
|
||||
|
||||
// Get AWS config
|
||||
let aws = {};
|
||||
try {
|
||||
aws = require('./aws.json'); //eslint-disable-line
|
||||
} catch (e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
const minSuffix = '.min';
|
||||
|
||||
// Paths
|
||||
@@ -95,16 +89,18 @@ const browsers = ['> 1%'];
|
||||
|
||||
// Babel config
|
||||
const babelrc = {
|
||||
presets: [[
|
||||
'env',
|
||||
{
|
||||
targets: {
|
||||
browsers,
|
||||
presets: [
|
||||
[
|
||||
'env',
|
||||
{
|
||||
targets: {
|
||||
browsers,
|
||||
},
|
||||
useBuiltIns: true,
|
||||
modules: false,
|
||||
},
|
||||
useBuiltIns: true,
|
||||
modules: false,
|
||||
},
|
||||
]],
|
||||
],
|
||||
],
|
||||
plugins: ['external-helpers'],
|
||||
babelrc: false,
|
||||
exclude: 'node_modules/**',
|
||||
@@ -112,10 +108,9 @@ const babelrc = {
|
||||
|
||||
// Clean out /dist
|
||||
gulp.task('clean', () => {
|
||||
const dirs = [
|
||||
paths.plyr.output,
|
||||
paths.demo.output,
|
||||
].map(dir => path.join(dir, '**/*'));
|
||||
const dirs = [paths.plyr.output, paths.demo.output].map(dir =>
|
||||
path.join(dir, '**/*'),
|
||||
);
|
||||
|
||||
// Don't delete the mp4
|
||||
dirs.push(`!${path.join(paths.plyr.output, '**/*.mp4')}`);
|
||||
@@ -187,9 +182,11 @@ const build = {
|
||||
.src(paths[bundle].src.sprite)
|
||||
.pipe(
|
||||
svgmin({
|
||||
plugins: [{
|
||||
removeDesc: true,
|
||||
}],
|
||||
plugins: [
|
||||
{
|
||||
removeDesc: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
)
|
||||
.pipe(svgstore())
|
||||
@@ -238,9 +235,21 @@ gulp.task('default', () => {
|
||||
|
||||
// Publish a version to CDN and demo
|
||||
// --------------------------------------------
|
||||
// If aws is setup
|
||||
if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
// Get deployment config
|
||||
let credentials = {};
|
||||
try {
|
||||
credentials = require('./credentials.json'); //eslint-disable-line
|
||||
} catch (e) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// If deployment is setup
|
||||
if (
|
||||
Object.keys(credentials).includes('aws') &&
|
||||
Object.keys(credentials).includes('fastly')
|
||||
) {
|
||||
const { version } = pkg;
|
||||
const { aws, fastly } = credentials;
|
||||
|
||||
// Get branch info
|
||||
const branch = {
|
||||
@@ -248,10 +257,6 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
master: 'master',
|
||||
develop: 'develop',
|
||||
};
|
||||
const allowed = [
|
||||
branch.master,
|
||||
branch.develop,
|
||||
];
|
||||
|
||||
const maxAge = 31536000; // 1 year
|
||||
const options = {
|
||||
@@ -264,7 +269,8 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
demo: {
|
||||
uploadPath: branch.current === branch.develop ? 'beta/' : null,
|
||||
headers: {
|
||||
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
||||
'Cache-Control':
|
||||
'no-cache, no-store, must-revalidate, max-age=0',
|
||||
Vary: 'Accept-Encoding',
|
||||
},
|
||||
},
|
||||
@@ -273,27 +279,51 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
headers: {
|
||||
// http://stackoverflow.com/questions/2272835/amazon-s3-object-redirect
|
||||
'x-amz-website-redirect-location': `/${ver}/${filename}`,
|
||||
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
||||
'Cache-Control':
|
||||
'no-cache, no-store, must-revalidate, max-age=0',
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const regex = '(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?';
|
||||
const regex =
|
||||
'(?:0|[1-9][0-9]*)\\.(?:0|[1-9][0-9]*).(?:0|[1-9][0-9]*)(?:-[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?(?:\\+[\\da-z\\-]+(?:.[\\da-z\\-]+)*)?';
|
||||
const semver = new RegExp(`v${regex}`, 'gi');
|
||||
const localPath = new RegExp('(../)?dist', 'gi');
|
||||
const versionPath = `https://${aws.cdn.domain}/${version}`;
|
||||
const cdnpath = new RegExp(`${aws.cdn.domain}/${regex}/`, 'gi');
|
||||
|
||||
const renameFile = rename(p => {
|
||||
p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line
|
||||
p.dirname = p.dirname.replace('.', version); // eslint-disable-line
|
||||
});
|
||||
|
||||
// Check we're on the correct branch to deploy
|
||||
const canDeploy = () => {
|
||||
const allowed = [branch.master, branch.develop];
|
||||
|
||||
if (!allowed.includes(branch.current)) {
|
||||
console.error(
|
||||
`Must be on ${allowed.join(', ')} to publish! (current: ${
|
||||
branch.current
|
||||
})`,
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
gulp.task('version', () => {
|
||||
if (!canDeploy()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(`Updating versions to '${version}'...`);
|
||||
|
||||
// Replace versioned URLs in source
|
||||
const files = [
|
||||
'plyr.js',
|
||||
'plyr.polyfilled.js',
|
||||
'defaults.js',
|
||||
];
|
||||
const files = ['plyr.js', 'plyr.polyfilled.js', 'defaults.js'];
|
||||
|
||||
return gulp
|
||||
.src(files.map(file => path.join(root, `src/js/${file}`)))
|
||||
@@ -304,8 +334,7 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
|
||||
// Publish version to CDN bucket
|
||||
gulp.task('cdn', () => {
|
||||
if (!allowed.includes(branch.current)) {
|
||||
console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`);
|
||||
if (!canDeploy()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -315,14 +344,15 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
return (
|
||||
gulp
|
||||
.src(paths.upload)
|
||||
.pipe(
|
||||
rename(p => {
|
||||
p.basename = p.basename.replace(minSuffix, ''); // eslint-disable-line
|
||||
p.dirname = p.dirname.replace('.', version); // eslint-disable-line
|
||||
}),
|
||||
)
|
||||
.pipe(renameFile)
|
||||
// Remove min suffix from source map URL
|
||||
.pipe(replace(/sourceMappingURL=([\w-?.]+)/, (match, p1) => `sourceMappingURL=${p1.replace(minSuffix, '')}`))
|
||||
.pipe(
|
||||
replace(
|
||||
/sourceMappingURL=([\w-?.]+)/,
|
||||
(match, p1) =>
|
||||
`sourceMappingURL=${p1.replace(minSuffix, '')}`,
|
||||
),
|
||||
)
|
||||
.pipe(
|
||||
size({
|
||||
showFiles: true,
|
||||
@@ -334,10 +364,36 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
);
|
||||
});
|
||||
|
||||
// Purge the fastly cache incase any 403/404 are cached
|
||||
gulp.task('purge', () => {
|
||||
const list = [];
|
||||
|
||||
return gulp.src(paths.upload).pipe(
|
||||
through.obj((file, enc, cb) => {
|
||||
const filename = file.path.split('/').pop();
|
||||
list.push(`${versionPath}/${filename}`);
|
||||
cb(null);
|
||||
}),
|
||||
).on('end', () => {
|
||||
const purge = new FastlyPurge(fastly.token);
|
||||
|
||||
list.forEach(url => {
|
||||
console.log(`Purging ${url}...`);
|
||||
|
||||
purge.url(url, (error, result) => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
} else if (result) {
|
||||
console.log(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Publish to demo bucket
|
||||
gulp.task('demo', () => {
|
||||
if (!allowed.includes(branch.current)) {
|
||||
console.error(`Must be on ${allowed.join(', ')} to publish! (current: ${branch.current})`);
|
||||
if (!canDeploy()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -399,22 +455,29 @@ if (Object.keys(aws).includes('cdn') && Object.keys(aws).includes('demo')) {
|
||||
}));
|
||||
}); */
|
||||
|
||||
// Open the demo site to check it's sweet
|
||||
gulp.task('open', () => {
|
||||
console.log(`Opening ${aws.demo.domain}...`);
|
||||
|
||||
// A file must be specified or gulp will skip the task
|
||||
// Doesn't matter which file since we set the URL above
|
||||
// Weird, I know...
|
||||
return gulp.src([`${paths.demo.root}index.html`]).pipe(
|
||||
open('', {
|
||||
url: `http://${aws.demo.domain}`,
|
||||
// Open the demo site to check it's ok
|
||||
gulp.task('open', callback => {
|
||||
gulp.src(__filename).pipe(
|
||||
open({
|
||||
uri: `https://${aws.demo.domain}`,
|
||||
}),
|
||||
);
|
||||
|
||||
callback();
|
||||
});
|
||||
|
||||
// Do everything
|
||||
gulp.task('publish', callback => {
|
||||
run('version', tasks.clean, tasks.js, tasks.sass, tasks.sprite, 'cdn', 'demo', callback);
|
||||
});
|
||||
gulp.task('deploy', () =>
|
||||
run(
|
||||
'version',
|
||||
tasks.clean,
|
||||
tasks.js,
|
||||
tasks.sass,
|
||||
tasks.sprite,
|
||||
'cdn',
|
||||
'purge',
|
||||
'demo',
|
||||
'open',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
+50
-35
@@ -1,33 +1,63 @@
|
||||
{
|
||||
"name": "plyr",
|
||||
"version": "3.3.13",
|
||||
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||
"version": "3.3.23",
|
||||
"description":
|
||||
"A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||
"homepage": "https://plyr.io",
|
||||
"author": "Sam Potts <sam@potts.es>",
|
||||
"keywords": [
|
||||
"HTML5 Video",
|
||||
"HTML5 Audio",
|
||||
"Media Player",
|
||||
"DASH",
|
||||
"Shaka",
|
||||
"WordPress",
|
||||
"HLS"
|
||||
],
|
||||
"main": "./dist/plyr.js",
|
||||
"browser": "./dist/plyr.min.js",
|
||||
"sass": "./src/sass/plyr.scss",
|
||||
"style": "./dist/plyr.css",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/sampotts/plyr.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/sampotts/plyr/issues"
|
||||
},
|
||||
"directories": {
|
||||
"doc": "readme.md"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"lint": "eslint src/js && npm run-script remark",
|
||||
"remark":
|
||||
"remark -f --use 'validate-links=repository:\"sampotts/plyr\"' '{,!(node_modules),.?**/}*.md'",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.2.3",
|
||||
"babel-eslint": "^8.2.6",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"del": "^3.0.0",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint": "^5.2.0",
|
||||
"eslint-config-airbnb-base": "^13.0.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-import": "^2.13.0",
|
||||
"fastly-purge": "^1.0.1",
|
||||
"git-branch": "^2.0.1",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^5.0.0",
|
||||
"gulp-better-rollup": "^3.2.1",
|
||||
"gulp-better-rollup": "^3.3.0",
|
||||
"gulp-clean-css": "^3.9.4",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-filter": "^5.1.0",
|
||||
"gulp-header": "^2.0.5",
|
||||
"gulp-open": "^3.0.1",
|
||||
"gulp-postcss": "^7.0.1",
|
||||
"gulp-rename": "^1.3.0",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-replace": "^1.0.0",
|
||||
"gulp-s3": "^0.11.0",
|
||||
"gulp-sass": "^4.0.1",
|
||||
@@ -38,43 +68,28 @@
|
||||
"gulp-uglify-es": "^1.0.4",
|
||||
"gulp-util": "^3.0.8",
|
||||
"postcss-custom-properties": "^7.0.0",
|
||||
"prettier-eslint": "^8.8.1",
|
||||
"prettier-eslint": "^8.8.2",
|
||||
"prettier-stylelint": "^0.4.2",
|
||||
"rollup-plugin-babel": "^3.0.4",
|
||||
"rollup-plugin-commonjs": "^9.1.3",
|
||||
"remark-cli": "^5.0.0",
|
||||
"remark-validate-links": "^7.0.0",
|
||||
"rollup-plugin-babel": "^3.0.7",
|
||||
"rollup-plugin-commonjs": "^9.1.4",
|
||||
"rollup-plugin-node-resolve": "^3.3.0",
|
||||
"run-sequence": "^2.2.1",
|
||||
"stylelint": "^9.3.0",
|
||||
"stylelint-config-prettier": "^3.2.0",
|
||||
"stylelint": "^9.4.0",
|
||||
"stylelint-config-prettier": "^3.3.0",
|
||||
"stylelint-config-recommended": "^2.1.0",
|
||||
"stylelint-config-sass-guidelines": "^5.0.0",
|
||||
"stylelint-order": "^0.8.1",
|
||||
"stylelint-scss": "^3.1.2",
|
||||
"stylelint-selector-bem-pattern": "^2.0.0"
|
||||
"stylelint-scss": "^3.2.0",
|
||||
"stylelint-selector-bem-pattern": "^2.0.0",
|
||||
"through2": "^2.0.3"
|
||||
},
|
||||
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/sampotts/plyr.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sampotts/plyr/issues"
|
||||
},
|
||||
"directories": {
|
||||
"doc": "readme.md"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"lint": "eslint src/js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Sam Potts <sam@potts.es>",
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"custom-event-polyfill": "^0.3.0",
|
||||
"custom-event-polyfill": "^1.0.6",
|
||||
"loadjs": "^3.5.4",
|
||||
"raven-js": "^3.26.2",
|
||||
"raven-js": "^3.26.4",
|
||||
"url-polyfill": "^1.0.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ A simple, lightweight, accessible and customizable HTML5, YouTube and Vimeo medi
|
||||
* **HTML Video & Audio** - support for both formats
|
||||
* **[Embedded Video](#embeds)** - support for YouTube and Vimeo video playback
|
||||
* **[Monetization](#ads)** - make money from your videos
|
||||
* **[Streaming](#streaming)** - support for hls.js, Shaka and dash.js streaming playback
|
||||
* **[Streaming](#try-plyr-online)** - support for hls.js, Shaka and dash.js streaming playback
|
||||
* **[API](#api)** - toggle playback, volume, seeking, and more through a standardized API
|
||||
* **[Events](#events)** - no messing around with Vimeo and YouTube APIs, all events are standardized across formats
|
||||
* **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes
|
||||
@@ -80,7 +80,7 @@ Plyr extends upon the standard [HTML5 media element](https://developer.mozilla.o
|
||||
</audio>
|
||||
```
|
||||
|
||||
For YouTube and Vimeo players, Plyr uses progressive enhancement to enhance the default `<iframe>` embeds. Below are some examples. The `plyr__video-embed` classname will make the embed responsive. You can add the `autoplay`, `loop` and `playsinline` (YouTube only) query parameters to the URL and they will be set as config options automatically. For YouTube, the `origin` should be updated to reflect the domain you're hosting the embed on, or you can opt to omit it.
|
||||
For YouTube and Vimeo players, Plyr uses progressive enhancement to enhance the default `<iframe>` embeds. Below are some examples. The `plyr__video-embed` classname will make the embed responsive. You can add the `autoplay`, `loop`, `hl` (YouTube only) and `playsinline` (YouTube only) query parameters to the URL and they will be set as config options automatically. For YouTube, the `origin` should be updated to reflect the domain you're hosting the embed on, or you can opt to omit it.
|
||||
|
||||
#### YouTube embed
|
||||
|
||||
@@ -132,13 +132,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.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.plyr.io/3.3.13/plyr.js"></script>
|
||||
<script src="https://cdn.plyr.io/3.3.23/plyr.js"></script>
|
||||
```
|
||||
|
||||
...or...
|
||||
|
||||
```html
|
||||
<script src="https://cdn.plyr.io/3.3.13/plyr.polyfilled.js"></script>
|
||||
<script src="https://cdn.plyr.io/3.3.23/plyr.polyfilled.js"></script>
|
||||
```
|
||||
|
||||
### CSS
|
||||
@@ -152,13 +152,13 @@ Include the `plyr.css` stylsheet into your `<head>`
|
||||
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.3.13/plyr.css">
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.3.23/plyr.css">
|
||||
```
|
||||
|
||||
### SVG Sprite
|
||||
|
||||
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.3.13/plyr.svg`.
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.3.23/plyr.svg`.
|
||||
|
||||
## Ads
|
||||
|
||||
@@ -286,7 +286,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
|
||||
| `debug` | Boolean | `false` | Display debugging information in the console |
|
||||
| `controls` | Array, Function or Element | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return either an element or HTML string for the controls. Three arguments will be passed to your function; `id` (the unique id for the player), `seektime` (the seektime step in seconds), and `title` (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. |
|
||||
| `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu |
|
||||
| `i18n` | Object | See [defaults.js](/src/js/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
|
||||
| `i18n` | Object | See [defaults.js](/src/js/config/defaults.js) | Used for internationalization (i18n) of the text within the UI. |
|
||||
| `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. |
|
||||
| `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. |
|
||||
| `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. |
|
||||
@@ -409,7 +409,7 @@ player.fullscreen.active; // false;
|
||||
| `speed` | ✓ | ✓ | Gets or sets the speed for the player. The setter accepts a value in the options specified in your config. Generally the minimum should be 0.5. |
|
||||
| `quality`¹ | ✓ | ✓ | Gets or sets the quality for the player. The setter accepts a value from the options specified in your config. |
|
||||
| `loop` | ✓ | ✓ | Gets or sets the current loop state of the player. The setter accepts a boolean. |
|
||||
| `source` | ✓ | ✓ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#source-setter) below for examples. |
|
||||
| `source` | ✓ | ✓ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#the-source-setter) below for examples. |
|
||||
| `poster` | ✓ | ✓ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. |
|
||||
| `autoplay` | ✓ | ✓ | Gets or sets the autoplay state of the player. The setter accepts a boolean. |
|
||||
| `currentTrack` | ✓ | ✓ | Gets or sets the caption track by index. `-1` means the track is missing or captions is not active |
|
||||
@@ -435,10 +435,12 @@ player.source = {
|
||||
{
|
||||
src: '/path/to/movie.mp4',
|
||||
type: 'video/mp4',
|
||||
size: 720,
|
||||
},
|
||||
{
|
||||
src: '/path/to/movie.webm',
|
||||
type: 'video/webm',
|
||||
size: 1080,
|
||||
},
|
||||
],
|
||||
poster: '/path/to/poster.jpg',
|
||||
|
||||
+5
-3
@@ -84,7 +84,7 @@ const captions = {
|
||||
// * toggled: The real captions state
|
||||
|
||||
const languages = dedupe(
|
||||
Array.from(navigator.languages || navigator.userLanguage).map(language => language.split('-')[0]),
|
||||
Array.from(navigator.languages || navigator.language || navigator.userLanguage).map(language => language.split('-')[0]),
|
||||
);
|
||||
|
||||
let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();
|
||||
@@ -191,8 +191,10 @@ const captions = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle state
|
||||
this.elements.buttons.captions.pressed = active;
|
||||
// Toggle button if it's enabled
|
||||
if (this.elements.buttons.captions) {
|
||||
this.elements.buttons.captions.pressed = active;
|
||||
}
|
||||
|
||||
// Add class hook
|
||||
toggleClass(this.elements.container, activeClass, active);
|
||||
|
||||
@@ -17,10 +17,12 @@ export default class Console {
|
||||
// eslint-disable-next-line no-console
|
||||
return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;
|
||||
}
|
||||
|
||||
get warn() {
|
||||
// eslint-disable-next-line no-console
|
||||
return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;
|
||||
}
|
||||
|
||||
get error() {
|
||||
// eslint-disable-next-line no-console
|
||||
return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;
|
||||
|
||||
Vendored
+15
-8
@@ -16,11 +16,11 @@ import {
|
||||
getElement,
|
||||
getElements,
|
||||
hasClass,
|
||||
matches,
|
||||
removeElement,
|
||||
setAttributes,
|
||||
toggleClass,
|
||||
toggleHidden,
|
||||
matches,
|
||||
} from './utils/elements';
|
||||
import { off, on } from './utils/events';
|
||||
import is from './utils/is';
|
||||
@@ -187,7 +187,7 @@ const controls = {
|
||||
}
|
||||
|
||||
if ('class' in attributes) {
|
||||
if (attributes.class.includes(this.config.classNames.control)) {
|
||||
if (!attributes.class.includes(this.config.classNames.control)) {
|
||||
attributes.class += ` ${this.config.classNames.control}`;
|
||||
}
|
||||
} else {
|
||||
@@ -633,6 +633,16 @@ const controls = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.
|
||||
// https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415
|
||||
// https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062
|
||||
// https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338
|
||||
if (this.duration >= 2**32) {
|
||||
toggleHidden(this.elements.display.currentTime, true);
|
||||
toggleHidden(this.elements.progress, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update ARIA values
|
||||
if (is.element(this.elements.inputs.seek)) {
|
||||
this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);
|
||||
@@ -1445,12 +1455,9 @@ const controls = {
|
||||
target = this.elements.container;
|
||||
}
|
||||
|
||||
// Inject controls HTML
|
||||
if (is.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
// Inject controls HTML (needs to be before captions, hence "afterbegin")
|
||||
const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';
|
||||
target[insertMethod]('afterbegin', container);
|
||||
|
||||
// Find the elements if need be
|
||||
if (!is.element(this.elements.controls)) {
|
||||
|
||||
+14
-12
@@ -39,7 +39,7 @@ const html5 = {
|
||||
get() {
|
||||
// Get sources
|
||||
const sources = html5.getSources.call(player);
|
||||
const [source] = sources.filter(source => source.getAttribute('src') === player.source);
|
||||
const source = sources.find(source => source.getAttribute('src') === player.source);
|
||||
|
||||
// Return size, if match is found
|
||||
return source && Number(source.getAttribute('size'));
|
||||
@@ -57,23 +57,25 @@ const html5 = {
|
||||
}
|
||||
|
||||
// Get current state
|
||||
const { currentTime, playing } = player;
|
||||
const { currentTime, paused, preload, readyState } = player.media;
|
||||
|
||||
// Set new source
|
||||
player.media.src = source.getAttribute('src');
|
||||
|
||||
// Restore time
|
||||
const onLoadedMetaData = () => {
|
||||
player.currentTime = currentTime;
|
||||
};
|
||||
player.once('loadedmetadata', onLoadedMetaData);
|
||||
// Prevent loading if preload="none" and the current source isn't loaded (#1044)
|
||||
if (preload !== 'none' || readyState) {
|
||||
// Restore time
|
||||
player.once('loadedmetadata', () => {
|
||||
player.currentTime = currentTime;
|
||||
|
||||
// Load new source
|
||||
player.media.load();
|
||||
// Resume playing
|
||||
if (!paused) {
|
||||
player.play();
|
||||
}
|
||||
});
|
||||
|
||||
// Resume playing
|
||||
if (playing) {
|
||||
player.play();
|
||||
// Load new source
|
||||
player.media.load();
|
||||
}
|
||||
|
||||
// Trigger change event
|
||||
|
||||
+14
-29
@@ -431,9 +431,11 @@ class Listeners {
|
||||
};
|
||||
|
||||
// Play/pause toggle
|
||||
Array.from(this.player.elements.buttons.play).forEach(button => {
|
||||
bind(button, 'click', this.player.togglePlay, 'play');
|
||||
});
|
||||
if (this.player.elements.buttons.play) {
|
||||
Array.from(this.player.elements.buttons.play).forEach(button => {
|
||||
bind(button, 'click', this.player.togglePlay, 'play');
|
||||
});
|
||||
}
|
||||
|
||||
// Pause
|
||||
bind(this.player.elements.buttons.restart, 'click', this.player.restart, 'restart');
|
||||
@@ -665,36 +667,19 @@ class Listeners {
|
||||
// Detect "natural" scroll - suppored on OS X Safari only
|
||||
// Other browsers on OS X will be inverted until support improves
|
||||
const inverted = event.webkitDirectionInvertedFromDevice;
|
||||
const step = 1 / 50;
|
||||
let direction = 0;
|
||||
|
||||
// Scroll down (or up on natural) to decrease
|
||||
if (event.deltaY < 0 || event.deltaX > 0) {
|
||||
if (inverted) {
|
||||
this.player.decreaseVolume(step);
|
||||
direction = -1;
|
||||
} else {
|
||||
this.player.increaseVolume(step);
|
||||
direction = 1;
|
||||
}
|
||||
}
|
||||
// Get delta from event. Invert if `inverted` is true
|
||||
const [x, y] = [event.deltaX, -event.deltaY].map(value => (inverted ? -value : value));
|
||||
|
||||
// Scroll up (or down on natural) to increase
|
||||
if (event.deltaY > 0 || event.deltaX < 0) {
|
||||
if (inverted) {
|
||||
this.player.increaseVolume(step);
|
||||
direction = 1;
|
||||
} else {
|
||||
this.player.decreaseVolume(step);
|
||||
direction = -1;
|
||||
}
|
||||
}
|
||||
// Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)
|
||||
const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);
|
||||
|
||||
// Change the volume by 2%
|
||||
this.player.increaseVolume(direction / 50);
|
||||
|
||||
// Don't break page scrolling at max and min
|
||||
if (
|
||||
(direction === 1 && this.player.media.volume < 1) ||
|
||||
(direction === -1 && this.player.media.volume > 0)
|
||||
) {
|
||||
const { volume } = this.player.media;
|
||||
if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
+10
-8
@@ -7,12 +7,12 @@
|
||||
/* global google */
|
||||
|
||||
import i18n from '../i18n';
|
||||
import { createElement } from './../utils/elements';
|
||||
import { triggerEvent } from './../utils/events';
|
||||
import is from './../utils/is';
|
||||
import loadScript from './../utils/loadScript';
|
||||
import { formatTime } from './../utils/time';
|
||||
import { buildUrlParams } from './../utils/urls';
|
||||
import { createElement } from '../utils/elements';
|
||||
import { triggerEvent } from '../utils/events';
|
||||
import is from '../utils/is';
|
||||
import loadScript from '../utils/loadScript';
|
||||
import { formatTime } from '../utils/time';
|
||||
import { buildUrlParams } from '../utils/urls';
|
||||
|
||||
class Ads {
|
||||
/**
|
||||
@@ -49,7 +49,9 @@ class Ads {
|
||||
}
|
||||
|
||||
get enabled() {
|
||||
return this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId);
|
||||
return (
|
||||
this.player.isHTML5 && this.player.isVideo && this.player.config.ads.enabled && !is.empty(this.publisherId)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +100,7 @@ class Ads {
|
||||
const params = {
|
||||
AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',
|
||||
AV_CHANNELID: '5a0458dc28a06145e4519d21',
|
||||
AV_URL: location.hostname,
|
||||
AV_URL: window.location.hostname,
|
||||
cb: Date.now(),
|
||||
AV_WIDTH: 640,
|
||||
AV_HEIGHT: 480,
|
||||
|
||||
+10
-10
@@ -2,16 +2,16 @@
|
||||
// Vimeo plugin
|
||||
// ==========================================================================
|
||||
|
||||
import captions from './../captions';
|
||||
import controls from './../controls';
|
||||
import ui from './../ui';
|
||||
import { createElement, replaceElement, toggleClass } from './../utils/elements';
|
||||
import { triggerEvent } from './../utils/events';
|
||||
import fetch from './../utils/fetch';
|
||||
import is from './../utils/is';
|
||||
import loadScript from './../utils/loadScript';
|
||||
import { format, stripHTML } from './../utils/strings';
|
||||
import { buildUrlParams } from './../utils/urls';
|
||||
import captions from '../captions';
|
||||
import controls from '../controls';
|
||||
import ui from '../ui';
|
||||
import { createElement, replaceElement, toggleClass } from '../utils/elements';
|
||||
import { triggerEvent } from '../utils/events';
|
||||
import fetch from '../utils/fetch';
|
||||
import is from '../utils/is';
|
||||
import loadScript from '../utils/loadScript';
|
||||
import { format, stripHTML } from '../utils/strings';
|
||||
import { buildUrlParams } from '../utils/urls';
|
||||
|
||||
// Parse Vimeo ID from URL
|
||||
function parseId(url) {
|
||||
|
||||
+17
-12
@@ -2,16 +2,16 @@
|
||||
// YouTube plugin
|
||||
// ==========================================================================
|
||||
|
||||
import controls from './../controls';
|
||||
import ui from './../ui';
|
||||
import { dedupe } from './../utils/arrays';
|
||||
import { createElement, replaceElement, toggleClass } from './../utils/elements';
|
||||
import { triggerEvent } from './../utils/events';
|
||||
import fetch from './../utils/fetch';
|
||||
import is from './../utils/is';
|
||||
import loadImage from './../utils/loadImage';
|
||||
import loadScript from './../utils/loadScript';
|
||||
import { format, generateId } from './../utils/strings';
|
||||
import controls from '../controls';
|
||||
import ui from '../ui';
|
||||
import { dedupe } from '../utils/arrays';
|
||||
import { createElement, replaceElement, toggleClass } from '../utils/elements';
|
||||
import { triggerEvent } from '../utils/events';
|
||||
import fetch from '../utils/fetch';
|
||||
import is from '../utils/is';
|
||||
import loadImage from '../utils/loadImage';
|
||||
import loadScript from '../utils/loadScript';
|
||||
import { format, generateId } from '../utils/strings';
|
||||
|
||||
// Parse YouTube ID from URL
|
||||
function parseId(url) {
|
||||
@@ -188,6 +188,7 @@ const youtube = {
|
||||
videoId,
|
||||
playerVars: {
|
||||
autoplay: player.config.autoplay ? 1 : 0, // Autoplay
|
||||
hl: player.config.hl, // iframe interface language
|
||||
controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported
|
||||
rel: 0, // No related vids
|
||||
showinfo: 0, // Hide info
|
||||
@@ -239,6 +240,10 @@ const youtube = {
|
||||
triggerEvent.call(player, player.media, 'ratechange');
|
||||
},
|
||||
onReady(event) {
|
||||
// Bail if onReady has already been called. See issue #1108
|
||||
if (is.function(player.media.play)) {
|
||||
return;
|
||||
}
|
||||
// Get the instance
|
||||
const instance = event.target;
|
||||
|
||||
@@ -270,8 +275,8 @@ const youtube = {
|
||||
return Number(instance.getCurrentTime());
|
||||
},
|
||||
set(time) {
|
||||
// If paused, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
|
||||
if (player.paused) {
|
||||
// If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).
|
||||
if (player.paused && !player.embed.hasPlayed) {
|
||||
player.embed.mute();
|
||||
}
|
||||
|
||||
|
||||
+15
-7
@@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr
|
||||
// plyr.js v3.3.13
|
||||
// plyr.js v3.3.23
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
@@ -171,7 +171,7 @@ class Plyr {
|
||||
this.elements.container.className = '';
|
||||
|
||||
// Get attributes from URL and set config
|
||||
if (url.searchParams.length) {
|
||||
if (url.search.length) {
|
||||
const truthy = ['1', 'true'];
|
||||
|
||||
if (truthy.includes(url.searchParams.get('autoplay'))) {
|
||||
@@ -185,6 +185,7 @@ class Plyr {
|
||||
// YouTube requires the playsinline in the URL
|
||||
if (this.isYouTube) {
|
||||
this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));
|
||||
this.config.hl = url.searchParams.get('hl');
|
||||
} else {
|
||||
this.config.playsinline = true;
|
||||
}
|
||||
@@ -310,18 +311,23 @@ class Plyr {
|
||||
get isHTML5() {
|
||||
return Boolean(this.provider === providers.html5);
|
||||
}
|
||||
|
||||
get isEmbed() {
|
||||
return Boolean(this.isYouTube || this.isVimeo);
|
||||
}
|
||||
|
||||
get isYouTube() {
|
||||
return Boolean(this.provider === providers.youtube);
|
||||
}
|
||||
|
||||
get isVimeo() {
|
||||
return Boolean(this.provider === providers.vimeo);
|
||||
}
|
||||
|
||||
get isVideo() {
|
||||
return Boolean(this.type === types.video);
|
||||
}
|
||||
|
||||
get isAudio() {
|
||||
return Boolean(this.type === types.audio);
|
||||
}
|
||||
@@ -489,8 +495,9 @@ class Plyr {
|
||||
// Faux duration set via config
|
||||
const fauxDuration = parseFloat(this.config.duration);
|
||||
|
||||
// Media duration can be NaN before the media has loaded
|
||||
const duration = (this.media || {}).duration || 0;
|
||||
// Media duration can be NaN or Infinity before the media has loaded
|
||||
const realDuration = (this.media || {}).duration;
|
||||
const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;
|
||||
|
||||
// If config duration is funky, use regular duration
|
||||
return fauxDuration || duration;
|
||||
@@ -553,7 +560,7 @@ class Plyr {
|
||||
*/
|
||||
increaseVolume(step) {
|
||||
const volume = this.media.muted ? 0 : this.volume;
|
||||
this.volume = volume + (is.number(step) ? step : 1);
|
||||
this.volume = volume + (is.number(step) ? step : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -561,8 +568,7 @@ class Plyr {
|
||||
* @param {boolean} step - How much to decrease by (between 0 and 1)
|
||||
*/
|
||||
decreaseVolume(step) {
|
||||
const volume = this.media.muted ? 0 : this.volume;
|
||||
this.volume = volume - (is.number(step) ? step : 1);
|
||||
this.increaseVolume(-step);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -945,6 +951,7 @@ class Plyr {
|
||||
on(event, callback) {
|
||||
on.call(this, this.elements.container, event, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add event listeners once
|
||||
* @param {string} event - Event type
|
||||
@@ -953,6 +960,7 @@ class Plyr {
|
||||
once(event, callback) {
|
||||
once.call(this, this.elements.container, event, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove event listeners
|
||||
* @param {string} event - Event type
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr Polyfilled Build
|
||||
// plyr.js v3.3.13
|
||||
// plyr.js v3.3.23
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
|
||||
+4
-6
@@ -135,11 +135,9 @@ const ui = {
|
||||
}
|
||||
|
||||
// If there's a play button, set label
|
||||
if (is.nodeList(this.elements.buttons.play)) {
|
||||
Array.from(this.elements.buttons.play).forEach(button => {
|
||||
button.setAttribute('aria-label', label);
|
||||
});
|
||||
}
|
||||
Array.from(this.elements.buttons.play || []).forEach(button => {
|
||||
button.setAttribute('aria-label', label);
|
||||
});
|
||||
|
||||
// Set iframe title
|
||||
// https://github.com/sampotts/plyr/issues/124
|
||||
@@ -214,7 +212,7 @@ const ui = {
|
||||
toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);
|
||||
|
||||
// Set state
|
||||
Array.from(this.elements.buttons.play).forEach(target => {
|
||||
Array.from(this.elements.buttons.play || []).forEach(target => {
|
||||
target.pressed = this.playing;
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function fetch(url, responseType = 'text') {
|
||||
});
|
||||
|
||||
request.addEventListener('error', () => {
|
||||
throw new Error(request.statusText);
|
||||
throw new Error(request.status);
|
||||
});
|
||||
|
||||
request.open('GET', url, true);
|
||||
|
||||
+54
-58
@@ -3,65 +3,61 @@
|
||||
// ==========================================================================
|
||||
|
||||
const getConstructor = input => (input !== null && typeof input !== 'undefined' ? input.constructor : null);
|
||||
|
||||
const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);
|
||||
const isNullOrUndefined = input => input === null || typeof input === 'undefined';
|
||||
const isObject = input => getConstructor(input) === Object;
|
||||
const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);
|
||||
const isString = input => getConstructor(input) === String;
|
||||
const isBoolean = input => getConstructor(input) === Boolean;
|
||||
const isFunction = input => getConstructor(input) === Function;
|
||||
const isArray = input => Array.isArray(input);
|
||||
const isWeakMap = input => instanceOf(input, WeakMap);
|
||||
const isNodeList = input => instanceOf(input, NodeList);
|
||||
const isElement = input => instanceOf(input, Element);
|
||||
const isTextNode = input => getConstructor(input) === Text;
|
||||
const isEvent = input => instanceOf(input, Event);
|
||||
const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
||||
const isTrack = input => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));
|
||||
|
||||
const is = {
|
||||
object(input) {
|
||||
return getConstructor(input) === Object;
|
||||
},
|
||||
number(input) {
|
||||
return getConstructor(input) === Number && !Number.isNaN(input);
|
||||
},
|
||||
string(input) {
|
||||
return getConstructor(input) === String;
|
||||
},
|
||||
boolean(input) {
|
||||
return getConstructor(input) === Boolean;
|
||||
},
|
||||
function(input) {
|
||||
return getConstructor(input) === Function;
|
||||
},
|
||||
array(input) {
|
||||
return !is.nullOrUndefined(input) && Array.isArray(input);
|
||||
},
|
||||
weakMap(input) {
|
||||
return instanceOf(input, WeakMap);
|
||||
},
|
||||
nodeList(input) {
|
||||
return instanceOf(input, NodeList);
|
||||
},
|
||||
element(input) {
|
||||
return instanceOf(input, Element);
|
||||
},
|
||||
textNode(input) {
|
||||
return getConstructor(input) === Text;
|
||||
},
|
||||
event(input) {
|
||||
return instanceOf(input, Event);
|
||||
},
|
||||
cue(input) {
|
||||
return instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);
|
||||
},
|
||||
track(input) {
|
||||
return instanceOf(input, TextTrack) || (!is.nullOrUndefined(input) && is.string(input.kind));
|
||||
},
|
||||
url(input) {
|
||||
return (
|
||||
!is.nullOrUndefined(input) &&
|
||||
/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(input)
|
||||
);
|
||||
},
|
||||
nullOrUndefined(input) {
|
||||
return input === null || typeof input === 'undefined';
|
||||
},
|
||||
empty(input) {
|
||||
return (
|
||||
is.nullOrUndefined(input) ||
|
||||
((is.string(input) || is.array(input) || is.nodeList(input)) && !input.length) ||
|
||||
(is.object(input) && !Object.keys(input).length)
|
||||
);
|
||||
},
|
||||
const isEmpty = input =>
|
||||
isNullOrUndefined(input) ||
|
||||
((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||
|
||||
(isObject(input) && !Object.keys(input).length);
|
||||
|
||||
const isUrl = input => {
|
||||
// Accept a URL object
|
||||
if (instanceOf(input, window.URL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add the protocol if required
|
||||
let string = input;
|
||||
if (!input.startsWith('http://') || !input.startsWith('https://')) {
|
||||
string = `http://${input}`;
|
||||
}
|
||||
|
||||
try {
|
||||
return !isEmpty(new URL(string).hostname);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export default is;
|
||||
export default {
|
||||
nullOrUndefined: isNullOrUndefined,
|
||||
object: isObject,
|
||||
number: isNumber,
|
||||
string: isString,
|
||||
boolean: isBoolean,
|
||||
function: isFunction,
|
||||
array: isArray,
|
||||
weakMap: isWeakMap,
|
||||
nodeList: isNodeList,
|
||||
element: isElement,
|
||||
textNode: isTextNode,
|
||||
event: isEvent,
|
||||
cue: isCue,
|
||||
track: isTrack,
|
||||
url: isUrl,
|
||||
empty: isEmpty,
|
||||
};
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// Sprite loader
|
||||
// ==========================================================================
|
||||
|
||||
import Storage from './../storage';
|
||||
import Storage from '../storage';
|
||||
import fetch from './fetch';
|
||||
import is from './is';
|
||||
|
||||
// Load an external SVG sprite
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
.plyr__controls {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
text-align: center;
|
||||
|
||||
// Spacing
|
||||
@@ -23,6 +24,7 @@
|
||||
&:first-child,
|
||||
&:first-child + [data-plyr='pause'] {
|
||||
margin-left: 0;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,13 +50,17 @@
|
||||
|
||||
// Video controls
|
||||
.plyr--video .plyr__controls {
|
||||
background: linear-gradient(rgba($plyr-video-controls-bg, 0), rgba($plyr-video-controls-bg, 0.7));
|
||||
background: linear-gradient(
|
||||
rgba($plyr-video-controls-bg, 0),
|
||||
rgba($plyr-video-controls-bg, 0.7)
|
||||
);
|
||||
border-bottom-left-radius: inherit;
|
||||
border-bottom-right-radius: inherit;
|
||||
bottom: 0;
|
||||
color: $plyr-video-control-color;
|
||||
left: 0;
|
||||
padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing $plyr-control-spacing;
|
||||
padding: ($plyr-control-spacing * 3.5) $plyr-control-spacing
|
||||
$plyr-control-spacing;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out;
|
||||
@@ -103,3 +109,11 @@
|
||||
.plyr--fullscreen-enabled [data-plyr='fullscreen'] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.plyr__controls:empty {
|
||||
display: none;
|
||||
|
||||
~ .plyr__captions {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,6 @@ $embed-padding: ((100 / 16) * 9);
|
||||
$height: 240;
|
||||
$offset: to-percentage(($height - $embed-padding) / ($height / 50));
|
||||
|
||||
// To allow mouse events to be captured if full support
|
||||
iframe {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Only used for Vimeo
|
||||
> .plyr__video-embed__container {
|
||||
padding-bottom: to-percentage($height);
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
transition: opacity 0.3s ease;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.plyr--stopped.plyr__poster-enabled .plyr__poster {
|
||||
opacity: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
border: 0;
|
||||
border-radius: ($plyr-range-track-height / 2);
|
||||
height: $plyr-range-track-height;
|
||||
transition: all 0.3s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user