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:
Sam Potts 2018-06-18 22:17:34 +10:00
commit d64ed4ba5a
20 changed files with 291 additions and 266 deletions

View File

@ -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.

View File

@ -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!)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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"

View File

@ -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
View File

@ -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

File diff suppressed because one or more lines are too long

2
dist/plyr.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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",

View File

@ -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

View File

@ -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)
// ==========================================================================

View File

@ -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)
// ==========================================================================

View File

@ -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);

View File

@ -3,6 +3,7 @@
// ==========================================================================
import Storage from './../storage';
import fetch from './fetch';
import is from './is';
// Load an external SVG sprite