Fullscreen API methods (Fixes #74), onSetup callback

This commit is contained in:
Sam Potts 2015-04-06 11:47:23 +10:00
parent 2f4c56176d
commit 5322f4c62f
9 changed files with 123 additions and 73 deletions

View File

@ -1,5 +1,9 @@
# Changelog # Changelog
## v1.1.2
- Added an onSetup callback option
- Added fullscreen API methods toggleFullscreen() (must be user iniated), and isFullscreen()
## v1.1.1 ## v1.1.1
- Fix for unsupported browser handling - Fix for unsupported browser handling
- Fix for config.controls having no effect - Fix for config.controls having no effect

2
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

2
docs/dist/docs.js vendored

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Docs styles --> <!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.1.1/docs.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.2/docs.css">
</head> </head>
<body> <body>
<main> <main>

View File

@ -8,10 +8,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Styles --> <!-- Styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.1.1/plyr.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.2/plyr.css">
<!-- Docs styles --> <!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.1.1/docs.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.2/docs.css">
</head> </head>
<body> <body>
<header> <header>
@ -83,13 +83,13 @@
b.insertBefore(c, b.childNodes[0]); b.insertBefore(c, b.childNodes[0]);
} }
} }
})(document, "https://cdn.plyr.io/1.1.1/sprite.svg"); })(document, "https://cdn.plyr.io/1.1.2/sprite.svg");
</script> </script>
<!-- Plyr core script --> <!-- Plyr core script -->
<script src="//cdn.plyr.io/1.1.1/plyr.js"></script> <script src="//cdn.plyr.io/1.1.2/plyr.js"></script>
<!-- Docs script --> <!-- Docs script -->
<script src="//cdn.plyr.io/1.1.1/docs.js"></script> <script src="//cdn.plyr.io/1.1.2/docs.js"></script>
</body> </body>
</html> </html>

View File

