See changelog (fixes #265, #253, #257)

This commit is contained in:
Sam 2016-06-07 12:34:36 +01:00
parent 4afd311ef6
commit 70646ca907
32 changed files with 202 additions and 174 deletions

View File

@ -10,14 +10,14 @@
"plyr.js": ["src/js/plyr.js"]
}
},
"docs": {
"demo": {
"less": {
"docs.css": ["docs/src/less/docs.less"]
"demo.css": ["demo/src/less/demo.less"]
},
"js": {
"docs.js": [
"docs/src/js/lib/classlist.js",
"docs/src/js/docs.js"
"demo.js": [
"demo/src/js/lib/classlist.js",
"demo/src/js/main.js"
]
}
}

View File

@ -1,18 +1,25 @@
# Changelog
# v1.6.20
# v1.7.0
- SASS cleanup (fixes #265)
- Docs tidy up to help quick start (fixes #253)
- Fix for issues with data attribute options passing (fixes #257)
- Removed the requirement for a wrapper div to setup Plyr and removed the dependency on the `plyr` classname as a JS hook. By default it will now look for `<video>`, `<audio>` and `[data-type]` elements. If you are just calling `setup()` with a `<div class="plyr">` you may want to give it a good test after upgrading. You can probably remove the wrapper div. The reason behind this is to make setup easier for newcomers and prevent the styling being used on unsupported players (because the plyr classname was used as a CSS and JS hook - which isn't ideal)
- Renamed the 'docs' folder to `demo` to avoid confusion. The readme is the docs after all.
## v1.6.20
- Fix for multiple sprites being requested (fixes #259)
# v1.6.19
## v1.6.19
- Fix for scroll direction issues on volume control (fixes #258)
# v1.6.18
## v1.6.18
- Reduced rounding of seek value from 1 decimal point to 4 (fixes #242)
# v1.6.17
## v1.6.17
- Added `disableContextMenu` option to hide the right click context menu (fixes #248 and #225)
# v1.6.16
## v1.6.16
- Always hide standard controls (fixes #225)
- Fix for Tooltips overflowing (fixes #230)

1
demo/dist/demo.js vendored Normal file
View File

@ -0,0 +1 @@
"document"in self&&("classList"in document.createElement("_")?!function(){"use strict";var e=document.createElement("_");if(e.classList.add("c1","c2"),!e.classList.contains("c2")){var t=function(e){var t=DOMTokenList.prototype[e];DOMTokenList.prototype[e]=function(e){var i,s=arguments.length;for(i=0;s>i;i++)e=arguments[i],t.call(this,e)}};t("add"),t("remove")}if(e.classList.toggle("c3",!1),e.classList.contains("c3")){var i=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(e,t){return 1 in arguments&&!this.contains(e)==!t?t:i.call(this,e)}}e=null}():!function(e){"use strict";if("Element"in e){var t="classList",i="prototype",s=e.Element[i],o=Object,n=String[i].trim||function(){return this.replace(/^\s+|\s+$/g,"")},r=Array[i].indexOf||function(e){for(var t=0,i=this.length;i>t;t++)if(t in this&&this[t]===e)return t;return-1},a=function(e,t){this.name=e,this.code=DOMException[e],this.message=t},c=function(e,t){if(""===t)throw new a("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(t))throw new a("INVALID_CHARACTER_ERR","String contains an invalid character");return r.call(e,t)},l=function(e){for(var t=n.call(e.getAttribute("class")||""),i=t?t.split(/\s+/):[],s=0,o=i.length;o>s;s++)this.push(i[s]);this._updateClassName=function(){e.setAttribute("class",this.toString())}},u=l[i]=[],d=function(){return new l(this)};if(a[i]=Error[i],u.item=function(e){return this[e]||null},u.contains=function(e){return e+="",-1!==c(this,e)},u.add=function(){var e,t=arguments,i=0,s=t.length,o=!1;do e=t[i]+"",-1===c(this,e)&&(this.push(e),o=!0);while(++i<s);o&&this._updateClassName()},u.remove=function(){var e,t,i=arguments,s=0,o=i.length,n=!1;do for(e=i[s]+"",t=c(this,e);-1!==t;)this.splice(t,1),n=!0,t=c(this,e);while(++s<o);n&&this._updateClassName()},u.toggle=function(e,t){e+="";var i=this.contains(e),s=i?t!==!0&&"remove":t!==!1&&"add";return s&&this[s](e),t===!0||t===!1?t:!i},u.toString=function(){return this.join(" ")},o.defineProperty){var p={get:d,enumerable:!0,configurable:!0};try{o.defineProperty(s,t,p)}catch(h){-2146823252===h.number&&(p.enumerable=!1,o.defineProperty(s,t,p))}}else o[i].__defineGetter__&&s.__defineGetter__(t,d)}}(self)),function(){function e(e,t,i){if(e)if(e.classList)e.classList[i?"add":"remove"](t);else{var s=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=s+(i?" "+t:"")}}function t(t,i){if(t in n&&(i||t!=r)&&(r.length||t!=n.video)){switch(t){case n.video:s.source({type:"video",title:"View From A Blue Moon",sources:[{src:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.mp4",type:"video/mp4"},{src:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.webm",type:"video/webm"}],poster:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.en.vtt","default":!0}]});break;case n.audio:s.source({type:"audio",title:"Kishi Bashi &ndash; &ldquo;It All Began With A Burst&rdquo;",sources:[{src:"https://cdn.selz.com/plyr/1.5/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3",type:"audio/mp3"},{src:"https://cdn.selz.com/plyr/1.5/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg",type:"audio/ogg"}]});break;case n.youtube:s.source({type:"video",title:"View From A Blue Moon",sources:[{src:"bTqVqk7FSmY",type:"youtube"}]});break;case n.vimeo:s.source({type:"video",title:"View From A Blue Moon",sources:[{src:"143418951",type:"vimeo"}]})}r=t;for(var a=o.length-1;a>=0;a--)e(o[a].parentElement,"active",!1);e(document.querySelector('[data-source="'+t+'"]').parentElement,"active",!0)}}var i=plyr.setup({debug:!0,title:"Video demo",iconUrl:"../dist/plyr.svg",tooltips:{controls:!0},captions:{defaultActive:!0}});plyr.loadSprite("dist/demo.svg");for(var s=i[0],o=document.querySelectorAll("[data-source]"),n={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},r=window.location.hash.replace("#",""),a=window.history&&window.history.pushState,c=o.length-1;c>=0;c--)o[c].addEventListener("click",function(){var e=this.getAttribute("data-source");t(e),a&&history.pushState({type:e},"","#"+e)});if(window.addEventListener("popstate",function(e){e.state&&"type"in e.state&&t(e.state.type)}),a){var l=!r.length;l&&(r=n.video),r in n&&history.replaceState({type:r},"",l?"":"#"+r),r!==n.video&&t(r,!0)}}(),document.domain.indexOf("plyr.io")>-1&&(!function(e,t,i,s,o,n,r){e.GoogleAnalyticsObject=o,e[o]=e[o]||function(){(e[o].q=e[o].q||[]).push(arguments)},e[o].l=1*new Date,n=t.createElement(i),r=t.getElementsByTagName(i)[0],n.async=1,n.src=s,r.parentNode.insertBefore(n,r)}(window,document,"script","//www.google-analytics.com/analytics.js","ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -11,7 +11,7 @@
<link rel="stylesheet" href="../dist/plyr.css">
<!-- Docs styles -->
<link rel="stylesheet" href="dist/docs.css">
<link rel="stylesheet" href="dist/demo.css">
</head>
<body>
<header>
@ -51,7 +51,6 @@
</ul>
</nav>
<section>
<div class="js-media-player">
<video poster="https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.jpg" controls crossorigin>
<!-- Video files -->
<source src="https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.mp4" type="video/mp4">
@ -61,9 +60,8 @@
<track kind="captions" label="English" srclang="en" src="https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.en.vtt" default>
<!-- Fallback for browsers that don't support the <video> element -->
<a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
<a href="https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.mp4" download>Download</a>
</video>
</div>
<ul>
<li class="plyr__cite plyr__cite--video"><small><a href="http://viewfromabluemoon.com/" target="_blank">View From A Blue Moon</a> &copy; Brainfarm</small></li>
@ -78,7 +76,7 @@
<script src="../dist/plyr.js"></script>
<!-- Docs script -->
<script src="dist/docs.js"></script>
<script src="dist/demo.js"></script>
<!-- Rangetouch to fix <input type="range"> on touch devices (see https://rangetouch.com) -->
<script src="https://cdn.rangetouch.com/0.0.9/rangetouch.js"></script>

View File

@ -1,11 +1,16 @@
// ==========================================================================
// Docs example
// Plyr.io demo
// This code is purely for the plyr.io website
// Please see readme.md in the root or github.com/selz/plyr
// ==========================================================================
/*global plyr*/
// General functions
;(function() {
// Setup the player
plyr.setup('.js-media-player', {
var instances = plyr.setup({
debug: true,
title: 'Video demo',
iconUrl: '../dist/plyr.svg',
@ -16,10 +21,12 @@ plyr.setup('.js-media-player', {
defaultActive: true
}
});
plyr.loadSprite('dist/docs.svg');
plyr.loadSprite('dist/demo.svg');
// General functions
(function() {
// Plyr returns an array regardless
var player = instances[0];
// Setup type toggle
var buttons = document.querySelectorAll('[data-source]'),
types = {
video: 'video',
@ -90,9 +97,6 @@ plyr.loadSprite('dist/docs.svg');
return;
}
// Get plyr instance
var player = document.querySelector('.js-media-player').plyr;
switch(type) {
case types.video:
player.source({

View File

@ -1,5 +1,5 @@
// ==========================================================================
// HTML5 Video Player Demo Page
// Plyr.io Demo Page
// ==========================================================================
// CSS Reset

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 981 B

View File

Before

Width:  |  Height:  |  Size: 779 B

After

Width:  |  Height:  |  Size: 779 B

View File

Before

Width:  |  Height:  |  Size: 739 B

After

Width:  |  Height:  |  Size: 739 B

4
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

1
docs/dist/docs.js vendored
View File

@ -1 +0,0 @@
"document"in self&&("classList"in document.createElement("_")?!function(){"use strict";var e=document.createElement("_");if(e.classList.add("c1","c2"),!e.classList.contains("c2")){var t=function(e){var t=DOMTokenList.prototype[e];DOMTokenList.prototype[e]=function(e){var i,s=arguments.length;for(i=0;s>i;i++)e=arguments[i],t.call(this,e)}};t("add"),t("remove")}if(e.classList.toggle("c3",!1),e.classList.contains("c3")){var i=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(e,t){return 1 in arguments&&!this.contains(e)==!t?t:i.call(this,e)}}e=null}():!function(e){"use strict";if("Element"in e){var t="classList",i="prototype",s=e.Element[i],o=Object,n=String[i].trim||function(){return this.replace(/^\s+|\s+$/g,"")},r=Array[i].indexOf||function(e){for(var t=0,i=this.length;i>t;t++)if(t in this&&this[t]===e)return t;return-1},a=function(e,t){this.name=e,this.code=DOMException[e],this.message=t},c=function(e,t){if(""===t)throw new a("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(t))throw new a("INVALID_CHARACTER_ERR","String contains an invalid character");return r.call(e,t)},l=function(e){for(var t=n.call(e.getAttribute("class")||""),i=t?t.split(/\s+/):[],s=0,o=i.length;o>s;s++)this.push(i[s]);this._updateClassName=function(){e.setAttribute("class",this.toString())}},u=l[i]=[],d=function(){return new l(this)};if(a[i]=Error[i],u.item=function(e){return this[e]||null},u.contains=function(e){return e+="",-1!==c(this,e)},u.add=function(){var e,t=arguments,i=0,s=t.length,o=!1;do e=t[i]+"",-1===c(this,e)&&(this.push(e),o=!0);while(++i<s);o&&this._updateClassName()},u.remove=function(){var e,t,i=arguments,s=0,o=i.length,n=!1;do for(e=i[s]+"",t=c(this,e);-1!==t;)this.splice(t,1),n=!0,t=c(this,e);while(++s<o);n&&this._updateClassName()},u.toggle=function(e,t){e+="";var i=this.contains(e),s=i?t!==!0&&"remove":t!==!1&&"add";return s&&this[s](e),t===!0||t===!1?t:!i},u.toString=function(){return this.join(" ")},o.defineProperty){var p={get:d,enumerable:!0,configurable:!0};try{o.defineProperty(s,t,p)}catch(h){-2146823252===h.number&&(p.enumerable=!1,o.defineProperty(s,t,p))}}else o[i].__defineGetter__&&s.__defineGetter__(t,d)}}(self)),plyr.setup(".js-media-player",{debug:!0,title:"Video demo",iconUrl:"../dist/plyr.svg",tooltips:{controls:!0},captions:{defaultActive:!0}}),plyr.loadSprite("dist/docs.svg"),function(){function e(e,t,i){if(e)if(e.classList)e.classList[i?"add":"remove"](t);else{var s=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=s+(i?" "+t:"")}}function t(t,n){if(t in s&&(n||t!=o)&&(o.length||t!=s.video)){var r=document.querySelector(".js-media-player").plyr;switch(t){case s.video:r.source({type:"video",title:"View From A Blue Moon",sources:[{src:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.mp4",type:"video/mp4"},{src:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.webm",type:"video/webm"}],poster:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"https://cdn.selz.com/plyr/1.5/View_From_A_Blue_Moon_Trailer-HD.en.vtt","default":!0}]});break;case s.audio:r.source({type:"audio",title:"Kishi Bashi &ndash; &ldquo;It All Began With A Burst&rdquo;",sources:[{src:"https://cdn.selz.com/plyr/1.5/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3",type:"audio/mp3"},{src:"https://cdn.selz.com/plyr/1.5/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg",type:"audio/ogg"}]});break;case s.youtube:r.source({type:"video",title:"View From A Blue Moon",sources:[{src:"bTqVqk7FSmY",type:"youtube"}]});break;case s.vimeo:r.source({type:"video",title:"View From A Blue Moon",sources:[{src:"143418951",type:"vimeo"}]})}o=t;for(var a=i.length-1;a>=0;a--)e(i[a].parentElement,"active",!1);e(document.querySelector('[data-source="'+t+'"]').parentElement,"active",!0)}}for(var i=document.querySelectorAll("[data-source]"),s={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},o=window.location.hash.replace("#",""),n=window.history&&window.history.pushState,r=i.length-1;r>=0;r--)i[r].addEventListener("click",function(){var e=this.getAttribute("data-source");t(e),n&&history.pushState({type:e},"","#"+e)});if(window.addEventListener("popstate",function(e){e.state&&"type"in e.state&&t(e.state.type)}),n){var a=!o.length;a&&(o=s.video),o in s&&history.replaceState({type:o},"",a?"":"#"+o),o!==s.video&&t(o,!0)}}(),document.domain.indexOf("plyr.io")>-1&&(!function(e,t,i,s,o,n,r){e.GoogleAnalyticsObject=o,e[o]=e[o]||function(){(e[o].q=e[o].q||[]).push(arguments)},e[o].l=1*new Date,n=t.createElement(i),r=t.getElementsByTagName(i)[0],n.async=1,n.src=s,r.parentNode.insertBefore(n,r)}(window,document,"script","//www.google-analytics.com/analytics.js","ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));

View File

@ -37,19 +37,19 @@ paths = {
// Output paths
output: path.join(root, "dist/")
},
docs: {
demo: {
// Source paths
src: {
less: path.join(root, "docs/src/less/**/*"),
js: path.join(root, "docs/src/js/**/*"),
sprite: path.join(root, "docs/src/sprite/**/*")
less: path.join(root, "demo/src/less/**/*"),
js: path.join(root, "demo/src/js/**/*"),
sprite: path.join(root, "demo/src/sprite/**/*")
},
// Output paths
output: path.join(root, "docs/dist/"),
// Docs
root: path.join(root, "docs/")
output: path.join(root, "demo/dist/"),
// Demo
root: path.join(root, "demo/")
},
upload: [path.join(root, "dist/**"), path.join(root, "docs/dist/**")]
upload: [path.join(root, "dist/**"), path.join(root, "demo/dist/**")]
},
// Task arrays
@ -178,10 +178,10 @@ build.less(bundles.plyr.less, "plyr");
build.scss(bundles.plyr.scss, "plyr");
build.sprite("plyr");
// Docs files
build.less(bundles.docs.less, "docs");
build.js(bundles.docs.js, "docs");
build.sprite("docs");
// Demo files
build.less(bundles.demo.less, "demo");
build.js(bundles.demo.js, "demo");
build.sprite("demo");
// Build all JS
gulp.task("js", function(){
@ -200,10 +200,10 @@ gulp.task("watch", function () {
gulp.watch(paths.plyr.src.less, tasks.less);
gulp.watch(paths.plyr.src.sprite, tasks.sprite);
// Docs
gulp.watch(paths.docs.src.js, tasks.js);
gulp.watch(paths.docs.src.less, tasks.less);
gulp.watch(paths.docs.src.sprite, tasks.sprite);
// Demo
gulp.watch(paths.demo.src.js, tasks.js);
gulp.watch(paths.demo.src.less, tasks.less);
gulp.watch(paths.demo.src.sprite, tasks.sprite);
});
// Default gulp task
@ -211,7 +211,7 @@ gulp.task("default", function(){
run(tasks.js, tasks.less, tasks.sprite, "watch");
});
// Publish a version to CDN and docs
// Publish a version to CDN and demo
// --------------------------------------------
// Some options
@ -225,7 +225,7 @@ options = {
"Vary": "Accept-Encoding"
}
},
docs: {
demo: {
headers: {
"Cache-Control": "no-cache, no-store, must-revalidate, max-age=0",
"Vary": "Accept-Encoding"
@ -268,9 +268,9 @@ gulp.task("cdn", function () {
.pipe(s3(aws.cdn, options.cdn));
});
// Publish to Docs bucket
gulp.task("docs", function () {
console.log("Uploading " + version + " docs to " + aws.docs.bucket + "...");
// Publish to demo bucket
gulp.task("demo", function () {
console.log("Uploading " + version + " demo to " + aws.demo.bucket + "...");
// Replace versioned files in readme.md
gulp.src([root + "/readme.md"])
@ -283,19 +283,19 @@ gulp.task("docs", function () {
.pipe(replace(cdnpath, aws.cdn.bucket + "/" + version))
.pipe(gulp.dest(path.join(root, "src/js/")));
// Replace local file paths with remote paths in docs HTML
// Replace local file paths with remote paths in demo HTML
// e.g. "../dist/plyr.js" to "https://cdn.plyr.io/x.x.x/plyr.js"
gulp.src([paths.docs.root + "*.html"])
gulp.src([paths.demo.root + "*.html"])
.pipe(replace(localPath, versionPath))
.pipe(s3(aws.docs, options.docs));
.pipe(s3(aws.demo, options.demo));
// Upload error.html to cdn (as well as docs site)
return gulp.src([paths.docs.root + "error.html"])
// Upload error.html to cdn (as well as demo site)
return gulp.src([paths.demo.root + "error.html"])
.pipe(replace(localPath, versionPath))
.pipe(s3(aws.cdn, options.docs));
.pipe(s3(aws.cdn, options.demo));
});
// Open the docs site to check it's sweet
// Open the demo site to check it's sweet
gulp.task("symlinks", function () {
console.log("Updating symlinks...");
@ -318,20 +318,20 @@ gulp.task("symlinks", function () {
}));
});
// Open the docs site to check it's sweet
// Open the demo site to check it's sweet
gulp.task("open", function () {
console.log("Opening " + aws.docs.bucket + "...");
console.log("Opening " + aws.demo.bucket + "...");
// A file must be specified or gulp will skip the task
// Doesn't matter which file since we set the URL above
// Weird, I know...
return gulp.src([paths.docs.root + "index.html"])
return gulp.src([paths.demo.root + "index.html"])
.pipe(open("", {
url: "http://" + aws.docs.bucket
url: "http://" + aws.demo.bucket
}));
});
// Do everything
gulp.task("publish", function () {
run(tasks.js, tasks.less, tasks.sprite, "cdn", "docs", "symlinks");
run(tasks.js, tasks.less, tasks.sprite, "cdn", "demo", "symlinks");
});

View File

@ -1,6 +1,6 @@
{
"name": "plyr",
"version": "1.6.20",
"version": "1.7.0",
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
"homepage": "http://plyr.io",
"main": "src/js/plyr.js",
@ -38,7 +38,7 @@
"url": "https://github.com/selz/plyr/issues"
},
"directories": {
"doc": "docs"
"doc": "readme.md"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"

169
readme.md
View File

@ -38,22 +38,15 @@ Check out the [changelog](changelog.md) to see what's new with Plyr.
If you have any cool ideas or features, please let me know by [creating an issue](https://github.com/Selz/plyr/issues/new) or, of course, forking and sending a pull request.
## Implementation
Check `docs/index.html` and `docs/src/js/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.6.20/plyr.js` to `https://cdn.plyr.io/1.6.20/plyr.js`
## Using package managers
### npm
Using `npm`, you can grab Plyr:
```
npm install plyr
```
[https://www.npmjs.com/package/plyr](https://www.npmjs.com/package/plyr)
### Bower
If bower is your thing, you can grab Plyr using:
```
bower install plyr
```
@ -68,24 +61,81 @@ 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
If you want to use our CDN, you can use the following:
## Quick setup
Here's a quick run through on getting up and running.
### HTML
Plyr extends upon the standard HTML5 markup so that's all you need for those types.
#### HTML5 Video
```html
<link rel="stylesheet" href="https://cdn.plyr.io/1.6.20/plyr.css">
<script src="https://cdn.plyr.io/1.6.20/plyr.js"></script>
<video poster="/path/to/poster.jpg" controls>
<source src="/path/to/video.mp4" type="video/mp4">
<source src="/path/to/video.webm" type="video/webm">
<!-- Captions are optional -->
<track kind="captions" label="English captions" src="/path/to/captions.vtt" srclang="en" default>
</video>
```
The SVG sprite/defs file can be found here: `https://cdn.plyr.io/1.6.20/plyr.svg`.
### CSS & Styling
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.scss` file included in `/src` in your build to save a request.
#### HTML5 Audio
```html
<link rel="stylesheet" href="dist/plyr.css">
<audio controls>
<source src="/path/to/audio.mp3" type="audio/mp3">
<source src="/path/to/audio.ogg" type="audio/ogg">
</audio>
```
The default setup uses the BEM methodology with `plyr` as the block, e.g. `.plyr__controls`. You can change the class hooks in the options. Check out the source for more on this.
For YouTube and Vimeo, Plyr uses the standard YouTube API markup (an empty `<div>`):
#### YouTube embed
```html
<div data-type="youtube" data-video-id="bTqVqk7FSmY"></div>
```
#### Vimeo embed
```html
<div data-type="vimeo" data-video-id="143418951"></div>
```
### JavaScript
Include the `plyr.js` script before the closing `</body>` tag and then call `plyr.setup()`. More info on `setup()` can be found under [#initialising](initialising).
```html
<script src="path/to/plyr.js"></script>
<script>plyr.setup();</script>
```
If you want to use our CDN for the JavaScript, you can use the following:
```html
<script src="https://cdn.plyr.io/1.7.0/plyr.js"></script>
```
### CSS
Include the `plyr.css` stylsheet into your `<head>`
```html
<link rel="stylesheet" href="path/to/plyr.css">
```
If you want to use our CDN for the default CSS, you can use the following:
```html
<link rel="stylesheet" href="https://cdn.plyr.io/1.7.0/plyr.css">
```
### SVG Sprite
The SVG sprite is loaded automatically from our CDN. To change this, see the [#options](Options) below. For reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/1.7.0/plyr.svg`.
## Advanced
### LESS & SASS/SCSS
You can use `plyr.less` or `plyr.scss` file included in `/src` as part of your build and change variables to suit your design. The HTML markup uses the BEM methodology with `plyr` as the block, e.g. `.plyr__controls`. You can change the class hooks in the options to match any custom CSS you write. Check out the JavaScript source for more on this.
### SVG
The icons used in the Plyr controls are loaded in an SVG sprite. The sprite is automatically loaded from our CDN by default. If you already have an icon build system in place, you can include the source plyr icons (see `/src/sprite` for source icons).
@ -101,91 +151,36 @@ More info on SVG sprites here:
and the AJAX technique here:
[http://css-tricks.com/ajaxing-svg-sprite/](http://css-tricks.com/ajaxing-svg-sprite/)
### HTML
The only extra markup that's needed to use plyr is a `<div>` wrapper. Replace the source, poster and captions with urls for your media.
```html
<div class="plyr">
<video poster="/path/to/poster.jpg" controls>
<!-- Video files -->
<source src="/path/to/video.mp4" type="video/mp4">
<source src="/path/to/video.webm" type="video/webm">
<!-- Text track file -->
<track kind="captions" label="English captions" src="/path/to/captions.vtt" srclang="en" default>
<!-- Fallback for browsers that don't support the <video> element -->
<a href="/path/to/movie.mp4">Download</a>
</video>
</div>
```
And the same for `<audio>`
```html
<div class="plyr">
<audio controls>
<!-- Audio files -->
<source src="/path/to/audio.mp3" type="audio/mp3">
<source src="/path/to/audio.ogg" type="audio/ogg">
<!-- Fallback for browsers that don't support the <audio> element -->
<a href="/path/to/audio.mp3">Download</a>
</audio>
</div>
```
For YouTube and Vimeo, Plyr uses the standard YouTube API markup (an empty `<div>`):
```html
<div class="plyr">
<div data-video-id="bTqVqk7FSmY" data-type="youtube"></div>
</div>
```
```html
<div class="plyr">
<div data-video-id="143418951" data-type="vimeo"></div>
</div>
```
#### Cross Origin (CORS)
You'll notice the `crossorigin` attribute on the example `<video>` and `<audio>` elements. This is because the media is loaded from another domain. If your media is hosted on another domain, you may need to add this attribute.
More info on CORS here:
### Cross Origin (CORS)
You'll notice the `crossorigin` attribute on the example `<video>` elements. This is because the TextTrack captions are loaded from another domain. If your TextTrack captions are also hosted on another domain, you will need to add this attribute and make sure your host has the correct headers setup. For more info on CORS checkout the MDN docs:
[https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)
### Captions
WebVTT captions are supported. To add a caption track, check the HTML example above and look for the `<track>` element.
Be sure to [validate your caption files](https://quuz.org/webvtt/)
WebVTT captions are supported. To add a caption track, check the HTML example above and look for the `<track>` element. Be sure to [validate your caption files](https://quuz.org/webvtt/).
### JavaScript
#### Quick setup
#### Initialising
Here's an example of a default setup:
```html
<script src="https://cdn.plyr.io/1.6.20/plyr.js"></script>
<script>plyr.setup();</script>
```
This will look for all elements with the specified container classname (default is `plyr`) and setup plyr on each element found. You can specify other options, including a different selector hook below. The container classname will be added to the specified element(s) if it is not already present (for the CSS).
By default, Plyr looks for all `<video>`, `<audio>` and `[data-type]` elements and initialises on any found. You can specify other options, including a different selector hook below. The container classname will be added to the specified element(s) if it is not already present (for the CSS).
You can initialize the player a few other ways:
Passing a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList):
```javascript
plyr.setup(document.querySelectorAll('.js-plyr'), options);
plyr.setup(document.querySelectorAll('.js-player'), options);
```
Passing a [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement):
```javascript
plyr.setup(document.querySelector('.js-plyr'), options);
plyr.setup(document.querySelector('.js-player'), options);
```
Passing a [string selector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll):
```javascript
plyr.setup('.js-plyr', options);
plyr.setup('.js-player', options);
```
This can be the target `<video>`, `<audio>` or `[data-type]` elements or a container element.
Passing just the options object:
```javascript
@ -200,7 +195,7 @@ Some touch browsers (particularly Mobile Safari on iOS) seem to have issues with
Options must be passed as an object to the `setup()` method as above or as JSON in `data-plyr` attribute on each of your target elements:
```html
<div class="plyr" data-plyr='{ title: "testing" }'>
<video data-plyr='{ title: "testing" }'></video>
```
Note the single quotes encapsulating the JSON and double quotes on the object keys.
@ -404,16 +399,16 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke
#### Fetching the plyr instance
A `plyr` object is added to any element that Plyr is initialized on. You can then control the player by accessing methods in the `plyr` object.
There are two ways to access the instance, firstly you re-query the element container you used for setup (e.g. `.js-plyr`) like so:
There are two ways to access the instance, firstly you re-query the element container you used for setup (e.g. `.js-player`) like so:
```javascript
var player = document.querySelector('.js-plyr').plyr;
var player = document.querySelector('.js-player').plyr;
```
Or you can use the returned object from your call to the setup method:
The other method is using the return value from the call to `setup()`. An array of instances is returned so you need to use an index:
```javascript
var player = plyr.setup('.js-plyr')[0];
var player = plyr.setup('.js-player')[0];
```
This will return an array of plyr instances setup, so you need to specify the index of the instance you want. This is less useful if you are setting up multiple instances. You can listen for the `setup` [event](#events) documented below which will return each instance one by one, as they are setup (in the `plyr` key of the event object).

View File

@ -1,6 +1,6 @@
// ==========================================================================
// Plyr
// plyr.js v1.6.20
// plyr.js v1.7.0
// https://github.com/selz/plyr
// License: The MIT License (MIT)
// ==========================================================================
@ -44,7 +44,7 @@
displayDuration: true,
loadSprite: true,
iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/1.6.20/plyr.svg',
iconUrl: 'https://cdn.plyr.io/1.7.0/plyr.svg',
clickToPlay: true,
hideControls: true,
showPosterOnEnd: false,
@ -54,6 +54,8 @@
seek: true
},
selectors: {
html5: 'video, audio',
embed: '[data-type]',
container: '.plyr',
controls: {
container: null,
@ -323,6 +325,8 @@
else {
parent.appendChild(child);
}
return child;
}
}
@ -404,6 +408,17 @@
return false;
}
// Element matches selector
function _matches(element, selector) {
var p = Element.prototype;
var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
};
return f.call(element, selector);
}
// Bind event
function _on(element, events, callback, useCapture) {
if (element) {
@ -3045,7 +3060,7 @@
// Get the div placeholder for YouTube and Vimeo
if (!plyr.media) {
plyr.media = plyr.container.querySelectorAll('div')[0];
plyr.media = plyr.container.querySelectorAll('[data-type]')[0];
}
// Bail if nothing to setup
@ -3285,7 +3300,8 @@
// Setup function
function setup(elements, options) {
// Get the players
var instances = [];
var instances = [],
selector = [defaults.selectors.html5, defaults.selectors.embed].join(',');
// Select the elements
// Assume elements is a NodeList by default
@ -3304,7 +3320,7 @@
}
// Use default selector
elements = document.querySelectorAll(defaults.selectors.container);
elements = document.querySelectorAll(selector);
}
// Bail if disabled or no basic support
@ -3318,10 +3334,19 @@
// Get the current element
var element = elements[i];
// Custom settings passed as data attribute
var settings = element.getAttribute("data-plyr");
// Wrap each media element if needed
if (_matches(element, selector)) {
// Wrap in a <div>
element = _wrap(element, document.createElement('div'));
}
// Setup a player instance and add to the element
if (typeof element.plyr === 'undefined') {
// Create instance-specific config
var config = _extend(defaults, options, JSON.parse(element.getAttribute("data-plyr")));
var config = _extend({}, defaults, options, JSON.parse(settings));
// Bail if not enabled
if (!config.enabled) {

View File

@ -487,7 +487,6 @@
// First tooltip
.plyr__controls button:first-child .plyr__tooltip {
$tooltip-arrow-offset: ;
left: 0;
transform: translate(0, 10px) scale(.8);
transform-origin: 0 100%;