Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
268223ac52 | |||
b81b8c1d31 | |||
5b2a016241 | |||
a665121b52 | |||
02d312f2d2 | |||
c23c150fe9 | |||
2e5bdb338e | |||
c51ef05067 | |||
dbe152a4c1 | |||
3f42e53d95 | |||
54b0dc5273 | |||
d6b67c3388 | |||
a277224ef4 |
10
changelog.md
10
changelog.md
@ -1,7 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## v1.5.2
|
||||
- `handlers` option renamed to `listeners`
|
||||
- Added event listeners for all types to the plyr container (playback, fullscreen, captions etc - see docs)
|
||||
- Removed onSetup config option (use the 'setup' event instead, plyr element is event.plyr)
|
||||
- Style bug fixes
|
||||
- Vimeo seek bug fix (requires whole seconds when seeking)
|
||||
- Fix for fullscreen player (using class hook, not browser fullscreen)
|
||||
|
||||
## v1.5.1
|
||||
- Fix for event listeners being duplicated on source change
|
||||
- Fix for event listeners being duplicated on source change
|
||||
|
||||
# v1.5.0
|
||||
- Vimeo support (fixes #8)
|
||||
|
2
dist/plyr.css
vendored
2
dist/plyr.css
vendored
File diff suppressed because one or more lines are too long
3
dist/plyr.js
vendored
3
dist/plyr.js
vendored
File diff suppressed because one or more lines are too long
2
docs/dist/docs.js
vendored
2
docs/dist/docs.js
vendored
@ -1 +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 n,s=arguments.length;for(n=0;s>n;n++)e=arguments[n],t.call(this,e)}};t("add"),t("remove")}if(e.classList.toggle("c3",!1),e.classList.contains("c3")){var n=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(e,t){return 1 in arguments&&!this.contains(e)==!t?t:n.call(this,e)}}e=null}():!function(e){"use strict";if("Element"in e){var t="classList",n="prototype",s=e.Element[n],i=Object,o=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},r=Array[n].indexOf||function(e){for(var t=0,n=this.length;n>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=o.call(e.getAttribute("class")||""),n=t?t.split(/\s+/):[],s=0,i=n.length;i>s;s++)this.push(n[s]);this._updateClassName=function(){e.setAttribute("class",this.toString())}},u=l[n]=[],p=function(){return new l(this)};if(a[n]=Error[n],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,n=0,s=t.length,i=!1;do e=t[n]+"",-1===c(this,e)&&(this.push(e),i=!0);while(++n<s);i&&this._updateClassName()},u.remove=function(){var e,t,n=arguments,s=0,i=n.length,o=!1;do for(e=n[s]+"",t=c(this,e);-1!==t;)this.splice(t,1),o=!0,t=c(this,e);while(++s<i);o&&this._updateClassName()},u.toggle=function(e,t){e+="";var n=this.contains(e),s=n?t!==!0&&"remove":t!==!1&&"add";return s&&this[s](e),t===!0||t===!1?t:!n},u.toString=function(){return this.join(" ")},i.defineProperty){var d={get:p,enumerable:!0,configurable:!0};try{i.defineProperty(s,t,d)}catch(h){-2146823252===h.number&&(d.enumerable=!1,i.defineProperty(s,t,d))}}else i[n].__defineGetter__&&s.__defineGetter__(t,p)}}(self)),plyr.setup(".js-media-player",{debug:!0,title:"Video demo",tooltips:!0,captions:{defaultActive:!0},onSetup:function(){console.log("✓ Setup done")}}),shr.setup({count:{classname:"btn__count"}}),function(){function e(e,t,n){if(e)if(e.classList)e.classList[n?"add":"remove"](t);else{var s=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=s+(n?" "+t:"")}}function t(){var t=this,s=t.getAttribute("data-source"),i=document.querySelector(".js-media-player").plyr;switch(s){case"video":i.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.0/example_captions_en.vtt","default":!0}]});break;case"audio":i.source({type:"audio",title:"Kishi Bashi – “It All Began With A Burst”",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"youtube":i.source({type:"video",title:"View From A Blue Moon",sources:[{src:"bTqVqk7FSmY",type:"youtube"}]});break;case"vimeo":i.source({type:"video",title:"View From A Blue Moon",sources:[{src:"143418951",type:"vimeo"}]})}window.history&&window.history.pushState&&history.pushState({type:s},"","#"+s);for(var o=n.length-1;o>=0;o--)e(n[o].parentElement,"active",!1);e((event.target||event.srcElement).parentElement,"active",!0)}for(var n=document.querySelectorAll("[data-source]"),s=n.length-1;s>=0;s--)n[s].addEventListener("click",t);window.addEventListener("popstate",function(e){console.log(e)})}(),document.domain.indexOf("plyr.io")>-1&&(!function(e,t,n,s,i,o,r){e.GoogleAnalyticsObject=i,e[i]=e[i]||function(){(e[i].q=e[i].q||[]).push(arguments)},e[i].l=1*new Date,o=t.createElement(n),r=t.getElementsByTagName(n)[0],o.async=1,o.src=s,r.parentNode.insertBefore(o,r)}(window,document,"script","//www.google-analytics.com/analytics.js","ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));
|
||||
"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,n=arguments.length;for(i=0;n>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",n=e.Element[i],s=Object,o=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=o.call(e.getAttribute("class")||""),i=t?t.split(/\s+/):[],n=0,s=i.length;s>n;n++)this.push(i[n]);this._updateClassName=function(){e.setAttribute("class",this.toString())}},u=l[i]=[],p=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,n=t.length,s=!1;do e=t[i]+"",-1===c(this,e)&&(this.push(e),s=!0);while(++i<n);s&&this._updateClassName()},u.remove=function(){var e,t,i=arguments,n=0,s=i.length,o=!1;do for(e=i[n]+"",t=c(this,e);-1!==t;)this.splice(t,1),o=!0,t=c(this,e);while(++n<s);o&&this._updateClassName()},u.toggle=function(e,t){e+="";var i=this.contains(e),n=i?t!==!0&&"remove":t!==!1&&"add";return n&&this[n](e),t===!0||t===!1?t:!i},u.toString=function(){return this.join(" ")},s.defineProperty){var d={get:p,enumerable:!0,configurable:!0};try{s.defineProperty(n,t,d)}catch(h){-2146823252===h.number&&(d.enumerable=!1,s.defineProperty(n,t,d))}}else s[i].__defineGetter__&&n.__defineGetter__(t,p)}}(self)),plyr.setup(".js-media-player",{debug:!0,title:"Video demo",tooltips:!0,captions:{defaultActive:!0},onSetup:function(){console.log("✓ Setup done")}}),shr.setup({count:{classname:"btn__count"}}),function(){function e(e,t,i){if(e)if(e.classList)e.classList[i?"add":"remove"](t);else{var n=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=n+(i?" "+t:"")}}function t(t){if(t in n){var o=document.querySelector(".js-media-player").plyr;switch(t){case n.video:o.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.0/example_captions_en.vtt","default":!0}]});break;case n.audio:o.source({type:"audio",title:"Kishi Bashi – “It All Began With A Burst”",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:o.source({type:"video",title:"View From A Blue Moon",sources:[{src:"bTqVqk7FSmY",type:"youtube"}]});break;case n.vimeo:o.source({type:"video",title:"View From A Blue Moon",sources:[{src:"143418951",type:"vimeo"}]})}s=t;for(var r=i.length-1;r>=0;r--)e(i[r].parentElement,"active",!1);e(document.querySelector('[data-source="'+t+'"]').parentElement,"active",!0)}}for(var i=document.querySelectorAll("[data-source]"),n={video:"video",audio:"audio",youtube:"youtube",vimeo:"vimeo"},s=window.location.hash.replace("#",""),o=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),o&&history.pushState({type:e},"","#"+e)});if(window.addEventListener("popstate",function(e){e.state&&"type"in e.state&&t(e.state.type)}),o){var a=!s.length;a&&(s=n.video),s in n&&history.replaceState({type:s},"",a?"":"#"+s),a||t(s)}}(),document.domain.indexOf("plyr.io")>-1&&(!function(e,t,i,n,s,o,r){e.GoogleAnalyticsObject=s,e[s]=e[s]||function(){(e[s].q=e[s].q||[]).push(arguments)},e[s].l=1*new Date,o=t.createElement(i),r=t.getElementsByTagName(i)[0],o.async=1,o.src=n,r.parentNode.insertBefore(o,r)}(window,document,"script","//www.google-analytics.com/analytics.js","ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));
|
@ -26,17 +26,51 @@ shr.setup({
|
||||
|
||||
// General functions
|
||||
(function() {
|
||||
var buttons = document.querySelectorAll('[data-source]');
|
||||
var buttons = document.querySelectorAll('[data-source]'),
|
||||
types = {
|
||||
video: 'video',
|
||||
audio: 'audio',
|
||||
youtube: 'youtube',
|
||||
vimeo: 'vimeo'
|
||||
},
|
||||
currentType = window.location.hash.replace('#', ''),
|
||||
historySupport = (window.history && window.history.pushState);
|
||||
|
||||
// Bind to each button
|
||||
for (var i = buttons.length - 1; i >= 0; i--) {
|
||||
buttons[i].addEventListener('click', newSource);
|
||||
buttons[i].addEventListener('click', function() {
|
||||
var type = this.getAttribute('data-source');
|
||||
|
||||
newSource(type);
|
||||
|
||||
if (historySupport) {
|
||||
history.pushState({ 'type': type }, '', '#' + type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// List for backwards/forwards
|
||||
window.addEventListener('popstate', function(event) {
|
||||
console.log(event);
|
||||
if(event.state && 'type' in event.state) {
|
||||
newSource(event.state.type);
|
||||
}
|
||||
});
|
||||
|
||||
// On load
|
||||
if(historySupport) {
|
||||
var video = !currentType.length;
|
||||
if(video) {
|
||||
currentType = types.video;
|
||||
}
|
||||
if(currentType in types) {
|
||||
history.replaceState({ 'type': currentType }, '', (video ? '' : '#' + currentType));
|
||||
}
|
||||
if(!video) {
|
||||
newSource(currentType);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle class on an element
|
||||
function toggleClass(element, className, state) {
|
||||
if (element) {
|
||||
if (element.classList) {
|
||||
@ -50,13 +84,15 @@ shr.setup({
|
||||
}
|
||||
|
||||
// Set a new source
|
||||
function newSource() {
|
||||
var trigger = this,
|
||||
type = trigger.getAttribute('data-source'),
|
||||
player = document.querySelector('.js-media-player').plyr;
|
||||
function newSource(type) {
|
||||
if(!(type in types)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var player = document.querySelector('.js-media-player').plyr;
|
||||
|
||||
switch(type) {
|
||||
case 'video':
|
||||
case types.video:
|
||||
player.source({
|
||||
type: 'video',
|
||||
title: 'View From A Blue Moon',
|
||||
@ -79,7 +115,7 @@ shr.setup({
|
||||
});
|
||||
break;
|
||||
|
||||
case 'audio':
|
||||
case types.audio:
|
||||
player.source({
|
||||
type: 'audio',
|
||||
title: 'Kishi Bashi – “It All Began With A Burst”',
|
||||
@ -94,7 +130,7 @@ shr.setup({
|
||||
});
|
||||
break;
|
||||
|
||||
case 'youtube':
|
||||
case types.youtube:
|
||||
player.source({
|
||||
type: 'video',
|
||||
title: 'View From A Blue Moon',
|
||||
@ -105,7 +141,7 @@ shr.setup({
|
||||
});
|
||||
break;
|
||||
|
||||
case 'vimeo':
|
||||
case types.vimeo:
|
||||
player.source({
|
||||
type: 'video',
|
||||
title: 'View From A Blue Moon',
|
||||
@ -117,15 +153,13 @@ shr.setup({
|
||||
break;
|
||||
}
|
||||
|
||||
if (window.history && window.history.pushState) {
|
||||
history.pushState({ 'type': type }, '', '#' + type);
|
||||
}
|
||||
currentType = type;
|
||||
|
||||
for (var x = buttons.length - 1; x >= 0; x--) {
|
||||
toggleClass(buttons[x].parentElement, 'active', false);
|
||||
}
|
||||
|
||||
toggleClass((event.target || event.srcElement).parentElement, 'active', true);
|
||||
toggleClass(document.querySelector('[data-source="'+ type +'"]').parentElement, 'active', true);
|
||||
}
|
||||
})();
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "plyr",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"description": "A simple HTML5 media player using custom controls",
|
||||
"homepage": "http://plyr.io",
|
||||
"main": "gulpfile.js",
|
||||
|
188
readme.md
188
readme.md
@ -6,20 +6,20 @@ A simple, accessible and customizable HTML5, YouTube and Vimeo media player.
|
||||
[](http://plyr.io)
|
||||
|
||||
## Why?
|
||||
We wanted a lightweight, accessible and customizable media player that just supports [*modern*](#browser-support) browsers. Sure, there are many other players out there but we wanted to keep things simple, using the right elements for the job.
|
||||
We wanted a lightweight, accessible and customizable media player that supports [*modern*](#browser-support) browsers. Sure, there are many other players out there but we wanted to keep things simple, using the right elements for the job.
|
||||
|
||||
## Features
|
||||
- **Accessible** - full support for VTT captions and screen readers.
|
||||
- **Lightweight** - just 8KB minified and gzipped.
|
||||
- **[Customisable](#html)** - 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.
|
||||
- **Responsive** - as you'd expect these days.
|
||||
- **Audio & Video** - support for both formats.
|
||||
- **[Embedded Video](#embeds)** - support for YouTube and Vimeo (beta).
|
||||
- **[API](#api)** - toggle playback, volume, seeking, and more.
|
||||
- **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes.
|
||||
- **i18n support** - support for internationalization of controls.
|
||||
- **No dependencies** - written in vanilla JavaScript, no jQuery required.
|
||||
- **Accessible** - full support for VTT captions and screen readers
|
||||
- **Lightweight** - under 10KB minified and gzipped
|
||||
- **[Customisable](#html)** - 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
|
||||
- **Responsive** - as you'd expect these days
|
||||
- **HTML Video & Audio** - support for both formats
|
||||
- **[Embedded Video](#embeds)** - support for YouTube and Vimeo (beta)
|
||||
- **[API](#api)** - toggle playback, volume, seeking, and more
|
||||
- **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes
|
||||
- **i18n support** - support for internationalization of controls
|
||||
- **No dependencies** - written in "vanilla" JavaScript, no jQuery required
|
||||
|
||||
Oh and yes, it works with Bootstrap.
|
||||
|
||||
@ -39,7 +39,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.
|
||||
|
||||
**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.5.1/plyr.js` to `https://cdn.plyr.io/1.5.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.5.2/plyr.js` to `https://cdn.plyr.io/1.5.2/plyr.js`
|
||||
|
||||
### Bower
|
||||
If bower is your thang, you can grab Plyr using:
|
||||
@ -59,11 +59,11 @@ More info is on [npm](https://www.npmjs.com/package/ember-cli-plyr) and [GitHub]
|
||||
If you want to use our CDN, you can use the following:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/1.5.1/plyr.css">
|
||||
<script src="https://cdn.plyr.io/1.5.1/plyr.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/1.5.2/plyr.css">
|
||||
<script src="https://cdn.plyr.io/1.5.2/plyr.js"></script>
|
||||
```
|
||||
|
||||
You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.5.1/sprite.svg`.
|
||||
You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.5.2/sprite.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.sass` file included in `/src` in your build to save a request.
|
||||
@ -134,13 +134,19 @@ And the same for `<audio>`
|
||||
</div>
|
||||
```
|
||||
|
||||
For YouTube, Plyr uses the standard YouTube API markup (an empty `<div>`):
|
||||
For YouTube and Vimeo, Plyr uses the standard YouTube API markup (an empty `<div>`):
|
||||
|
||||
```html
|
||||
<div class="plyr">
|
||||
<div data-video-id="L1h9xxCU20g" data-type="youtube"></div>
|
||||
<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.
|
||||
@ -155,7 +161,7 @@ More info on CORS here:
|
||||
Here's an example of a default setup:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.plyr.io/1.5.1/plyr.js"></script>
|
||||
<script src="https://cdn.plyr.io/1.5.2/plyr.js"></script>
|
||||
<script>plyr.setup();</script>
|
||||
```
|
||||
|
||||
@ -299,12 +305,6 @@ Options must be passed as an object to the `setup()` method as above.
|
||||
<td>—</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>
|
||||
<td><code>onSetup</code></td>
|
||||
<td>Function</td>
|
||||
<td>—</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>
|
||||
</table>
|
||||
|
||||
@ -364,7 +364,7 @@ Or you can use the returned object from your call to the setup method:
|
||||
var player = plyr.setup('.js-plyr')[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 mutliple instances. You can also use the `onSetup` callback documented below which will return each instance one by one, as they are setup.
|
||||
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 mutliple 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).
|
||||
|
||||
Once you have your instance, you can use the API methods below on it. For example to pause it:
|
||||
|
||||
@ -599,19 +599,139 @@ Some more details on the object parameters
|
||||
</table>
|
||||
|
||||
|
||||
## Events/Callbacks
|
||||
## Events
|
||||
|
||||
The `plyr` object on the player element also contains a `media` property which is a reference to the `<audio>` or `<video>` element within the player which you can use to listen for events. Here's an example:
|
||||
You can listen for events on the element you setup Plyr on. Some events only apply to HTML5 audio and video.
|
||||
|
||||
<table class="table" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="20%">Event name</th>
|
||||
<th width="20%">HTML5 only</th>
|
||||
<th width="60%">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/canplay" title="/en-US/docs/Web/Events/canplay">canplay</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the <code>HAVE_ENOUGH_DATA</code> <code>readyState</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/canplaythrough" title="/en-US/docs/Web/Events/canplaythrough">canplaythrough</a></code></td>
|
||||
<td></td>
|
||||
<td>Sent when the ready state changes to <code>CAN_PLAY_THROUGH</code>, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. <strong>Note</strong>: Manually setting the <code>currentTime</code> will eventually fire a <code>canplaythrough</code> event in firefox. Other browsers might not fire this event.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/emptied" title="/en-US/docs/Web/Events/emptied">emptied</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>The media has become empty; for example, this event is sent if the media has already been loaded (or partially loaded), and the <a href="/En/XPCOM_Interface_Reference/NsIDOMHTMLMediaElement" class="internal" title="en/nsIDOMHTMLMediaElement"><code>load()</code></a> method is called to reload it.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ended</code></td>
|
||||
<td></td>
|
||||
<td>Sent when playback completes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>error</code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when an error occurs. The element's <code>error</code> attribute contains more information. See <a href="/en-US/docs/Web/Guide/HTML/Using_HTML5_audio_and_video#Error_handling">Error handling</a> for details.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/loadeddata" title="/en-US/docs/Web/Events/loadeddata">loadeddata</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>The first frame of the media has finished loading.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/loadedmetadata" title="/en-US/docs/Web/Events/loadedmetadata">loadedmetadata</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>The media's metadata has finished loading; all attributes now contain as much useful information as they're going to.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/loadstart" title="/en-US/docs/Web/Events/loadstart">loadstart</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when loading of the media begins.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/pause" title="/en-US/docs/Web/Events/pause">pause</a></code></td>
|
||||
<td></td>
|
||||
<td>Sent when playback is paused.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/play" title="/en-US/docs/Web/Events/play">play</a></code></td>
|
||||
<td></td>
|
||||
<td>Sent when playback of the media starts after having been paused; that is, when playback is resumed after a prior <code>pause</code> event.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/playing" title="/en-US/docs/Web/Events/playing">playing</a></code></td>
|
||||
<td></td>
|
||||
<td>Sent when the media begins to play (either for the first time, after having been paused, or after ending and then restarting).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/progress" title="/en-US/docs/Web/Events/progress">progress</a></code></td>
|
||||
<td></td>
|
||||
<td>Sent periodically to inform interested parties of progress downloading the media. Information about the current amount of the media that has been downloaded is available in the media element's <code>buffered</code> attribute.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/seeked" title="/en-US/docs/Web/Events/seeked">seeked</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when a seek operation completes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/seeking" title="/en-US/docs/Web/Events/seeking">seeking</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when a seek operation begins.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/stalled" title="/en-US/docs/Web/Events/stalled">stalled</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/timeupdate" title="/en-US/docs/Web/Events/timeupdate">timeupdate</a></code></td>
|
||||
<td></td>
|
||||
<td>The time indicated by the element's <code>currentTime</code> attribute has changed.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/volumechange" title="/en-US/docs/Web/Events/volumechange">volumechange</a></code></td>
|
||||
<td></td>
|
||||
<td>Sent when the audio volume changes (both when the volume is set and when the <code>muted</code> attribute is changed).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a href="/en-US/docs/Web/Events/waiting" title="/en-US/docs/Web/Events/waiting">waiting</a></code></td>
|
||||
<td>✔</td>
|
||||
<td>Sent when the requested operation (such as playback) is delayed pending the completion of another operation (such as a seek).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>enterfullscreen</code></td>
|
||||
<td></td>
|
||||
<td>User enters fullscreen (either the proper fullscreen or full-window fallback for older browsers)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>exitfullscreen</code></td>
|
||||
<td></td>
|
||||
<td>User exits fullscreen</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>captionsenabled</code></td>
|
||||
<td></td>
|
||||
<td>Captions toggled on</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>captionsdisabled</code></td>
|
||||
<td></td>
|
||||
<td>Captions toggled off</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Here's an example of binding an event listener:
|
||||
|
||||
```javascript
|
||||
var media = document.querySelector(".js-plyr").plyr.media;
|
||||
|
||||
media.addEventListener("playing", function() {
|
||||
console.log("playing");
|
||||
document.querySelector(".js-plyr").addEventListener("playing", function() {
|
||||
/* Magic happens */
|
||||
});
|
||||
```
|
||||
A complete list of events can be found here:
|
||||
[Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html)
|
||||
|
||||
## Embeds
|
||||
|
||||
|
135
src/js/plyr.js
135
src/js/plyr.js
@ -92,18 +92,6 @@
|
||||
},
|
||||
tabFocus: 'tab-focus'
|
||||
},
|
||||
handlers: {
|
||||
seek: null,
|
||||
play: null,
|
||||
pause: null,
|
||||
restart: null,
|
||||
rewind: null,
|
||||
forward: null,
|
||||
mute: null,
|
||||
volume: null,
|
||||
captions: null,
|
||||
fullscreen: null
|
||||
},
|
||||
captions: {
|
||||
defaultActive: false
|
||||
},
|
||||
@ -138,6 +126,7 @@
|
||||
embed: ['youtube', 'vimeo'],
|
||||
html5: ['video', 'audio']
|
||||
},
|
||||
// URLs
|
||||
urls: {
|
||||
vimeo: {
|
||||
api: 'https://cdn.plyr.io/froogaloop/1.0.0/plyr.froogaloop.js',
|
||||
@ -145,7 +134,22 @@
|
||||
youtube: {
|
||||
api: 'https://www.youtube.com/iframe_api'
|
||||
}
|
||||
}
|
||||
},
|
||||
// Custom control listeners
|
||||
listeners: {
|
||||
seek: null,
|
||||
play: null,
|
||||
pause: null,
|
||||
restart: null,
|
||||
rewind: null,
|
||||
forward: null,
|
||||
mute: null,
|
||||
volume: null,
|
||||
captions: null,
|
||||
fullscreen: null
|
||||
},
|
||||
// Events to watch on HTML5 media elements
|
||||
events: ['ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'emptied']
|
||||
};
|
||||
|
||||
// Build the default HTML
|
||||
@ -529,36 +533,36 @@
|
||||
// Bind event
|
||||
function _on(element, events, callback) {
|
||||
if (element) {
|
||||
_toggleHandler(element, events, callback, true);
|
||||
_toggleListener(element, events, callback, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Unbind event
|
||||
function _off(element, events, callback) {
|
||||
if (element) {
|
||||
_toggleHandler(element, events, callback, false);
|
||||
_toggleListener(element, events, callback, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind along with custom handler
|
||||
function _proxyHandler(element, eventName, userHandler, defaultHandler) {
|
||||
function _proxyListener(element, eventName, userListener, defaultListener) {
|
||||
_on(element, eventName, function(event) {
|
||||
if(userHandler) {
|
||||
userHandler.apply(element, [event]);
|
||||
if(userListener) {
|
||||
userListener.apply(element, [event]);
|
||||
}
|
||||
defaultHandler.apply(element, [event]);
|
||||
defaultListener.apply(element, [event]);
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle event handler
|
||||
function _toggleHandler(element, events, callback, toggle) {
|
||||
// Toggle event listener
|
||||
function _toggleListener(element, events, callback, toggle) {
|
||||
var eventList = events.split(' ');
|
||||
|
||||
// If a nodelist is passed, call itself on each node
|
||||
if (element instanceof NodeList) {
|
||||
for (var x = 0; x < element.length; x++) {
|
||||
if (element[x] instanceof Node) {
|
||||
_toggleHandler(element[x], arguments[1], arguments[2], arguments[3]);
|
||||
_toggleListener(element[x], arguments[1], arguments[2], arguments[3]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -571,20 +575,17 @@
|
||||
}
|
||||
|
||||
// Trigger event
|
||||
function _triggerEvent(element, event) {
|
||||
function _triggerEvent(element, eventName, properties) {
|
||||
// Bail if no element
|
||||
if(!element || !event) {
|
||||
if(!element || !eventName) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create faux event
|
||||
var fauxEvent = document.createEvent('MouseEvents');
|
||||
|
||||
// Set the event type
|
||||
fauxEvent.initEvent(event, true, true);
|
||||
// create and dispatch the event
|
||||
var event = new CustomEvent(eventName, properties);
|
||||
|
||||
// Dispatch the event
|
||||
element.dispatchEvent(fauxEvent);
|
||||
element.dispatchEvent(event);
|
||||
}
|
||||
|
||||
// Toggle aria-pressed state on a toggle button
|
||||
@ -1241,6 +1242,9 @@
|
||||
// Bail if we're at 100%
|
||||
if (plyr.media.buffered === 1) {
|
||||
window.clearInterval(plyr.timer.buffering);
|
||||
|
||||
// Trigger event
|
||||
_triggerEvent(plyr.media, 'canplaythrough');
|
||||
}
|
||||
}, 200);
|
||||
|
||||
@ -1274,6 +1278,7 @@
|
||||
plyr.media.paused = false;
|
||||
plyr.media.seeking = false;
|
||||
_triggerEvent(plyr.media, 'play');
|
||||
_triggerEvent(plyr.media, 'playing');
|
||||
|
||||
// Poll to get playback progress
|
||||
plyr.timer.playing = window.setInterval(function() {
|
||||
@ -1289,6 +1294,7 @@
|
||||
case 2:
|
||||
plyr.media.paused = true;
|
||||
_triggerEvent(plyr.media, 'pause');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1339,6 +1345,7 @@
|
||||
plyr.embed.addEvent('play', function() {
|
||||
plyr.media.paused = false;
|
||||
_triggerEvent(plyr.media, 'play');
|
||||
_triggerEvent(plyr.media, 'playing');
|
||||
});
|
||||
|
||||
plyr.embed.addEvent('pause', function() {
|
||||
@ -1355,6 +1362,11 @@
|
||||
plyr.embed.addEvent('loadProgress', function(data) {
|
||||
plyr.media.buffered = data.percent;
|
||||
_triggerEvent(plyr.media, 'progress');
|
||||
|
||||
if(parseInt(data.percent) === 1) {
|
||||
// Trigger event
|
||||
_triggerEvent(plyr.media, 'canplaythrough');
|
||||
}
|
||||
});
|
||||
|
||||
plyr.embed.addEvent('finish', function() {
|
||||
@ -1646,7 +1658,8 @@
|
||||
break;
|
||||
|
||||
case 'vimeo':
|
||||
plyr.embed.api('seekTo', targetTime);
|
||||
// Round to nearest second for vimeo
|
||||
plyr.embed.api('seekTo', targetTime.toFixed(0));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1758,11 +1771,14 @@
|
||||
_toggleClass(plyr.controls, config.classes.hover, false);
|
||||
|
||||
// Keep an eye on the mouse location in relation to controls
|
||||
_toggleHandler(plyr.controls, 'mouseenter mouseleave', _setMouseOver, plyr.isFullscreen);
|
||||
_toggleListener(plyr.controls, 'mouseenter mouseleave', _setMouseOver, plyr.isFullscreen);
|
||||
|
||||
// Show the controls on mouse move
|
||||
_toggleHandler(plyr.container, 'mousemove', _showControls, plyr.isFullscreen);
|
||||
_toggleListener(plyr.container, 'mousemove', _showControls, plyr.isFullscreen);
|
||||
}
|
||||
|
||||
// Trigger an event
|
||||
_triggerEvent(plyr.container, plyr.isFullscreen ? 'enterfullscreen' : 'exitfullscreen');
|
||||
}
|
||||
|
||||
// Bail from faux-fullscreen
|
||||
@ -1898,6 +1914,9 @@
|
||||
|
||||
// Add class hook
|
||||
_toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled);
|
||||
|
||||
// Trigger an event
|
||||
_triggerEvent(plyr.container, plyr.captionsEnabled ? 'captionsenabled' : 'captionsdisabled');
|
||||
}
|
||||
|
||||
// Check if media is loading
|
||||
@ -2214,8 +2233,8 @@
|
||||
}
|
||||
|
||||
// Determine which buttons
|
||||
var trigger = plyr.buttons[play ? "play" : "pause"],
|
||||
target = plyr.buttons[play ? "pause" : "play"];
|
||||
var trigger = plyr.buttons[play ? 'play' : 'pause'],
|
||||
target = plyr.buttons[play ? 'pause' : 'play'];
|
||||
|
||||
// Setup focus and tab focus
|
||||
if(target) {
|
||||
@ -2266,33 +2285,33 @@
|
||||
}
|
||||
|
||||
// Play
|
||||
_proxyHandler(plyr.buttons.play, 'click', config.handlers.play, _togglePlay);
|
||||
_proxyListener(plyr.buttons.play, 'click', config.listeners.play, _togglePlay);
|
||||
|
||||
// Pause
|
||||
_proxyHandler(plyr.buttons.pause, 'click', config.handlers.pause, _togglePlay);
|
||||
_proxyListener(plyr.buttons.pause, 'click', config.listeners.pause, _togglePlay);
|
||||
|
||||
// Restart
|
||||
_proxyHandler(plyr.buttons.restart, 'click', config.handlers.restart, _seek);
|
||||
_proxyListener(plyr.buttons.restart, 'click', config.listeners.restart, _seek);
|
||||
|
||||
// Rewind
|
||||
_proxyHandler(plyr.buttons.rewind, 'click', config.handlers.rewind, _rewind);
|
||||
_proxyListener(plyr.buttons.rewind, 'click', config.listeners.rewind, _rewind);
|
||||
|
||||
// Fast forward
|
||||
_proxyHandler(plyr.buttons.forward, 'click', config.handlers.forward, _forward);
|
||||
_proxyListener(plyr.buttons.forward, 'click', config.listeners.forward, _forward);
|
||||
|
||||
// Seek
|
||||
_proxyHandler(plyr.buttons.seek, inputEvent, config.handlers.seek, _seek);
|
||||
_proxyListener(plyr.buttons.seek, inputEvent, config.listeners.seek, _seek);
|
||||
|
||||
// Set volume
|
||||
_proxyHandler(plyr.volume, inputEvent, config.handlers.volume, function() {
|
||||
_proxyListener(plyr.volume, inputEvent, config.listeners.volume, function() {
|
||||
_setVolume(plyr.volume.value);
|
||||
});
|
||||
|
||||
// Mute
|
||||
_proxyHandler(plyr.buttons.mute, 'click', config.handlers.mute, _toggleMute);
|
||||
_proxyListener(plyr.buttons.mute, 'click', config.listeners.mute, _toggleMute);
|
||||
|
||||
// Fullscreen
|
||||
_proxyHandler(plyr.buttons.fullscreen, 'click', config.handlers.fullscreen, _toggleFullscreen);
|
||||
_proxyListener(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, _toggleFullscreen);
|
||||
|
||||
// Handle user exiting fullscreen by escaping etc
|
||||
if (fullscreen.supportsFullScreen) {
|
||||
@ -2352,6 +2371,11 @@
|
||||
|
||||
// Loading
|
||||
_on(plyr.media, 'waiting canplay seeked', _checkLoading);
|
||||
|
||||
// Proxy events to container
|
||||
_on(plyr.media, config.events.join(' '), function(event) {
|
||||
_triggerEvent(plyr.container, event.type);
|
||||
});
|
||||
}
|
||||
|
||||
// Destroy an instance
|
||||
@ -2475,7 +2499,7 @@
|
||||
function _setupInterface() {
|
||||
// Don't setup interface if no support
|
||||
if (!plyr.supported.full) {
|
||||
_log("No full support for this media type (" + plyr.type + ")", true);
|
||||
_log('No full support for this media type (' + plyr.type + ')', true);
|
||||
|
||||
// Remove controls
|
||||
_remove(_getElement(config.selectors.controls.wrapper));
|
||||
@ -2642,9 +2666,7 @@
|
||||
element.plyr = (Object.keys(instance).length ? instance : false);
|
||||
|
||||
// Callback
|
||||
if (typeof config.onSetup === 'function') {
|
||||
config.onSetup.apply(element.plyr);
|
||||
}
|
||||
_triggerEvent(element, 'setup', { plyr: element.plyr });
|
||||
}
|
||||
|
||||
// Add to return array even if it's already setup
|
||||
@ -2656,3 +2678,20 @@
|
||||
|
||||
return api;
|
||||
}));
|
||||
|
||||
// Custom event polyfill
|
||||
//
|
||||
(function () {
|
||||
function CustomEvent (event, params) {
|
||||
params = params || { bubbles: false, cancelable: false, detail: undefined };
|
||||
var evt = document.createEvent('CustomEvent');
|
||||
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
|
||||
return evt;
|
||||
}
|
||||
|
||||
CustomEvent.prototype = window.Event.prototype;
|
||||
|
||||
if(!('CustomEvent' in window)) {
|
||||
window.CustomEvent = CustomEvent;
|
||||
}
|
||||
})();
|
||||
|
@ -7,78 +7,78 @@
|
||||
// -------------------------------
|
||||
|
||||
// Colors
|
||||
@blue: #3498DB;
|
||||
@gray-dark: #343F4A;
|
||||
@gray: #565D64;
|
||||
@gray-light: #6B7D86;
|
||||
@gray-lighter: #CBD0D3;
|
||||
@off-white: #D6DADD;
|
||||
@plyr-blue: #3498DB;
|
||||
@plyr-gray-dark: #343F4A;
|
||||
@plyr-gray: #565D64;
|
||||
@plyr-gray-light: #6B7D86;
|
||||
@plyr-gray-lighter: #CBD0D3;
|
||||
@plyr-off-white: #D6DADD;
|
||||
|
||||
// Font sizes
|
||||
@font-size-small: 14px;
|
||||
@font-size-base: 16px;
|
||||
@plyr-font-size-small: 14px;
|
||||
@plyr-font-size-base: 16px;
|
||||
|
||||
// Captions
|
||||
@font-size-captions-base: ceil(@font-size-base * 1.25);
|
||||
@font-size-captions-medium: ceil(@font-size-base * 1.5);
|
||||
@font-size-captions-large: (@font-size-base * 2);
|
||||
@plyr-font-size-captions-base: ceil(@plyr-font-size-base * 1.25);
|
||||
@plyr-font-size-captions-medium: ceil(@plyr-font-size-base * 1.5);
|
||||
@plyr-font-size-captions-large: (@plyr-font-size-base * 2);
|
||||
|
||||
// Controls
|
||||
@control-spacing: 10px;
|
||||
@controls-bg: #fff;
|
||||
@control-bg-hover: @blue;
|
||||
.contrast-control-color(@controls-bg);
|
||||
.contrast-control-color-hover(@control-bg-hover);
|
||||
@plyr-control-spacing: 10px;
|
||||
@plyr-controls-bg: #fff;
|
||||
@plyr-control-bg-hover: @plyr-blue;
|
||||
.contrast-control-color(@plyr-controls-bg);
|
||||
.contrast-control-color-hover(@plyr-control-bg-hover);
|
||||
|
||||
// Tooltips
|
||||
@tooltip-bg: @controls-bg;
|
||||
@tooltip-border-color: fade(@gray-dark, 10%);
|
||||
@tooltip-border-width: 1px;
|
||||
@tooltip-shadow: 0 0 5px @tooltip-border-color, 0 0 0 @tooltip-border-width @tooltip-border-color;
|
||||
@tooltip-color: @control-color;
|
||||
@tooltip-padding: @control-spacing;
|
||||
@tooltip-arrow-size: 6px;
|
||||
@tooltip-radius: 3px;
|
||||
@plyr-tooltip-bg: @plyr-controls-bg;
|
||||
@plyr-tooltip-border-color: fade(@plyr-gray-dark, 10%);
|
||||
@plyr-tooltip-border-width: 1px;
|
||||
@plyr-tooltip-shadow: 0 0 5px @plyr-tooltip-border-color, 0 0 0 @plyr-tooltip-border-width @plyr-tooltip-border-color;
|
||||
@plyr-tooltip-color: @plyr-control-color;
|
||||
@plyr-tooltip-padding: @plyr-control-spacing;
|
||||
@plyr-tooltip-arrow-size: 6px;
|
||||
@plyr-tooltip-radius: 3px;
|
||||
|
||||
// Progress
|
||||
@progress-bg: fade(@gray, 20%);
|
||||
@progress-playing-bg: @blue;
|
||||
@progress-buffered-bg: fade(@gray, 25%);
|
||||
@progress-loading-size: 40px;
|
||||
@progress-loading-bg: rgba(0,0,0, .15);
|
||||
@plyr-progress-bg: fade(@plyr-gray, 20%);
|
||||
@plyr-progress-playing-bg: @plyr-blue;
|
||||
@plyr-progress-buffered-bg: fade(@plyr-gray, 25%);
|
||||
@plyr-progress-loading-size: 40px;
|
||||
@plyr-progress-loading-bg: fade(#000, 15%);
|
||||
|
||||
// Volume
|
||||
@volume-track-height: 6px;
|
||||
@volume-track-bg: darken(@controls-bg, 10%);
|
||||
@volume-thumb-height: (@volume-track-height * 2);
|
||||
@volume-thumb-width: (@volume-track-height * 2);
|
||||
@volume-thumb-bg: @control-color;
|
||||
@volume-thumb-bg-focus: @control-bg-hover;
|
||||
@plyr-volume-track-height: 6px;
|
||||
@plyr-volume-track-bg: darken(@plyr-controls-bg, 10%);
|
||||
@plyr-volume-thumb-height: (@plyr-volume-track-height * 2);
|
||||
@plyr-volume-thumb-width: (@plyr-volume-track-height * 2);
|
||||
@plyr-volume-thumb-bg: @plyr-control-color;
|
||||
@plyr-volume-thumb-bg-focus: @plyr-control-bg-hover;
|
||||
|
||||
// Breakpoints
|
||||
@bp-control-split: 560px; // When controls split into left/right
|
||||
@bp-captions-large: 768px; // When captions jump to the larger font size
|
||||
@plyr-bp-control-split: 560px; // When controls split into left/right
|
||||
@plyr-bp-captions-large: 768px; // When captions jump to the larger font size
|
||||
|
||||
// Animation
|
||||
// ---------------------------------------
|
||||
@keyframes progress {
|
||||
to { background-position: @progress-loading-size 0; }
|
||||
@keyframes plyr-progress {
|
||||
to { background-position: @plyr-progress-loading-size 0; }
|
||||
}
|
||||
|
||||
// Mixins
|
||||
// -------------------------------
|
||||
// Contrast
|
||||
.contrast-control-color(@color: "") when (lightness(@color) >= 65%) {
|
||||
@control-color: @gray-light;
|
||||
.contrast-control-color(@plyr-color: "") when (lightness(@plyr-color) >= 65%) {
|
||||
@plyr-control-color: @plyr-gray-light;
|
||||
}
|
||||
.contrast-control-color(@color: "") when (lightness(@color) < 65%) {
|
||||
@control-color: @gray-lighter;
|
||||
.contrast-control-color(@plyr-color: "") when (lightness(@plyr-color) < 65%) {
|
||||
@plyr-control-color: @plyr-gray-lighter;
|
||||
}
|
||||
.contrast-control-color-hover(@color: "") when (lightness(@color) >= 65%) {
|
||||
@control-color-hover: @gray;
|
||||
.contrast-control-color-hover(@plyr-color: "") when (lightness(@plyr-color) >= 65%) {
|
||||
@plyr-control-color-hover: @plyr-gray;
|
||||
}
|
||||
.contrast-control-color-hover(@color: "") when (lightness(@color) < 65%) {
|
||||
@control-color-hover: #fff;
|
||||
.contrast-control-color-hover(@plyr-color: "") when (lightness(@plyr-color) < 65%) {
|
||||
@plyr-control-color-hover: #fff;
|
||||
}
|
||||
|
||||
// Font smoothing
|
||||
@ -91,40 +91,27 @@
|
||||
-webkit-font-smoothing: subpixel-antialiased;
|
||||
}
|
||||
|
||||
// Contain floats: nicolasgallagher.com/micro-clearfix-hack/
|
||||
.clearfix() {
|
||||
zoom: 1;
|
||||
&:before,
|
||||
&:after { content: ""; display: table; }
|
||||
&:after { clear: both; }
|
||||
}
|
||||
// Tab focus styles
|
||||
.tab-focus() {
|
||||
outline: 1px dotted fade(@gray-dark, 80%);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
// <input type="range"> styling
|
||||
.volume-thumb() {
|
||||
height: @volume-thumb-height;
|
||||
width: @volume-thumb-width;
|
||||
background: @volume-thumb-bg;
|
||||
height: @plyr-volume-thumb-height;
|
||||
width: @plyr-volume-thumb-width;
|
||||
background: @plyr-volume-thumb-bg;
|
||||
border: 0;
|
||||
border-radius: 100%;
|
||||
transition: background .3s ease;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.volume-track() {
|
||||
height: @volume-track-height;
|
||||
background: @volume-track-bg;
|
||||
height: @plyr-volume-track-height;
|
||||
background: @plyr-volume-track-bg;
|
||||
border: 0;
|
||||
border-radius: (@volume-track-height / 2);
|
||||
border-radius: (@plyr-volume-track-height / 2);
|
||||
}
|
||||
.seek-thumb() {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
width: (@control-spacing * 4);
|
||||
height: @control-spacing;
|
||||
width: (@plyr-control-spacing * 4);
|
||||
height: @plyr-control-spacing;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.seek-track() {
|
||||
@ -208,49 +195,55 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: (@control-spacing * 2) (@control-spacing * 2) (@control-spacing * 3);
|
||||
padding: (@plyr-control-spacing * 2) (@plyr-control-spacing * 2) (@plyr-control-spacing * 3);
|
||||
color: #fff;
|
||||
font-size: @font-size-captions-base;
|
||||
font-size: @plyr-font-size-captions-base;
|
||||
text-align: center;
|
||||
.font-smoothing();
|
||||
|
||||
span {
|
||||
border-radius: 2px;
|
||||
padding: 3px 10px;
|
||||
background: rgba(0,0,0, .9);
|
||||
background: fade(#000, 90%);
|
||||
}
|
||||
span:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: @bp-captions-large) {
|
||||
font-size: @font-size-captions-medium;
|
||||
@media (min-width: @plyr-bp-captions-large) {
|
||||
font-size: @plyr-font-size-captions-medium;
|
||||
}
|
||||
}
|
||||
&--captions-active &__captions {
|
||||
display: block;
|
||||
}
|
||||
&--fullscreen-active &__captions {
|
||||
font-size: @font-size-captions-large;
|
||||
font-size: @plyr-font-size-captions-large;
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
&__controls {
|
||||
.clearfix();
|
||||
.font-smoothing();
|
||||
position: relative;
|
||||
padding: @control-spacing;
|
||||
background: @controls-bg;
|
||||
padding: @plyr-control-spacing;
|
||||
background: @plyr-controls-bg;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
box-shadow: 0 1px 1px fade(@gray-dark, 20%);
|
||||
box-shadow: 0 1px 1px fade(@plyr-gray-dark, 20%);
|
||||
|
||||
// Clear floats
|
||||
&::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
// Layout
|
||||
&--right {
|
||||
display: block;
|
||||
margin: @control-spacing auto 0;
|
||||
margin: @plyr-control-spacing auto 0;
|
||||
}
|
||||
@media (min-width: @bp-control-split) {
|
||||
@media (min-width: @plyr-bp-control-split) {
|
||||
&--left {
|
||||
float: left;
|
||||
}
|
||||
@ -265,13 +258,13 @@
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 0 2px;
|
||||
padding: (@control-spacing / 2) @control-spacing;
|
||||
padding: (@plyr-control-spacing / 2) @plyr-control-spacing;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
color: @control-color;
|
||||
color: @plyr-control-color;
|
||||
transition: background .3s ease, color .3s ease, opacity .3s ease;
|
||||
|
||||
svg {
|
||||
@ -285,8 +278,8 @@
|
||||
// Hover and tab focus
|
||||
&.tab-focus:focus,
|
||||
&:hover {
|
||||
background: @control-bg-hover;
|
||||
color: @control-color-hover;
|
||||
background: @plyr-control-bg-hover;
|
||||
color: @plyr-control-color-hover;
|
||||
}
|
||||
// Default focus
|
||||
&:focus {
|
||||
@ -305,24 +298,24 @@
|
||||
.plyr__time {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: @control-spacing;
|
||||
color: @control-color;
|
||||
margin-left: @plyr-control-spacing;
|
||||
color: @plyr-control-color;
|
||||
font-weight: 600;
|
||||
font-size: @font-size-small;
|
||||
font-size: @plyr-font-size-small;
|
||||
}
|
||||
|
||||
// Media duration hidden on small screens
|
||||
.plyr__time + .plyr__time {
|
||||
display: none;
|
||||
|
||||
@media (min-width: @bp-control-split) {
|
||||
@media (min-width: @plyr-bp-control-split) {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// Add a slash in before
|
||||
&::before {
|
||||
content: '\2044';
|
||||
margin-right: @control-spacing;
|
||||
margin-right: @plyr-control-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,19 +325,19 @@
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
bottom: 100%;
|
||||
margin-bottom: @tooltip-padding;
|
||||
padding: @tooltip-padding (@tooltip-padding * 1.5);
|
||||
margin-bottom: @plyr-tooltip-padding;
|
||||
padding: @plyr-tooltip-padding (@plyr-tooltip-padding * 1.5);
|
||||
|
||||
opacity: 0;
|
||||
background: @tooltip-bg;
|
||||
box-shadow: @tooltip-shadow;
|
||||
border-radius: @tooltip-radius;
|
||||
color: @tooltip-color;
|
||||
font-size: @font-size-small;
|
||||
background: @plyr-tooltip-bg;
|
||||
box-shadow: @plyr-tooltip-shadow;
|
||||
border-radius: @plyr-tooltip-radius;
|
||||
color: @plyr-tooltip-color;
|
||||
font-size: @plyr-font-size-small;
|
||||
line-height: 1.5;
|
||||
font-weight: 600;
|
||||
|
||||
transform: translate(-50%, (@tooltip-padding * 3)) scale(.8);
|
||||
transform: translate(-50%, (@plyr-tooltip-padding * 3)) scale(.8);
|
||||
transform-origin: 50% 100%;
|
||||
transition: transform .2s .1s ease, opacity .2s .1s ease;
|
||||
|
||||
@ -361,19 +354,19 @@
|
||||
}
|
||||
// The border triangle
|
||||
&::after {
|
||||
@border-arrow-size: (@tooltip-arrow-size + (@tooltip-border-width * 1));
|
||||
bottom: -(@border-arrow-size + @tooltip-border-width);
|
||||
border-right: @border-arrow-size solid transparent;
|
||||
border-top: @border-arrow-size solid @tooltip-border-color;
|
||||
border-left: @border-arrow-size solid transparent;
|
||||
@plyr-border-arrow-size: (@plyr-tooltip-arrow-size + (@plyr-tooltip-border-width * 1));
|
||||
bottom: -(@plyr-border-arrow-size + @plyr-tooltip-border-width);
|
||||
border-right: @plyr-border-arrow-size solid transparent;
|
||||
border-top: @plyr-border-arrow-size solid @plyr-tooltip-border-color;
|
||||
border-left: @plyr-border-arrow-size solid transparent;
|
||||
z-index: 1;
|
||||
}
|
||||
// The background triangle
|
||||
&::before {
|
||||
bottom: -@tooltip-arrow-size;
|
||||
border-right: @tooltip-arrow-size solid transparent;
|
||||
border-top: @tooltip-arrow-size solid @tooltip-bg;
|
||||
border-left: @tooltip-arrow-size solid transparent;
|
||||
bottom: -@plyr-tooltip-arrow-size;
|
||||
border-right: @plyr-tooltip-arrow-size solid transparent;
|
||||
border-top: @plyr-tooltip-arrow-size solid @plyr-tooltip-bg;
|
||||
border-left: @plyr-tooltip-arrow-size solid transparent;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
@ -388,7 +381,8 @@
|
||||
|
||||
// Common range styles
|
||||
input[type='range'].tab-focus:focus {
|
||||
.tab-focus();
|
||||
outline: 1px dotted fade(@plyr-gray-dark, 80%);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
// Playback progress
|
||||
@ -399,8 +393,8 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: @control-spacing;
|
||||
background: @progress-bg;
|
||||
height: @plyr-control-spacing;
|
||||
background: @plyr-progress-bg;
|
||||
|
||||
&--buffer[value],
|
||||
&--played[value],
|
||||
@ -409,7 +403,7 @@
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: @control-spacing;
|
||||
height: @plyr-control-spacing;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
@ -423,22 +417,25 @@
|
||||
&--played[value] {
|
||||
&::-webkit-progress-bar {
|
||||
background: transparent;
|
||||
transition: width .2s ease;
|
||||
}
|
||||
|
||||
// Inherit from currentColor;
|
||||
&::-webkit-progress-value {
|
||||
background: currentColor;
|
||||
transition: width .2s ease;
|
||||
}
|
||||
&::-moz-progress-bar {
|
||||
background: currentColor;
|
||||
transition: width .2s ease;
|
||||
}
|
||||
}
|
||||
&--played[value] {
|
||||
z-index: 2;
|
||||
color: @progress-playing-bg;
|
||||
color: @plyr-progress-playing-bg;
|
||||
}
|
||||
&--buffer[value] {
|
||||
color: @progress-buffered-bg;
|
||||
color: @plyr-progress-buffered-bg;
|
||||
}
|
||||
|
||||
// Seek control
|
||||
@ -491,17 +488,17 @@
|
||||
|
||||
// Loading state
|
||||
&--loading .plyr__progress--buffer {
|
||||
animation: progress 1s linear infinite;
|
||||
background-size: @progress-loading-size @progress-loading-size;
|
||||
animation: plyr-progress 1s linear infinite;
|
||||
background-size: @plyr-progress-loading-size @plyr-progress-loading-size;
|
||||
background-repeat: repeat-x;
|
||||
background-color: @progress-buffered-bg;
|
||||
background-color: @plyr-progress-buffered-bg;
|
||||
background-image: linear-gradient(
|
||||
-45deg,
|
||||
@progress-loading-bg 25%,
|
||||
@plyr-progress-loading-bg 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
@progress-loading-bg 50%,
|
||||
@progress-loading-bg 75%,
|
||||
@plyr-progress-loading-bg 50%,
|
||||
@plyr-progress-loading-bg 75%,
|
||||
transparent 75%,
|
||||
transparent);
|
||||
color: transparent;
|
||||
@ -525,7 +522,7 @@
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 100px;
|
||||
margin: 0 @control-spacing 0 0;
|
||||
margin: 0 @plyr-control-spacing 0 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
@ -537,7 +534,7 @@
|
||||
}
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
margin-top: -((@volume-thumb-height - @volume-track-height) / 2);
|
||||
margin-top: -((@plyr-volume-thumb-height - @plyr-volume-track-height) / 2);
|
||||
.volume-thumb();
|
||||
}
|
||||
|
||||
@ -551,10 +548,10 @@
|
||||
|
||||
// Microsoft
|
||||
&::-ms-track {
|
||||
height: @volume-track-height;
|
||||
height: @plyr-volume-track-height;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
border-width: ((@volume-thumb-height - @volume-track-height) / 2) 0;
|
||||
border-width: ((@plyr-volume-thumb-height - @plyr-volume-track-height) / 2) 0;
|
||||
color: transparent;
|
||||
}
|
||||
&::-ms-fill-lower,
|
||||
@ -569,13 +566,13 @@
|
||||
outline: 0;
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
background: @volume-thumb-bg-focus;
|
||||
background: @plyr-volume-thumb-bg-focus;
|
||||
}
|
||||
&::-moz-range-thumb {
|
||||
background: @volume-thumb-bg-focus;
|
||||
background: @plyr-volume-thumb-bg-focus;
|
||||
}
|
||||
&::-ms-thumb {
|
||||
background: @volume-thumb-bg-focus;
|
||||
background: @plyr-volume-thumb-bg-focus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -596,16 +593,16 @@
|
||||
// Audio specific styles
|
||||
// Position the progress within the container
|
||||
&--audio .plyr__controls {
|
||||
padding-top: (@control-spacing * 2);
|
||||
padding-top: (@plyr-control-spacing * 2);
|
||||
}
|
||||
&--audio .plyr__progress {
|
||||
bottom: auto;
|
||||
top: 0;
|
||||
background: @off-white;
|
||||
background: @plyr-off-white;
|
||||
}
|
||||
|
||||
// Full screen mode
|
||||
&--fullscreen,
|
||||
&.plyr--fullscreen,
|
||||
&--fullscreen-active {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@ -633,28 +630,29 @@
|
||||
}
|
||||
|
||||
// Hide controls when playing in full screen
|
||||
&--fullscreen--hide-controls&--fullscreen-active&--playing {
|
||||
&--fullscreen-active.plyr--fullscreen--hide-controls.plyr--playing,
|
||||
&.plyr--fullscreen.plyr--fullscreen--hide-controls.plyr--playing {
|
||||
.plyr__controls {
|
||||
transform: translateY(100%) translateY(@control-spacing / 2);
|
||||
transform: translateY(100%) translateY(@plyr-control-spacing / 2);
|
||||
transition: transform .3s .2s ease;
|
||||
}
|
||||
.plyr__captions {
|
||||
bottom: (@plyr-control-spacing / 2);
|
||||
transition: bottom .3s .2s ease;
|
||||
}
|
||||
&.plyr--hover .plyr__controls {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.plyr__captions {
|
||||
bottom: (@control-spacing / 2);
|
||||
transition: bottom .3s .2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// Captions
|
||||
&--fullscreen .plyr__captions,
|
||||
&.plyr--fullscreen .plyr__captions,
|
||||
&--fullscreen-active .plyr__captions,
|
||||
&--fullscreen--hide-controls&--fullscreen-active&--playing&--hover &__captions {
|
||||
&--fullscreen--hide-controls.plyr--fullscreen-active.plyr--playing.plyr--hover .plyr__captions {
|
||||
top: auto;
|
||||
bottom: 90px;
|
||||
|
||||
@media (min-width: @bp-control-split) {
|
||||
@media (min-width: @plyr-bp-control-split) {
|
||||
bottom: 60px;
|
||||
}
|
||||
}
|
||||
|
@ -7,76 +7,76 @@
|
||||
// -------------------------------
|
||||
|
||||
// Colors
|
||||
$blue: #3498DB !default;
|
||||
$gray-dark: #343F4A !default;
|
||||
$gray: #565D64 !default;
|
||||
$gray-light: #6B7D86 !default;
|
||||
$gray-lighter: #CBD0D3 !default;
|
||||
$off-white: #D6DADD !default;
|
||||
$plyr-blue: #3498DB !default;
|
||||
$plyr-gray-dark: #343F4A !default;
|
||||
$plyr-gray: #565D64 !default;
|
||||
$plyr-gray-light: #6B7D86 !default;
|
||||
$plyr-gray-lighter: #CBD0D3 !default;
|
||||
$plyr-off-white: #D6DADD !default;
|
||||
|
||||
// Font sizes
|
||||
$font-size-small: 14px !default;
|
||||
$font-size-base: 16px !default;
|
||||
$plyr-font-size-small: 14px !default;
|
||||
$plyr-font-size-base: 16px !default;
|
||||
|
||||
// Captions
|
||||
$font-size-captions-base: ceil($font-size-base * 1.25) !default;
|
||||
$font-size-captions-medium: ceil($font-size-base * 1.5) !default;
|
||||
$font-size-captions-large: ($font-size-base * 2) !default;
|
||||
$plyr-font-size-captions-base: ceil($plyr-font-size-base * 1.25) !default;
|
||||
$plyr-font-size-captions-medium: ceil($plyr-font-size-base * 1.5) !default;
|
||||
$plyr-font-size-captions-large: ($plyr-font-size-base * 2) !default;
|
||||
|
||||
// Controls
|
||||
$control-spacing: 10px !default;
|
||||
$controls-bg: #fff !default;
|
||||
$control-bg-hover: $blue !default;
|
||||
$control-color: null !default;
|
||||
$control-color-hover: null !default;
|
||||
$plyr-control-spacing: 10px !default;
|
||||
$plyr-controls-bg: #fff !default;
|
||||
$plyr-control-bg-hover: $plyr-blue !default;
|
||||
$plyr-control-color: null !default;
|
||||
$plyr-control-color-hover: null !default;
|
||||
|
||||
// Contrast
|
||||
@if lightness($controls-bg) >= 65% {
|
||||
$control-color: $gray-light;
|
||||
@if lightness($plyr-controls-bg) >= 65% {
|
||||
$plyr-control-color: $plyr-gray-light;
|
||||
}
|
||||
@else {
|
||||
$control-color: $gray-lighter;
|
||||
$plyr-control-color: $plyr-gray-lighter;
|
||||
}
|
||||
@if lightness($control-bg-hover) >= 65% {
|
||||
$control-color-hover: $gray;
|
||||
@if lightness($plyr-control-bg-hover) >= 65% {
|
||||
$plyr-control-color-hover: $plyr-gray;
|
||||
}
|
||||
@else {
|
||||
$control-color-hover: #fff;
|
||||
$plyr-control-color-hover: #fff;
|
||||
}
|
||||
|
||||
// Tooltips
|
||||
$tooltip-bg: $controls-bg !default;
|
||||
$tooltip-border-color: transparentize(@gray-dark, .1) !default;
|
||||
$tooltip-border-width: 1px;
|
||||
$tooltip-shadow: 0 0 5px $tooltip-border-color, 0 0 0 $tooltip-border-width $tooltip-border-color;
|
||||
$tooltip-color: $control-color !default;
|
||||
$tooltip-padding: $control-spacing !default;
|
||||
$tooltip-arrow-size: 6px !default;
|
||||
$tooltip-radius: 3px !default;
|
||||
$plyr-tooltip-bg: $plyr-controls-bg !default;
|
||||
$plyr-tooltip-border-color: transparentize(@gray-dark, .1) !default;
|
||||
$plyr-tooltip-border-width: 1px;
|
||||
$plyr-tooltip-shadow: 0 0 5px $plyr-tooltip-border-color, 0 0 0 $plyr-tooltip-border-width $plyr-tooltip-border-color;
|
||||
$plyr-tooltip-color: $plyr-control-color !default;
|
||||
$plyr-tooltip-padding: $plyr-control-spacing !default;
|
||||
$plyr-tooltip-arrow-size: 6px !default;
|
||||
$plyr-tooltip-radius: 3px !default;
|
||||
|
||||
// Progress
|
||||
$progress-bg: transparentize($gray, .2) !default;
|
||||
$progress-playing-bg: $blue !default;
|
||||
$progress-buffered-bg: transparentize($gray, .25) !default;
|
||||
$progress-loading-size: 40px !default;
|
||||
$progress-loading-bg: rgba(0,0,0, .15) !default;
|
||||
$plyr-progress-bg: transparentize($plyr-gray, .2) !default;
|
||||
$plyr-progress-playing-bg: $plyr-blue !default;
|
||||
$plyr-progress-buffered-bg: transparentize($plyr-gray, .25) !default;
|
||||
$plyr-progress-loading-size: 40px !default;
|
||||
$plyr-progress-loading-bg: transparentize(#000, .15); !default;
|
||||
|
||||
// Volume
|
||||
$volume-track-height: 6px !default;
|
||||
$volume-track-bg: darken($controls-bg, 10%) !default;
|
||||
$volume-thumb-height: ($volume-track-height * 2) !default;
|
||||
$volume-thumb-width: ($volume-track-height * 2) !default;
|
||||
$volume-thumb-bg: $control-color !default;
|
||||
$volume-thumb-bg-focus: $control-bg-hover !default;
|
||||
$plyr-volume-track-height: 6px !default;
|
||||
$plyr-volume-track-bg: darken($plyr-controls-bg, 10%) !default;
|
||||
$plyr-volume-thumb-height: ($plyr-volume-track-height * 2) !default;
|
||||
$plyr-volume-thumb-width: ($plyr-volume-track-height * 2) !default;
|
||||
$plyr-volume-thumb-bg: $plyr-control-color !default;
|
||||
$plyr-volume-thumb-bg-focus: $plyr-control-bg-hover !default;
|
||||
|
||||
// Breakpoints
|
||||
$bp-control-split: 560px !default; // When controls split into left/right
|
||||
$bp-captions-large: 768px !default; // When captions jump to the larger font size
|
||||
$plyr-bp-control-split: 560px !default; // When controls split into left/right
|
||||
$plyr-bp-captions-large: 768px !default; // When captions jump to the larger font size
|
||||
|
||||
// Animation
|
||||
// ---------------------------------------
|
||||
@keyframes progress {
|
||||
to { background-position: $progress-loading-size 0; }
|
||||
@keyframes plyr-progress {
|
||||
to { background-position: $plyr-progress-loading-size 0; }
|
||||
}
|
||||
|
||||
// Font smoothing
|
||||
@ -92,41 +92,27 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
}
|
||||
}
|
||||
|
||||
// Contain floats: nicolasgallagher.com/micro-clearfix-hack/
|
||||
@mixin clearfix()
|
||||
{
|
||||
zoom: 1;
|
||||
&:before,
|
||||
&:after { content: ''; display: table; }
|
||||
&:after { clear: both; }
|
||||
}
|
||||
// Tab focus styles
|
||||
@mixin tab-focus() {
|
||||
outline: thin dotted transparentize($gray-dark, .8);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
// <input type="range"> styling
|
||||
@mixin volume-thumb() {
|
||||
height: $volume-thumb-height;
|
||||
width: $volume-thumb-width;
|
||||
background: $volume-thumb-bg;
|
||||
height: $plyr-volume-thumb-height;
|
||||
width: $plyr-volume-thumb-width;
|
||||
background: $plyr-volume-thumb-bg;
|
||||
border: 0;
|
||||
border-radius: 100%;
|
||||
transition: background .3s ease;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
@mixin volume-track() {
|
||||
height: $volume-track-height;
|
||||
background: $volume-track-bg;
|
||||
height: $plyr-volume-track-height;
|
||||
background: $plyr-volume-track-bg;
|
||||
border: 0;
|
||||
border-radius: ($volume-track-height / 2);
|
||||
border-radius: ($plyr-volume-track-height / 2);
|
||||
}
|
||||
@mixin seek-thumb() {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
width: ($control-spacing * 4);
|
||||
height: $control-spacing;
|
||||
width: ($plyr-control-spacing * 4);
|
||||
height: $plyr-control-spacing;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
@mixin seek-track() {
|
||||
@ -209,49 +195,55 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: ($control-spacing * 2) ($control-spacing * 2) ($control-spacing * 3);
|
||||
padding: ($plyr-control-spacing * 2) ($plyr-control-spacing * 2) ($plyr-control-spacing * 3);
|
||||
color: #fff;
|
||||
font-size: $font-size-captions-base;
|
||||
font-size: $plyr-font-size-captions-base;
|
||||
text-align: center;
|
||||
@include font-smoothing();
|
||||
|
||||
span {
|
||||
border-radius: 2px;
|
||||
padding: 3px 10px;
|
||||
background: rgba(0,0,0, .9);
|
||||
background: transparentize(#000, .9);
|
||||
}
|
||||
span:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: $bp-captions-large) {
|
||||
font-size: $font-size-captions-medium;
|
||||
@media (min-width: $plyr-bp-captions-large) {
|
||||
font-size: $plyr-font-size-captions-medium;
|
||||
}
|
||||
}
|
||||
&--captions-active &__captions {
|
||||
display: block;
|
||||
}
|
||||
&--fullscreen-active &__captions {
|
||||
font-size: $font-size-captions-large;
|
||||
font-size: $plyr-font-size-captions-large;
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
&__controls {
|
||||
@include clearfix();
|
||||
@include font-smoothing();
|
||||
position: relative;
|
||||
padding: $control-spacing;
|
||||
background: $controls-bg;
|
||||
padding: $plyr-control-spacing;
|
||||
background: $plyr-controls-bg;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
box-shadow: 0 1px 1px transparentize($gray-dark, .2);
|
||||
box-shadow: 0 1px 1px transparentize($plyr-gray-dark, .2);
|
||||
|
||||
// Clear floats
|
||||
&::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
// Layout
|
||||
&--right {
|
||||
display: block;
|
||||
margin: $control-spacing auto 0;
|
||||
margin: $plyr-control-spacing auto 0;
|
||||
}
|
||||
@media (min-width: $bp-control-split) {
|
||||
@media (min-width: $plyr-bp-control-split) {
|
||||
&--left {
|
||||
float: left;
|
||||
}
|
||||
@ -266,13 +258,13 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 0 2px;
|
||||
padding: ($control-spacing / 2) $control-spacing;
|
||||
padding: ($plyr-control-spacing / 2) $plyr-control-spacing;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
color: $control-color;
|
||||
color: $plyr-control-color;
|
||||
transition: background .3s ease, color .3s ease, opacity .3s ease;
|
||||
|
||||
svg {
|
||||
@ -286,8 +278,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
// Hover and tab focus
|
||||
&.tab-focus:hover,
|
||||
&:hover {
|
||||
background: $control-bg-hover;
|
||||
color: $control-color-hover;
|
||||
background: $plyr-control-bg-hover;
|
||||
color: $plyr-control-color-hover;
|
||||
}
|
||||
// Default focus
|
||||
&:focus {
|
||||
@ -306,24 +298,24 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
.plyr__time {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: $control-spacing;
|
||||
color: $control-color;
|
||||
margin-left: $plyr-control-spacing;
|
||||
color: $plyr-control-color;
|
||||
font-weight: 600;
|
||||
font-size: $font-size-small;
|
||||
font-size: $plyr-font-size-small;
|
||||
}
|
||||
|
||||
// Media duration hidden on small screens
|
||||
.plyr__time + .plyr__time {
|
||||
display: none;
|
||||
|
||||
@media (min-width: $bp-control-split) {
|
||||
@media (min-width: $plyr-bp-control-split) {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
// Add a slash in before
|
||||
&::before {
|
||||
content: '\2044';
|
||||
margin-right: $control-spacing;
|
||||
margin-right: $plyr-control-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -333,19 +325,19 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
bottom: 100%;
|
||||
margin-bottom: $tooltip-padding;
|
||||
padding: $tooltip-padding ($tooltip-padding * 1.5);
|
||||
margin-bottom: $plyr-tooltip-padding;
|
||||
padding: $plyr-tooltip-padding ($plyr-tooltip-padding * 1.5);
|
||||
|
||||
opacity: 0;
|
||||
background: $tooltip-bg;
|
||||
box-shadow: $tooltip-shadow;
|
||||
border-radius: $tooltip-radius;
|
||||
color: $tooltip-color;
|
||||
font-size: $font-size-small;
|
||||
background: $plyr-tooltip-bg;
|
||||
box-shadow: $plyr-tooltip-shadow;
|
||||
border-radius: $plyr-tooltip-radius;
|
||||
color: $plyr-tooltip-color;
|
||||
font-size: $plyr-font-size-small;
|
||||
line-height: 1.5;
|
||||
font-weight: 600;
|
||||
|
||||
transform: translate(-50%, ($tooltip-padding * 3)) scale(.8);
|
||||
transform: translate(-50%, ($plyr-tooltip-padding * 3)) scale(.8);
|
||||
transform-origin: 50% 100%;
|
||||
transition: transform .2s .1s ease, opacity .2s .1s ease;
|
||||
|
||||
@ -362,19 +354,19 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
}
|
||||
// The border triangle
|
||||
&::after {
|
||||
$border-arrow-size: ($tooltip-arrow-size + ($tooltip-border-width * 1));
|
||||
bottom: -($border-arrow-size + $tooltip-border-width);
|
||||
border-right: $border-arrow-size solid transparent;
|
||||
border-top: $border-arrow-size solid $tooltip-border-color;
|
||||
border-left: $border-arrow-size solid transparent;
|
||||
$plyr-border-arrow-size: ($plyr-tooltip-arrow-size + ($plyr-tooltip-border-width * 1));
|
||||
bottom: -($plyr-border-arrow-size + $plyr-tooltip-border-width);
|
||||
border-right: $plyr-border-arrow-size solid transparent;
|
||||
border-top: $plyr-border-arrow-size solid $plyr-tooltip-border-color;
|
||||
border-left: $plyr-border-arrow-size solid transparent;
|
||||
z-index: 1;
|
||||
}
|
||||
// The background triangle
|
||||
&::before {
|
||||
bottom: -$tooltip-arrow-size;
|
||||
border-right: $tooltip-arrow-size solid transparent;
|
||||
border-top: $tooltip-arrow-size solid $tooltip-bg;
|
||||
border-left: $tooltip-arrow-size solid transparent;
|
||||
bottom: -$plyr-tooltip-arrow-size;
|
||||
border-right: $plyr-tooltip-arrow-size solid transparent;
|
||||
border-top: $plyr-tooltip-arrow-size solid $plyr-tooltip-bg;
|
||||
border-left: $plyr-tooltip-arrow-size solid transparent;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
@ -389,7 +381,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
|
||||
// Common range styles
|
||||
input[type='range'].tab-focus:focus {
|
||||
.tab-focus();
|
||||
outline: thin dotted transparentize($plyr-gray-dark, .8);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
// Playback progress
|
||||
@ -400,8 +393,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: $control-spacing;
|
||||
background: $progress-bg;
|
||||
height: $plyr-control-spacing;
|
||||
background: $plyr-progress-bg;
|
||||
|
||||
&--buffer[value],
|
||||
&--played[value],
|
||||
@ -410,7 +403,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: $control-spacing;
|
||||
height: $plyr-control-spacing;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
@ -424,22 +417,25 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
&--played[value] {
|
||||
&::-webkit-progress-bar {
|
||||
background: transparent;
|
||||
transition: width .2s ease;
|
||||
}
|
||||
|
||||
// Inherit from currentColor;
|
||||
&::-webkit-progress-value {
|
||||
background: currentColor;
|
||||
transition: width .2s ease;
|
||||
}
|
||||
&::-moz-progress-bar {
|
||||
background: currentColor;
|
||||
transition: width .2s ease;
|
||||
}
|
||||
}
|
||||
&--played[value] {
|
||||
z-index: 2;
|
||||
color: $progress-playing-bg;
|
||||
color: $plyr-progress-playing-bg;
|
||||
}
|
||||
&--buffer[value] {
|
||||
color: $progress-buffered-bg;
|
||||
color: $plyr-progress-buffered-bg;
|
||||
}
|
||||
|
||||
// Seek control
|
||||
@ -492,17 +488,17 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
|
||||
// Loading state
|
||||
&--loading .plyr__progress--buffer {
|
||||
animation: progress 1s linear infinite;
|
||||
background-size: $progress-loading-size $progress-loading-size;
|
||||
animation: plyr-progress 1s linear infinite;
|
||||
background-size: $plyr-progress-loading-size $plyr-progress-loading-size;
|
||||
background-repeat: repeat-x;
|
||||
background-color: $progress-buffered-bg;
|
||||
background-color: $plyr-progress-buffered-bg;
|
||||
background-image: linear-gradient(
|
||||
-45deg,
|
||||
$progress-loading-bg 25%,
|
||||
$plyr-progress-loading-bg 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
$progress-loading-bg 50%,
|
||||
$progress-loading-bg 75%,
|
||||
$plyr-progress-loading-bg 50%,
|
||||
$plyr-progress-loading-bg 75%,
|
||||
transparent 75%,
|
||||
transparent);
|
||||
color: transparent;
|
||||
@ -526,7 +522,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 100px;
|
||||
margin: 0 $control-spacing 0 0;
|
||||
margin: 0 $plyr-control-spacing 0 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
@ -538,7 +534,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
}
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
margin-top: -(($volume-thumb-height - $volume-track-height) / 2);
|
||||
margin-top: -(($plyr-volume-thumb-height - $plyr-volume-track-height) / 2);
|
||||
@include volume-thumb();
|
||||
}
|
||||
|
||||
@ -552,10 +548,10 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
|
||||
// Microsoft
|
||||
&::-ms-track {
|
||||
height: $volume-track-height;
|
||||
height: $plyr-volume-track-height;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
border-width: (($volume-thumb-height - $volume-track-height) / 2) 0;
|
||||
border-width: (($plyr-volume-thumb-height - $plyr-volume-track-height) / 2) 0;
|
||||
color: transparent;
|
||||
}
|
||||
&::-ms-fill-lower,
|
||||
@ -570,13 +566,13 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
outline: 0;
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
background: $volume-thumb-bg-focus;
|
||||
background: $plyr-volume-thumb-bg-focus;
|
||||
}
|
||||
&::-moz-range-thumb {
|
||||
background: $volume-thumb-bg-focus;
|
||||
background: $plyr-volume-thumb-bg-focus;
|
||||
}
|
||||
&::-ms-thumb {
|
||||
background: $volume-thumb-bg-focus;
|
||||
background: $plyr-volume-thumb-bg-focus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -597,12 +593,12 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
// Audio specific styles
|
||||
// Position the progress within the container
|
||||
&--audio .plyr__controls {
|
||||
padding-top: ($control-spacing * 2);
|
||||
padding-top: ($plyr-control-spacing * 2);
|
||||
}
|
||||
&--audio .plyr__progress {
|
||||
bottom: auto;
|
||||
top: 0;
|
||||
background: $off-white;
|
||||
background: $plyr-off-white;
|
||||
}
|
||||
|
||||
// Full screen mode
|
||||
@ -633,28 +629,29 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
}
|
||||
|
||||
// Hide controls when playing in full screen
|
||||
&--fullscreen--hide-controls&--fullscreen-active&--playing {
|
||||
&--fullscreen-active.plyr--fullscreen--hide-controls.plyr--playing,
|
||||
&.plyr--fullscreen.plyr--fullscreen--hide-controls.plyr--playing {
|
||||
.plyr__controls {
|
||||
transform: translateY(100%) translateY($control-spacing / 2);
|
||||
transform: translateY(100%) translateY($plyr-control-spacing / 2);
|
||||
transition: transform .3s .2s ease;
|
||||
}
|
||||
.plyr__captions {
|
||||
bottom: ($plyr-control-spacing / 2);
|
||||
transition: bottom .3s .2s ease;
|
||||
}
|
||||
&.plyr--hover .plyr__controls {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.plyr__captions {
|
||||
bottom: ($control-spacing / 2);
|
||||
transition: bottom .3s .2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
// Captions
|
||||
&--fullscreen .plyr__captions,
|
||||
&.plyr--fullscreen .plyr__captions,
|
||||
&--fullscreen-active .plyr__captions,
|
||||
&--fullscreen--hide-controls&--fullscreen-active&--playing&--hover &__captions {
|
||||
&--fullscreen--hide-controls.plyr--fullscreen-active.plyr--playing.plyr--hover .plyr__captions {
|
||||
top: auto;
|
||||
bottom: 90px;
|
||||
|
||||
@media (min-width: $bp-control-split) {
|
||||
@media (min-width: $plyr-bp-control-split) {
|
||||
bottom: 60px;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user