@ -11,9 +11,21 @@ plyr.setup({
html: templates.controls.render({}), html: templates.controls.render({}),
captions: { captions: {
defaultActive: true defaultActive: true
},
onSetup: function() {
var player = this,
type = player.media.tagName.toLowerCase(),
toggle = document.querySelector("[data-toggle='fullscreen']");
console.log("✓ Setup done for <" + type + ">");
if(type === "video" && toggle) {
toggle.addEventListener("click", player.toggleFullscreen, false);
}
} }
}); });
// Google analytics // Google analytics
// For demo site (http://[www.]plyr.io) only // For demo site (http://[www.]plyr.io) only
if(document.domain.indexOf("plyr.io") > -1) { if(document.domain.indexOf("plyr.io") > -1) {

View File

@ -1,6 +1,6 @@
{ {
"name": "plyr", "name": "plyr",
"version": "1.1.1", "version": "1.1.2",
"description": "A simple HTML5 media player using custom controls", "description": "A simple HTML5 media player using custom controls",
"homepage": "http://plyr.io", "homepage": "http://plyr.io",
"main": "gulpfile.js", "main": "gulpfile.js",

View File

@ -10,7 +10,7 @@ We wanted a lightweight, accessible and customisable media player that just supp
## Features ## Features
- **Accessible** - full support for captions and screen readers. - **Accessible** - full support for captions and screen readers.
- **Lightweight** - just 6KB minified and gzipped. - **Lightweight** - just 6.4KB minified and gzipped.
- **Customisable** - make the player look how you want with the markup you want. - **Customisable** - make the player look how you want with the markup you want.
- **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks. - **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks.
- **Responsive** - as you'd expect these days. - **Responsive** - as you'd expect these days.
@ -38,7 +38,7 @@ If you have any cool ideas or features, please let me know by [creating an issue
Check `docs/index.html` and `docs/dist/docs.js` for an example setup. Check `docs/index.html` and `docs/dist/docs.js` for an example setup.
**Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.1.1/plyr.js` to `https://cdn.plyr.io/1.1.1/plyr.js` **Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.1.2/plyr.js` to `https://cdn.plyr.io/1.1.2/plyr.js`
### Bower ### Bower
If bower is your thang, you can grab Plyr using: If bower is your thang, you can grab Plyr using:
@ -47,15 +47,22 @@ bower install plyr
``` ```
More info on setting up dependencies can be found in the [Bower Docs](http://bower.io/docs/creating-packages/#maintaining-dependencies) More info on setting up dependencies can be found in the [Bower Docs](http://bower.io/docs/creating-packages/#maintaining-dependencies)
### Ember
The awesome [@louisrudner](https://twitter.com/louisrudner) has created an ember component, available by running:
```
ember addon:install ember-cli-plyr
```
More info is on [npm](https://www.npmjs.com/package/ember-cli-plyr) and [GitHub](https://github.com/louisrudner/ember-cli-plyr)
### CDN ### CDN
If you want to use our CDN, you can use the following. HTTPS (SSL) is supported. If you want to use our CDN, you can use the following. HTTPS (SSL) is supported.
```html ```html
<link rel="stylesheet" href="//cdn.plyr.io/1.1.1/plyr.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.2/plyr.css">
<script src="//cdn.plyr.io/1.1.1/plyr.js"></script> <script src="//cdn.plyr.io/1.1.2/plyr.js"></script>
``` ```
You can also access the `sprite.svg` file at `//cdn.plyr.io/1.1.1/sprite.svg`. You can also access the `sprite.svg` file at `//cdn.plyr.io/1.1.2/sprite.svg`.
### CSS ### CSS
If you want to use the default css, add the `plyr.css` file from /dist into your head, or even better use `plyr.less` or `plyr.sass` file included in `/src` in your build to save a request. If you want to use the default css, add the `plyr.css` file from /dist into your head, or even better use `plyr.less` or `plyr.sass` file included in `/src` in your build to save a request.
@ -130,7 +137,7 @@ You'll notice the `crossorigin` attribute on the example `<video>` and `<audio>`
More info on CORS here: More info on CORS here:
[https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) [https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)
###JavaScript ### JavaScript
Much of the behaviour of the player is configurable when initialising the library. Below is an example of a default instance. Much of the behaviour of the player is configurable when initialising the library. Below is an example of a default instance.
```html ```html
@ -240,6 +247,12 @@ You can pass the following options to the setup method.
<td>&mdash;</td> <td>&mdash;</td>
<td>Two properties; <code>enabled</code> which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later. The second property <code>key</code> is the key used for the local storage. The default is <code>plyr_volume</code> until more settings are stored.</td> <td>Two properties; <code>enabled</code> which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later. The second property <code>key</code> is the key used for the local storage. The default is <code>plyr_volume</code> until more settings are stored.</td>
</tr> </tr>
<tr>
<td><code>onSetup</code></td>
<td>Function</td>
<td>&mdash;</td>
<td>This callback function is called on every new plyr instance created. The context (<code>this</code>) is the plyr instance itself.</td>
</tr>
</tbody> </tbody>
</table> </table>
@ -307,6 +320,16 @@ Here's a list of the methods supported:
<td>&mdash;</td> <td>&mdash;</td>
<td>Toggles whether captions are enabled.</td> <td>Toggles whether captions are enabled.</td>
</tr> </tr>
<tr>
<td><code>toggleFullscreen()</code></td>
<td>&mdash;</td>
<td>Toggles fullscreen. This can only be initiated by a user gesture due to browser security, i.e. a user event such as click.</td>
</tr>
<tr>
<td><code>isFullscreen()</code></td>
<td>&mdash;</td>
<td>Boolean returned if the player is in fullscreen.</td>
</tr>
<tr> <tr>
<td><code>support(...)</code></td> <td><code>support(...)</code></td>
<td>String</td> <td>String</td>
@ -350,11 +373,12 @@ A complete list of events can be found here:
[Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html) [Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html)
## Fullscreen ## Fullscreen
Fullscreen in Plyr is supported for all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). If you're using the default CSS, you can also use a "full browser" mode which will use the full browser window by adding the `player-fullscreen` class to your container. Fullscreen in Plyr is supported for all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). If you're using the default CSS, you can also use a "full browser" mode which will use the full browser window by adding the `player-fullscreen` class to your container.
## Browser support ## Browser support
<table width="100%" style="text-align: center;"> <table width="100%" style="text-align: center">
<thead> <thead>
<tr> <tr>
<td>Safari</td> <td>Safari</td>
@ -392,11 +416,14 @@ If a User Agent is disabled but supports `<video>` and `<audio>` natively, it wi
Any unsupported browsers will display links to download the media if the correct html is used. Any unsupported browsers will display links to download the media if the correct html is used.
### Checking for support
There's an API method for checking support. You can call `plyr.supported()` and optionally pass a type to it, e.g. `plyr.supported("video")`. It will return an object with two keys; `basic` meaning there's basic support for that media type (or both if no type is passed) and `full` meaning there's full support for plyr.
## Issues ## Issues
If you find anything weird with Plyr, please let us know using the GitHub issues tracker. If you find anything weird with Plyr, please let us know using the GitHub issues tracker.
## Author ## Author
Plyr is developed by Sam Potts ([@sam_potts](https://twitter.com/sam_potts)) ([sampotts.me](http://sampotts.me)) Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me](http://sampotts.me)
## Mentions ## Mentions
- [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) - [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/)

View File

@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr // Plyr
// plyr.js v1.1.1 // plyr.js v1.1.2
// https://github.com/selz/plyr // https://github.com/selz/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
@ -80,7 +80,8 @@
enabled: true, enabled: true,
key: "plyr_volume" key: "plyr_volume"
}, },
controls: ["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"] controls: ["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"],
onSetup: function() {},
}; };
// Build the default HTML // Build the default HTML
@ -234,8 +235,8 @@
function _browserSniff() { function _browserSniff() {
var nAgt = navigator.userAgent, var nAgt = navigator.userAgent,
name = navigator.appName, name = navigator.appName,
fullVersion = ""+parseFloat(navigator.appVersion), fullVersion = "" + parseFloat(navigator.appVersion),
majorVersion = parseInt(navigator.appVersion,10), majorVersion = parseInt(navigator.appVersion, 10),
nameOffset, nameOffset,
verOffset, verOffset,
ix; ix;
@ -248,46 +249,47 @@
// MSIE // MSIE
else if ((verOffset=nAgt.indexOf("MSIE")) !== -1) { else if ((verOffset=nAgt.indexOf("MSIE")) !== -1) {
name = "IE"; name = "IE";
fullVersion = nAgt.substring(verOffset+5); fullVersion = nAgt.substring(verOffset + 5);
} }
// Chrome // Chrome
else if ((verOffset=nAgt.indexOf("Chrome")) !== -1) { else if ((verOffset=nAgt.indexOf("Chrome")) !== -1) {
name = "Chrome"; name = "Chrome";
fullVersion = nAgt.substring(verOffset+7); fullVersion = nAgt.substring(verOffset + 7);
} }
// Safari // Safari
else if ((verOffset=nAgt.indexOf("Safari")) !== -1) { else if ((verOffset=nAgt.indexOf("Safari")) !== -1) {
name = "Safari"; name = "Safari";
fullVersion = nAgt.substring(verOffset+7); fullVersion = nAgt.substring(verOffset + 7);
if ((verOffset=nAgt.indexOf("Version")) !== -1) { if ((verOffset=nAgt.indexOf("Version")) !== -1) {
fullVersion = nAgt.substring(verOffset+8); fullVersion = nAgt.substring(verOffset + 8);
} }
} }
// Firefox // Firefox
else if ((verOffset=nAgt.indexOf("Firefox")) !== -1) { else if ((verOffset=nAgt.indexOf("Firefox")) !== -1) {
name = "Firefox"; name = "Firefox";
fullVersion = nAgt.substring(verOffset+8); fullVersion = nAgt.substring(verOffset + 8);
} }
// In most other browsers, "name/version" is at the end of userAgent // In most other browsers, "name/version" is at the end of userAgent
else if ( (nameOffset=nAgt.lastIndexOf(" ")+1) < (verOffset=nAgt.lastIndexOf("/")) ) { else if ((nameOffset=nAgt.lastIndexOf(" ") + 1) < (verOffset=nAgt.lastIndexOf("/"))) {
name = nAgt.substring(nameOffset,verOffset); name = nAgt.substring(nameOffset,verOffset);
fullVersion = nAgt.substring(verOffset+1); fullVersion = nAgt.substring(verOffset + 1);
if (name.toLowerCase()==name.toUpperCase()) {
if (name.toLowerCase() == name.toUpperCase()) {
name = navigator.appName; name = navigator.appName;
} }
} }
// Trim the fullVersion string at semicolon/space if present // Trim the fullVersion string at semicolon/space if present
if ((ix=fullVersion.indexOf(";")) !== -1) { if ((ix = fullVersion.indexOf(";")) !== -1) {
fullVersion=fullVersion.substring(0,ix); fullVersion = fullVersion.substring(0, ix);
} }
if ((ix=fullVersion.indexOf(" ")) !== -1) { if ((ix = fullVersion.indexOf(" ")) !== -1) {
fullVersion=fullVersion.substring(0,ix); fullVersion = fullVersion.substring(0, ix);
} }
// Get major version // Get major version
majorVersion = parseInt(""+fullVersion,10); majorVersion = parseInt("" + fullVersion, 10);
if (isNaN(majorVersion)) { if (isNaN(majorVersion)) {
fullVersion = ""+parseFloat(navigator.appVersion); fullVersion = "" + parseFloat(navigator.appVersion);
majorVersion = parseInt(navigator.appVersion,10); majorVersion = parseInt(navigator.appVersion, 10);
} }
// Return data // Return data
@ -340,7 +342,7 @@
// Wrap an element // Wrap an element
function _wrap(elements, wrapper) { function _wrap(elements, wrapper) {
// Convert `elms` to an array, if necessary. // Convert `elements` to an array, if necessary.
if (!elements.length) { if (!elements.length) {
elements = [elements]; elements = [elements];
} }
@ -349,15 +351,15 @@
// first element (see `child` below). // first element (see `child` below).
for (var i = elements.length - 1; i >= 0; i--) { for (var i = elements.length - 1; i >= 0; i--) {
var child = (i > 0) ? wrapper.cloneNode(true) : wrapper; var child = (i > 0) ? wrapper.cloneNode(true) : wrapper;
var el = elements[i]; var element = elements[i];
// Cache the current parent and sibling. // Cache the current parent and sibling.
var parent = el.parentNode; var parent = element.parentNode;
var sibling = el.nextSibling; var sibling = element.nextSibling;
// Wrap the element (is automatically removed from its current // Wrap the element (is automatically removed from its current
// parent). // parent).
child.appendChild(el); child.appendChild(element);
// If the element had a sibling, insert the wrapper before // If the element had a sibling, insert the wrapper before
// the sibling to maintain the HTML structure; otherwise, just // the sibling to maintain the HTML structure; otherwise, just
@ -519,7 +521,7 @@
} }
} }
// Safari doesn't support the ALLOW_KEYBOARD_INPUT flag so set it to not supported // Safari doesn't support the ALLOW_KEYBOARD_INPUT flag (for security) so set it to not supported
// https://bugs.webkit.org/show_bug.cgi?id=121496 // https://bugs.webkit.org/show_bug.cgi?id=121496
if(fullscreen.prefix === "webkit" && !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)) { if(fullscreen.prefix === "webkit" && !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)) {
fullscreen.supportsFullScreen = false; fullscreen.supportsFullScreen = false;
@ -531,19 +533,16 @@
// Sometimes the prefix is "ms", sometimes "MS" to keep you on your toes // Sometimes the prefix is "ms", sometimes "MS" to keep you on your toes
fullscreen.fullScreenEventName = (fullscreen.prefix == "ms" ? "MSFullscreenChange" : fullscreen.prefix + "fullscreenchange"); fullscreen.fullScreenEventName = (fullscreen.prefix == "ms" ? "MSFullscreenChange" : fullscreen.prefix + "fullscreenchange");
fullscreen.isFullScreen = function() { fullscreen.isFullScreen = function(element) {
if(typeof element == "undefined") {
element = document;
}
switch (this.prefix) { switch (this.prefix) {
case "": case "":
return document.fullScreen; return document.fullscreenElement == element;
case "webkit":
return document.webkitIsFullScreen;
case "ms":
// Docs say document.msFullScreenElement returns undefined
// if no element is full screem but it returns null, cheers
// https://msdn.microsoft.com/en-us/library/ie/dn265028%28v=vs.85%29.aspx
return (document.msFullscreenElement !== null);
default: default:
return document[this.prefix + "FullScreen"]; return document[this.prefix + "FullscreenElement"] == element;
} }
}; };
fullscreen.requestFullScreen = function(element) { fullscreen.requestFullScreen = function(element) {
@ -1035,7 +1034,7 @@
targetTime = input; targetTime = input;
} }
// Event // Event
else if (typeof input === "object" && (input.type === "change" || input.type === "input")) { else if (typeof input === "object" && (input.type === "input" || input.type === "change")) {
// It's the seek slider // It's the seek slider
// Seek to the selected time // Seek to the selected time
targetTime = ((input.target.value / input.target.max) * player.media.duration); targetTime = ((input.target.value / input.target.max) * player.media.duration);
@ -1072,17 +1071,18 @@
// Toggle fullscreen // Toggle fullscreen
function _toggleFullscreen(event) { function _toggleFullscreen(event) {
// Check for native support // Check for native support
var nativeSupport = fullscreen.supportsFullScreen; var nativeSupport = fullscreen.supportsFullScreen,
container = player.container;
// If it's a fullscreen change event, it's probably a native close // If it's a fullscreen change event, it's probably a native close
if(event && event.type === fullscreen.fullScreenEventName) { if(event && event.type === fullscreen.fullScreenEventName) {
config.fullscreen.active = fullscreen.isFullScreen(); player.isFullscreen = fullscreen.isFullScreen(container);
} }
// If there's native support, use it // If there's native support, use it
else if(nativeSupport) { else if(nativeSupport) {
// Request fullscreen // Request fullscreen
if(!fullscreen.isFullScreen()) { if(!fullscreen.isFullScreen(container)) {
fullscreen.requestFullScreen(player.container); fullscreen.requestFullScreen(container);
} }
// Bail from fullscreen // Bail from fullscreen
else { else {
@ -1090,14 +1090,14 @@
} }
// Check if we're actually full screen (it could fail) // Check if we're actually full screen (it could fail)
config.fullscreen.active = fullscreen.isFullScreen(); player.isFullscreen = fullscreen.isFullScreen(container);
} }
else { else {
// Otherwise, it's a simple toggle // Otherwise, it's a simple toggle
config.fullscreen.active = !config.fullscreen.active; player.isFullscreen = !player.isFullscreen;
// Bind/unbind escape key // Bind/unbind escape key
if(config.fullscreen.active) { if(player.isFullscreen) {
_on(document, "keyup", _handleEscapeFullscreen); _on(document, "keyup", _handleEscapeFullscreen);
document.body.style.overflow = "hidden"; document.body.style.overflow = "hidden";
} }
@ -1108,13 +1108,13 @@
} }
// Set class hook // Set class hook
_toggleClass(player.container, config.classes.fullscreen.active, config.fullscreen.active); _toggleClass(container, config.classes.fullscreen.active, player.isFullscreen);
} }
// Bail from faux-fullscreen // Bail from faux-fullscreen
function _handleEscapeFullscreen(event) { function _handleEscapeFullscreen(event) {
// If it's a keypress and not escape, bail // If it's a keypress and not escape, bail
if((event.which || event.charCode || event.keyCode) === 27 && config.fullscreen.active) { if((event.which || event.charCode || event.keyCode) === 27 && player.isFullscreen) {
_toggleFullscreen(); _toggleFullscreen();
} }
} }
@ -1391,6 +1391,9 @@
// Listen for events // Listen for events
function _listeners() { function _listeners() {
// IE doesn't support input event, so we fallback to change
var inputEvent = (player.browser.name == "IE" ? "change" : "input");
// Play // Play
_on(player.buttons.play, "click", function() { _on(player.buttons.play, "click", function() {
_play(); _play();
@ -1412,9 +1415,11 @@
// Fast forward // Fast forward
_on(player.buttons.forward, "click", _forward); _on(player.buttons.forward, "click", _forward);
// Get the HTML5 range input element and append audio volume adjustment on change/input // Seek
// IE10 doesn't support the "input" event so they have to wait for change _on(player.buttons.seek, inputEvent, _seek);
_on(player.volume, "change input", function() {
// Set volume
_on(player.volume, inputEvent, function() {
_setVolume(this.value); _setVolume(this.value);
}); });
@ -1440,9 +1445,6 @@
// Display duration // Display duration
_on(player.media, "loadedmetadata", _displayDuration); _on(player.media, "loadedmetadata", _displayDuration);
// Seek
_on(player.buttons.seek, "change input", _seek);
// Captions // Captions
_on(player.buttons.captions, "change", function() { _on(player.buttons.captions, "change", function() {
_toggleCaptions(this.checked); _toggleCaptions(this.checked);
@ -1578,11 +1580,13 @@
rewind: _rewind, rewind: _rewind,
forward: _forward, forward: _forward,
seek: _seek, seek: _seek,
source: _parseSource,
poster: _updatePoster,
setVolume: _setVolume, setVolume: _setVolume,
toggleMute: _toggleMute, toggleMute: _toggleMute,
toggleCaptions: _toggleCaptions, toggleCaptions: _toggleCaptions,
source: _parseSource, toggleFullscreen: _toggleFullscreen,
poster: _updatePoster, isFullscreen: function() { return player.isFullscreen || false; },
support: function(mimeType) { return _supportMime(player, mimeType); } support: function(mimeType) { return _supportMime(player, mimeType); }
} }
} }
@ -1646,9 +1650,12 @@
// Set plyr to false if setup failed // Set plyr to false if setup failed
element.plyr = (Object.keys(instance).length ? instance : false); element.plyr = (Object.keys(instance).length ? instance : false);
// Callback
config.onSetup.apply(element.plyr);
} }
// Add to return array // Add to return array even if it's already setup
players.push(element.plyr); players.push(element.plyr);
} }