Merge branch 'develop' into a11y-improvements
# Conflicts: # dist/plyr.js.map # dist/plyr.min.js # dist/plyr.min.js.map
This commit is contained in:
commit
d64ed4ba5a
@ -2,20 +2,31 @@
|
||||
|
||||
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 create support issues here. Use [Stack Overflow](https://stackoverflow.com/) or [our Slack](https://bit.ly/plyr-chat) for that.
|
||||
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), or that there isn't already an open issue for it.
|
||||
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.
|
||||
|
||||
Describe the issue as detailed as possible, answering these questions:
|
||||
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 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)
|
||||
@ -25,15 +36,13 @@ Describe the issue as detailed as possible, answering these questions:
|
||||
* [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 implementation is using a framework, library or custom methods, which aren't needed to reproduce the issue, 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") it also means that the person who is trying to fix the issue either has to know or learn your frameworks, libraries and custom methods, or that no one will try to fix your issue because it's too much work.
|
||||
|
||||
In order to keep things on topic and to avoid bothering people with github notifications, please don't combine multiple problems or bugs into one issue, don't comment on issues unless your comment is related to that issue, and don't post "+1" or "I agree" type of comments. Use the emojis instead.
|
||||
|
||||
Last but not least: Keep a civil tone in issues and comments. Non-constructive comments may be removed.
|
||||
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 it's 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.
|
||||
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
|
||||
|
||||
@ -43,7 +52,7 @@ If you are missing something in Plyr, you can create a GitHub issue for this as
|
||||
|
||||
* 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 logging or breakpoints you added for testing, and the build output.
|
||||
* 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.
|
||||
|
||||
|
24
changelog.md
24
changelog.md
@ -1,3 +1,27 @@
|
||||
# v3.3.14
|
||||
|
||||
- Fix sprite loading regression
|
||||
|
||||
# v3.3.13
|
||||
|
||||
You guessed it, a load of awesome changes from contributors:
|
||||
|
||||
Thanks @friday for the following:
|
||||
|
||||
- Captions fixes
|
||||
- Fix poster race conditions
|
||||
- Minor code improvements for quality switching
|
||||
- Minor event changes
|
||||
- Fix condition in events.toggleListener to allow non-elements
|
||||
- Suggestion: Remove array newline rule
|
||||
- Contributions improvements
|
||||
|
||||
- fix: html5.cancelRequest not remove source tag correctly (thanks @a60814billy)
|
||||
- remove event listeners in destroy() (thanks @cky917)
|
||||
- Fix markdown in README (thanks @azu)
|
||||
- Some parts of the accessibility improvements outlined in #905 (more on the way...)
|
||||
- Fix for bug where volume slider didn't always show
|
||||
|
||||
# v3.3.12
|
||||
|
||||
- Fix synthetic event bubble/proxy loses detail (thanks @friday!)
|
||||
|
2
demo/dist/demo.js.map
vendored
2
demo/dist/demo.js.map
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js.map
vendored
2
demo/dist/demo.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -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"
|
||||
|
@ -143,7 +143,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 +219,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 +232,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;
|
||||
|
96
dist/plyr.js
vendored
96
dist/plyr.js
vendored
@ -1148,6 +1148,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
|
||||
@ -2695,51 +2740,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
@ -2819,7 +2819,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);
|
||||
@ -5235,7 +5235,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;
|
||||
}
|
||||
@ -5650,7 +5650,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);
|
||||
|
2
dist/plyr.js.map
vendored
2
dist/plyr.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js
vendored
2
dist/plyr.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js.map
vendored
2
dist/plyr.min.js.map
vendored
File diff suppressed because one or more lines are too long
345
dist/plyr.polyfilled.js
vendored
345
dist/plyr.polyfilled.js
vendored
@ -5768,12 +5768,19 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Inaert an element after another
|
||||
function insertAfter(element, target) {
|
||||
if (!is$1.element(element) || !is$1.element(target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
target.parentNode.insertBefore(element, target.nextSibling);
|
||||
}
|
||||
|
||||
// Insert a DocumentFragment
|
||||
function insertElement(type, parent, attributes, text) {
|
||||
// Inject the new <element>
|
||||
if (!is$1.element(parent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent.appendChild(createElement(type, attributes, text));
|
||||
}
|
||||
|
||||
@ -5793,6 +5800,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Remove all child elements
|
||||
function emptyElement(element) {
|
||||
if (!is$1.element(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var length = element.childNodes.length;
|
||||
|
||||
|
||||
@ -6523,6 +6534,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
|
||||
@ -6976,31 +7032,16 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
_ref$checked = _ref.checked,
|
||||
checked = _ref$checked === undefined ? false : _ref$checked;
|
||||
|
||||
var item = createElement('li');
|
||||
|
||||
var label = createElement('label', {
|
||||
class: this.config.classNames.control
|
||||
});
|
||||
|
||||
var radio = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
||||
type: 'radio',
|
||||
name: 'plyr-' + type,
|
||||
var item = createElement('button', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
||||
type: 'button',
|
||||
value: value,
|
||||
checked: checked,
|
||||
class: 'plyr__sr-only'
|
||||
}));
|
||||
|
||||
var faux = createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
label.insertAdjacentHTML('beforeend', title);
|
||||
'aria-checked': checked
|
||||
}), title);
|
||||
|
||||
if (is$1.element(badge)) {
|
||||
label.appendChild(badge);
|
||||
item.appendChild(badge);
|
||||
}
|
||||
|
||||
item.appendChild(label);
|
||||
list.appendChild(item);
|
||||
},
|
||||
|
||||
@ -7265,8 +7306,8 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab: function toggleTab(setting, toggle) {
|
||||
toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
toggleMenuButton: function toggleMenuButton(setting, toggle) {
|
||||
toggleHidden(this.elements.settings.buttons[setting], !toggle);
|
||||
},
|
||||
|
||||
|
||||
@ -7275,12 +7316,12 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
var _this3 = this;
|
||||
|
||||
// Menu required
|
||||
if (!is$1.element(this.elements.settings.panes.quality)) {
|
||||
if (!is$1.element(this.elements.settings.menus.quality)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var type = 'quality';
|
||||
var list = this.elements.settings.panes.quality.querySelector('ul');
|
||||
var list = this.elements.settings.menus.quality.querySelector('[role="menu"]');
|
||||
|
||||
// Set options if passed and filter based on uniqueness and config
|
||||
if (is$1.array(options)) {
|
||||
@ -7291,7 +7332,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Toggle the pane and tab
|
||||
var toggle = !is$1.empty(this.options.quality) && this.options.quality.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
controls.toggleMenuButton.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
@ -7363,7 +7404,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Update the selected setting
|
||||
updateSetting: function updateSetting(setting, container, input) {
|
||||
var pane = this.elements.settings.panes[setting];
|
||||
var pane = this.elements.settings.menus[setting];
|
||||
var value = null;
|
||||
var list = container;
|
||||
|
||||
@ -7392,7 +7433,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Get the list if we need to
|
||||
if (!is$1.element(list)) {
|
||||
list = pane && pane.querySelector('ul');
|
||||
list = pane && pane.querySelector('[role="menu"]');
|
||||
}
|
||||
|
||||
// If there's no list it means it's not been rendered...
|
||||
@ -7401,14 +7442,14 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// Update the label
|
||||
var label = this.elements.settings.tabs[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||
var label = this.elements.settings.buttons[setting].querySelector('.' + this.config.classNames.menu.value);
|
||||
label.innerHTML = controls.getLabel.call(this, setting, value);
|
||||
|
||||
// Find the radio option and check it
|
||||
var target = list && list.querySelector('input[value="' + value + '"]');
|
||||
var target = list && list.querySelector('button[value="' + value + '"]');
|
||||
|
||||
if (is$1.element(target)) {
|
||||
target.checked = true;
|
||||
target.setAttribute('aria-checked', true);
|
||||
}
|
||||
},
|
||||
|
||||
@ -7416,17 +7457,17 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Set the looping options
|
||||
/* setLoopMenu() {
|
||||
// Menu required
|
||||
if (!is.element(this.elements.settings.panes.loop)) {
|
||||
if (!is.element(this.elements.settings.menus.loop)) {
|
||||
return;
|
||||
}
|
||||
const options = ['start', 'end', 'all', 'reset'];
|
||||
const list = this.elements.settings.panes.loop.querySelector('ul');
|
||||
const list = this.elements.settings.menus.loop.querySelector('[role="menu"]');
|
||||
// Show the pane and tab
|
||||
toggleHidden(this.elements.settings.tabs.loop, false);
|
||||
toggleHidden(this.elements.settings.panes.loop, false);
|
||||
toggleHidden(this.elements.settings.buttons.loop, false);
|
||||
toggleHidden(this.elements.settings.menus.loop, false);
|
||||
// Toggle the pane and tab
|
||||
const toggle = !is.empty(this.loop.options);
|
||||
controls.toggleTab.call(this, 'loop', toggle);
|
||||
controls.toggleMenuButton.call(this, 'loop', toggle);
|
||||
// Empty the menu
|
||||
emptyElement(list);
|
||||
options.forEach(option => {
|
||||
@ -7458,11 +7499,11 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// TODO: Captions or language? Currently it's mixed
|
||||
var type = 'captions';
|
||||
var list = this.elements.settings.panes.captions.querySelector('ul');
|
||||
var list = this.elements.settings.menus.captions.querySelector('[role="menu"]');
|
||||
var tracks = captions.getTracks.call(this);
|
||||
|
||||
// Toggle the pane and tab
|
||||
controls.toggleTab.call(this, type, tracks.length);
|
||||
controls.toggleMenuButton.call(this, type, tracks.length);
|
||||
|
||||
// Empty the menu
|
||||
emptyElement(list);
|
||||
@ -7513,7 +7554,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// Menu required
|
||||
if (!is$1.element(this.elements.settings.panes.speed)) {
|
||||
if (!is$1.element(this.elements.settings.menus.speed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7533,7 +7574,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Toggle the pane and tab
|
||||
var toggle = !is$1.empty(this.options.speed) && this.options.speed.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
controls.toggleMenuButton.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
@ -7544,7 +7585,7 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
}
|
||||
|
||||
// Get the list to populate
|
||||
var list = this.elements.settings.panes.speed.querySelector('ul');
|
||||
var list = this.elements.settings.menus.speed.querySelector('[role="menu"]');
|
||||
|
||||
// Empty the menu
|
||||
emptyElement(list);
|
||||
@ -7565,10 +7606,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Check if we need to hide/show the settings menu
|
||||
checkMenu: function checkMenu() {
|
||||
var tabs = this.elements.settings.tabs;
|
||||
var buttons = this.elements.settings.buttons;
|
||||
|
||||
var visible = !is$1.empty(tabs) && Object.values(tabs).some(function (tab) {
|
||||
return !tab.hidden;
|
||||
var visible = !is$1.empty(buttons) && Object.values(buttons).some(function (button) {
|
||||
return !button.hidden;
|
||||
});
|
||||
|
||||
toggleHidden(this.elements.settings.menu, !visible);
|
||||
@ -7577,19 +7618,19 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Show/hide menu
|
||||
toggleMenu: function toggleMenu(event) {
|
||||
var form = this.elements.settings.form;
|
||||
var popup = this.elements.settings.popup;
|
||||
|
||||
var button = this.elements.buttons.settings;
|
||||
|
||||
// Menu and button are required
|
||||
if (!is$1.element(form) || !is$1.element(button)) {
|
||||
if (!is$1.element(popup) || !is$1.element(button)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var show = is$1.boolean(event) ? event : is$1.element(form) && form.hasAttribute('hidden');
|
||||
var show = is$1.boolean(event) ? event : is$1.element(popup) && popup.hasAttribute('hidden');
|
||||
|
||||
if (is$1.event(event)) {
|
||||
var isMenuItem = is$1.element(form) && form.contains(event.target);
|
||||
var isMenuItem = is$1.element(popup) && popup.contains(event.target);
|
||||
var isButton = event.target === this.elements.buttons.settings;
|
||||
|
||||
// If the click was inside the form or if the click
|
||||
@ -7610,14 +7651,14 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
button.setAttribute('aria-expanded', show);
|
||||
}
|
||||
|
||||
if (is$1.element(form)) {
|
||||
toggleHidden(form, !show);
|
||||
if (is$1.element(popup)) {
|
||||
toggleHidden(popup, !show);
|
||||
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||
|
||||
if (show) {
|
||||
form.removeAttribute('tabindex');
|
||||
popup.removeAttribute('tabindex');
|
||||
} else {
|
||||
form.setAttribute('tabindex', -1);
|
||||
popup.setAttribute('tabindex', -1);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -7631,10 +7672,10 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
|
||||
var name = input.getAttribute('name');
|
||||
input.setAttribute('name', name + '-clone');
|
||||
});
|
||||
/* Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
||||
const name = input.getAttribute('name');
|
||||
input.setAttribute('name', `${name}-clone`);
|
||||
}); */
|
||||
|
||||
// Append to parent so we get the "real" size
|
||||
tab.parentNode.appendChild(clone);
|
||||
@ -7654,34 +7695,37 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
|
||||
// Toggle Menu
|
||||
showTab: function showTab() {
|
||||
showMenu: function showMenu() {
|
||||
var _this6 = this;
|
||||
|
||||
var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
||||
var menu = this.elements.settings.menu;
|
||||
|
||||
var pane = document.getElementById(target);
|
||||
var pane = document.getElementById('plyr-settings-' + this.id + '-' + type);
|
||||
|
||||
console.warn('plyr-settings-' + this.id + '-' + type);
|
||||
|
||||
// Nothing to show, bail
|
||||
if (!is$1.element(pane)) {
|
||||
console.warn('No pane found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Are we targeting a tab? If not, bail
|
||||
var isTab = pane.getAttribute('role') === 'tabpanel';
|
||||
/* const isTab = pane.getAttribute('role') === 'tabpanel';
|
||||
if (!isTab) {
|
||||
return;
|
||||
}
|
||||
} */
|
||||
|
||||
// Hide all other tabs
|
||||
// Get other tabs
|
||||
var current = menu.querySelector('[role="tabpanel"]:not([hidden])');
|
||||
var current = menu.querySelector('[id^=plyr-settings-' + this.id + ']:not([hidden])');
|
||||
var container = current.parentNode;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
Array.from(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]')).forEach(function (toggle) {
|
||||
/* Array.from(menu.querySelectorAll(`[aria-controls="${current.getAttribute('id')}"]`)).forEach(toggle => {
|
||||
toggle.setAttribute('aria-expanded', false);
|
||||
});
|
||||
}); */
|
||||
|
||||
// If we can do fancy animations, we'll animate the height/width
|
||||
if (support.transitions && !support.reducedMotion) {
|
||||
@ -7717,16 +7761,16 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Set attributes on current tab
|
||||
toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
// current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
toggleHidden(pane, false);
|
||||
|
||||
var tabs = getElements.call(this, '[aria-controls="' + target + '"]');
|
||||
Array.from(tabs).forEach(function (tab) {
|
||||
/* const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
||||
Array.from(tabs).forEach(tab => {
|
||||
tab.setAttribute('aria-expanded', true);
|
||||
});
|
||||
pane.removeAttribute('tabindex');
|
||||
pane.removeAttribute('tabindex'); */
|
||||
|
||||
// Focus the first item
|
||||
pane.querySelectorAll('button:not(:disabled), input:not(:disabled), [tabindex]')[0].focus();
|
||||
@ -7839,55 +7883,46 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
|
||||
// Settings button / menu
|
||||
if (this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) {
|
||||
var menu = createElement('div', {
|
||||
var control = createElement('div', {
|
||||
class: 'plyr__menu',
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
menu.appendChild(controls.createButton.call(this, 'settings', {
|
||||
control.appendChild(controls.createButton.call(this, 'settings', {
|
||||
id: 'plyr-settings-toggle-' + data.id,
|
||||
'aria-haspopup': true,
|
||||
'aria-controls': 'plyr-settings-' + data.id,
|
||||
'aria-expanded': false
|
||||
}));
|
||||
|
||||
var form = createElement('form', {
|
||||
var popup = createElement('div', {
|
||||
class: 'plyr__menu__container',
|
||||
id: 'plyr-settings-' + data.id,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tablist',
|
||||
tabindex: -1
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id
|
||||
});
|
||||
|
||||
var inner = createElement('div');
|
||||
|
||||
var home = createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-home',
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tabpanel'
|
||||
id: 'plyr-settings-' + data.id + '-home'
|
||||
});
|
||||
|
||||
// Create the tab list
|
||||
var tabs = createElement('ul', {
|
||||
role: 'tablist'
|
||||
// Create the menu
|
||||
var menu = createElement('div', {
|
||||
role: 'menu'
|
||||
});
|
||||
|
||||
// Build the tabs
|
||||
// Build the menu items
|
||||
this.config.settings.forEach(function (type) {
|
||||
var tab = createElement('li', {
|
||||
role: 'tab',
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
var button = createElement('button', extend(getAttributesFromSelector(_this7.config.selectors.buttons.settings), {
|
||||
var menuItem = createElement('button', extend(getAttributesFromSelector(_this7.config.selectors.buttons.settings), {
|
||||
type: 'button',
|
||||
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--forward',
|
||||
id: 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
'aria-haspopup': true,
|
||||
'aria-controls': 'plyr-settings-' + data.id + '-' + type,
|
||||
'aria-expanded': false
|
||||
}), i18n.get(type, _this7.config));
|
||||
'role': 'menuitem',
|
||||
'aria-haspopup': true
|
||||
}));
|
||||
|
||||
var flex = createElement('span', null, i18n.get(type, _this7.config));
|
||||
|
||||
var value = createElement('span', {
|
||||
class: _this7.config.classNames.menu.value
|
||||
@ -7896,50 +7931,46 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Speed contains HTML entities
|
||||
value.innerHTML = data[type];
|
||||
|
||||
button.appendChild(value);
|
||||
tab.appendChild(button);
|
||||
tabs.appendChild(tab);
|
||||
flex.appendChild(value);
|
||||
menuItem.appendChild(flex);
|
||||
menu.appendChild(menuItem);
|
||||
|
||||
_this7.elements.settings.tabs[type] = tab;
|
||||
});
|
||||
|
||||
home.appendChild(tabs);
|
||||
inner.appendChild(home);
|
||||
|
||||
// Build the panes
|
||||
this.config.settings.forEach(function (type) {
|
||||
// Build the panes
|
||||
var pane = createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-' + type,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
role: 'tabpanel',
|
||||
tabindex: -1
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
var back = createElement('button', {
|
||||
// Back button
|
||||
pane.appendChild(createElement('button', {
|
||||
type: 'button',
|
||||
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--back',
|
||||
'aria-haspopup': true,
|
||||
'aria-controls': 'plyr-settings-' + data.id + '-home',
|
||||
'aria-expanded': false
|
||||
}, i18n.get(type, _this7.config));
|
||||
class: _this7.config.classNames.control + ' ' + _this7.config.classNames.control + '--back'
|
||||
}, i18n.get(type, _this7.config)));
|
||||
|
||||
pane.appendChild(back);
|
||||
// Menu
|
||||
pane.appendChild(createElement('div', {
|
||||
role: 'menu'
|
||||
}));
|
||||
|
||||
var options = createElement('ul');
|
||||
|
||||
pane.appendChild(options);
|
||||
inner.appendChild(pane);
|
||||
|
||||
_this7.elements.settings.panes[type] = pane;
|
||||
menuItem.addEventListener('click', function () {
|
||||
controls.showMenu.call(_this7, type);
|
||||
});
|
||||
|
||||
_this7.elements.settings.buttons[type] = menuItem;
|
||||
_this7.elements.settings.menus[type] = pane;
|
||||
});
|
||||
|
||||
form.appendChild(inner);
|
||||
menu.appendChild(form);
|
||||
container.appendChild(menu);
|
||||
home.appendChild(menu);
|
||||
inner.appendChild(home);
|
||||
|
||||
this.elements.settings.form = form;
|
||||
this.elements.settings.menu = menu;
|
||||
popup.appendChild(inner);
|
||||
control.appendChild(popup);
|
||||
container.appendChild(control);
|
||||
|
||||
this.elements.settings.popup = popup;
|
||||
this.elements.settings.menu = control;
|
||||
}
|
||||
|
||||
// Picture in picture button
|
||||
@ -8095,51 +8126,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 +8205,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);
|
||||
@ -10003,13 +9989,12 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
});
|
||||
|
||||
// Settings menu
|
||||
bind(this.player.elements.settings.form, 'click', function (event) {
|
||||
bind(this.player.elements.settings.popup, 'click', function (event) {
|
||||
event.stopPropagation();
|
||||
|
||||
// Go back to home tab on click
|
||||
var showHomeTab = function showHomeTab() {
|
||||
var id = 'plyr-settings-' + _this4.player.id + '-home';
|
||||
controls.showTab.call(_this4.player, id);
|
||||
controls.showMenu.call(_this4.player, 'home');
|
||||
};
|
||||
|
||||
// Settings menu items - use event delegation as items are added/removed
|
||||
@ -10028,9 +10013,6 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
_this4.player.speed = parseFloat(event.target.value);
|
||||
showHomeTab();
|
||||
}, 'speed');
|
||||
} else {
|
||||
var tab = event.target;
|
||||
controls.showTab.call(_this4.player, tab.getAttribute('aria-controls'));
|
||||
}
|
||||
});
|
||||
|
||||
@ -10633,7 +10615,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 +11030,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);
|
||||
@ -12332,16 +12314,17 @@ typeof navigator === "object" && (function (global, factory) {
|
||||
// Elements cache
|
||||
this.elements = {
|
||||
container: null,
|
||||
captions: null,
|
||||
buttons: {},
|
||||
display: {},
|
||||
progress: {},
|
||||
inputs: {},
|
||||
settings: {
|
||||
popup: null,
|
||||
menu: null,
|
||||
panes: {},
|
||||
tabs: {}
|
||||
},
|
||||
captions: null
|
||||
menus: {},
|
||||
buttons: {}
|
||||
}
|
||||
};
|
||||
|
||||
// Captions
|
||||
|
2
dist/plyr.polyfilled.js.map
vendored
2
dist/plyr.polyfilled.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js
vendored
2
dist/plyr.polyfilled.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js.map
vendored
2
dist/plyr.polyfilled.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "plyr",
|
||||
"version": "3.3.12",
|
||||
"version": "3.3.14",
|
||||
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||
"homepage": "https://plyr.io",
|
||||
"main": "./dist/plyr.js",
|
||||
|
@ -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.12/plyr.js"></script>
|
||||
<script src="https://cdn.plyr.io/3.3.14/plyr.js"></script>
|
||||
```
|
||||
|
||||
...or...
|
||||
|
||||
```html
|
||||
<script src="https://cdn.plyr.io/3.3.12/plyr.polyfilled.js"></script>
|
||||
<script src="https://cdn.plyr.io/3.3.14/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.12/plyr.css">
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.3.14/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.12/plyr.svg`.
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.3.14/plyr.svg`.
|
||||
|
||||
## Ads
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr
|
||||
// plyr.js v3.3.12
|
||||
// plyr.js v3.3.14
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr Polyfilled Build
|
||||
// plyr.js v3.3.12
|
||||
// plyr.js v3.3.14
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
|
@ -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);
|
||||
|
@ -3,6 +3,7 @@
|
||||
// ==========================================================================
|
||||
|
||||
import Storage from './../storage';
|
||||
import fetch from './fetch';
|
||||
import is from './is';
|
||||
|
||||
// Load an external SVG sprite
|
||||
|
Loading…
x
Reference in New Issue
Block a user