Compare commits

...

35 Commits

Author SHA1 Message Date
34c9bdc84c Readme 2015-08-08 14:37:28 +10:00
38a206892b YouTube, Captions and Control improvements
- Controls improvements (Fixes #103)
- YouTube bug fixes (Fixes #105)
- Internationalization support (Fixes #101)
- Captions legibility improvements
2015-08-08 14:37:12 +10:00
12a737a49e Merge branch 'master' of github.com:selz/plyr 2015-08-08 11:14:19 +10:00
e7946189c6 Icon updates 2015-08-08 11:14:11 +10:00
850720d8f2 Merge pull request #106 from calvintam236/master
Fixed certain YouTube player issues
2015-08-08 11:13:03 +10:00
b130a13c8a Merge pull request #107 from ChristianPV/patch-1
Update plyr.scss - Make it work V3!
2015-08-07 11:50:01 +10:00
75c090e8b9 Update plyr.scss - Make it work V3! 2015-08-06 14:21:36 -03:00
f983f0771b Revert "Eliminated running try catch when player.type="youtube""
This reverts commit 5fcfd5fa4f.
2015-08-05 20:36:48 -07:00
9f1e5a55f4 Disabled YouTube embed player keyboard control to match with plyr's control 2015-08-05 20:33:04 -07:00
5fcfd5fa4f Eliminated running try catch when player.type="youtube" 2015-08-05 20:09:05 -07:00
e135309670 Fixed youtube video cannot seek before video started with controls 2015-08-05 19:57:24 -07:00
e97b616811 Fixed events are not fired in YouTube embed player 2015-08-05 19:55:30 -07:00
c504ecffe6 Merge pull request #104 from ChristianPV/patch-1
Update plyr.scss - Make it work V2!
2015-08-01 00:35:21 +10:00
9534db823d Update plyr.scss - Make it work V2!
Hi, thanks for accepting my previous pull request. I made this request because the variables control-color and control-color-hover weren't being set inside the mixin so i took them out and it's working now again. I hope you can merge this as it isnt completly working yet and sorry for the delay. Thanks again! :)
2015-07-31 10:59:03 -03:00
1ba1bec066 Merge branch 'master' of github.com:selz/plyr
# Conflicts:
#	src/sass/plyr.scss
2015-07-31 21:34:07 +10:00
aad4a720dc Tooltip fix for NVDA 2015-07-31 21:32:12 +10:00
a978348123 Version bump 2015-07-28 11:31:32 +10:00
00cf797c20 Restored !default and fullscreen logic in SASS 2015-07-28 11:29:49 +10:00
6b0f58dab2 Merge pull request #102 from ChristianPV/patch-1
Update plyr.scss - Make it work
2015-07-28 10:13:47 +10:00
04cf5dfda1 Update plyr.scss - Make it work
There were some things that needed to be changed for the sass preprocessor to work. There were some variables declared as @ that need to be declared with the right syntax: $. Also sass evaluation is eager, while less evaluation is _lazy_ that means in sass, mixins should be declared before they are use. I hope you can accept this change as it's currently not working. Thanks!
2015-07-27 13:04:02 -03:00
fe1989dea1 gulp 2015-07-25 22:06:13 +10:00
5d19b43888 Tooltip tweak 2015-07-25 21:35:12 +10:00
06ed345f29 YouTube quality tweak 2015-07-25 21:11:17 +10:00
e0cd34c996 Fix for omitted kind attribute on <track> (fixes #88) 2015-07-25 20:45:11 +10:00
06641d5709 Docs 2015-07-25 20:29:54 +10:00
a0d2d5cd24 Minor tweaks 2015-07-25 20:29:19 +10:00
e9cdbfb8da Safari fix (fixes #96), YouTube tweaks, docs 2015-07-25 19:51:32 +10:00
df64fdac9e Tab focus and caption position fixes (fixes #61, fixes #92) 2015-07-25 18:30:47 +10:00
4dbbbd04cc Merge pull request #99 from ChristianPV/patch-1
Update bower.json - fix sass file name
2015-07-25 10:59:56 +10:00
c9c3ee9014 Update bower.json - fix sass file name
I installed this package with bower and encountered an error while checking for existence of main bower files. I changed the filename to the correct one. Please take a look. Thanks!
2015-07-24 11:51:16 -03:00
67191c2a75 Merge branch 'master' of github.com:selz/plyr 2015-07-22 11:36:35 +10:00
8ba4522b3e Docs 2015-07-22 11:36:24 +10:00
52eaf62b58 Update readme.md 2015-07-21 12:30:41 +10:00
8d43f412ac Docs CSS 2015-07-21 10:48:31 +10:00
e9ea90f527 Update readme.md 2015-07-21 10:38:48 +10:00
35 changed files with 764 additions and 430 deletions

View File

@ -17,7 +17,7 @@
"dist/plyr.js", "dist/plyr.js",
"dist/sprite.svg", "dist/sprite.svg",
"src/less/plyr.less", "src/less/plyr.less",
"src/sass/plyr.sass", "src/sass/plyr.scss",
"src/js/plyr.js" "src/js/plyr.js"
], ],
"ignore": [ "ignore": [

View File

@ -17,6 +17,7 @@
"js": { "js": {
"docs.js": [ "docs.js": [
"docs/src/js/lib/hogan-3.0.2.mustache.js", "docs/src/js/lib/hogan-3.0.2.mustache.js",
"docs/src/js/lib/classlist.js",
"docs/dist/templates.js", "docs/dist/templates.js",
"docs/src/js/docs.js" "docs/src/js/docs.js"
] ]

View File

@ -1,7 +1,34 @@
# Changelog # Changelog
## v1.2.0 # v1.3.0
- Added YouTube support. - Internationalization support (i18n) using default controls (required markup changes to controls)
- ARIA enhancements for controls (required markup changes to controls)
- Captions legibility improvements
- YouTube bug fixes
## v1.2.6
- SASS updates and fixes (cheers @ChristianPV)
## v1.2.5
- Fix for YouTube quality (let them decide quality)
## v1.2.4
- Fix for omitted kind attribute on <track> (fixes #88)
## v1.2.3
- Fix for YouTube on iPhone or unsupported browsers (fallback to YouTube native)
- Docs tidy up
- Fullscreen for Safari fix (Fixes #96)
## v1.2.2
- Fix for :focus keyboard vs mouse (Fixes #61)
- Fix for caption positioning in full screen (Fixes #92)
## v1.2.1
- Tooltip bug fix
# v1.2.0
- Added YouTube support
## v1.1.13 ## v1.1.13
- Added icon prefix option for when using default controls - Added icon prefix option for when using default controls

View File

@ -1,10 +1,36 @@
# Controls HTML # Controls
This is the markup that is rendered for the Plyr controls. You can use the default controls or provide a customized version of markup based on your needs. This is the markup that is rendered for the Plyr controls. You can use the default controls or provide a customized version of markup based on your needs.
The demo Plyr setup uses a Hogan template. This purely to allow for localization at a later date. Check out `controls.html` in `/src/templates` to get an idea of how the default html is structured. ## Internationalization using default controls
## Requirements You can provide an `i18n` object as one of your options when initialising the plugin which we be used when rendering the controls.
### Example
```javascript
i18n: {
restart: "Restart",
rewind: "Rewind {seektime} secs",
play: "Play",
pause: "Pause",
forward: "Forward {seektime} secs",
played: "played",
buffered: "buffered",
currentTime: "Current time",
duration: "Duration",
volume: "Volume",
toggleMute: "Toggle Mute",
toggleCaptions: "Toggle Captions",
toggleFullscreen: "Toggle Fullscreen"
}
```
Note: `{seektime}` will be replaced with your configured seek time or the default. For example "Forward {seektime} secs" would render as "Forward 10 secs".
## Using custom HTML
The example on [plyr.io](http://plyr.io) setup uses a Hogan template. Check out `controls.html` in `/src/templates` to get an idea of how the default html is structured.
The classes and data attributes used in your template should match the `selectors` option. The classes and data attributes used in your template should match the `selectors` option.
@ -15,7 +41,7 @@ You need to add several placeholders to your html template that are replaced whe
You can include only the controls you need when specifying custom html. You can include only the controls you need when specifying custom html.
## Example ### Example
This is an example `html` option with all controls. This is an example `html` option with all controls.
@ -62,20 +88,18 @@ This is an example `html` option with all controls.
"</span>", "</span>",
"</span>", "</span>",
"<span class='player-controls-right'>", "<span class='player-controls-right'>",
"<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>", "<button type="button" data-player="mute">",
"<label id='mute{id}' for='mute{id}'>",
"<svg class='icon-muted'><use xlink:href='#icon-muted'></use></svg>", "<svg class='icon-muted'><use xlink:href='#icon-muted'></use></svg>",
"<svg><use xlink:href='#icon-volume'></use></svg>", "<svg><use xlink:href='#icon-volume'></use></svg>",
"<span class='sr-only'>Toggle Mute</span>", "<span class='sr-only'>Toggle Mute</span>",
"</label>", "</button>",
"<label for='volume{id}' class='sr-only'>Volume</label>", "<label for='volume{id}' class='sr-only'>Volume</label>",
"<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>", "<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>",
"<input class='sr-only' id='captions{id}' type='checkbox' data-player='captions'>", "<button type="button" data-player="captions">",
"<label for='captions{id}'>",
"<svg class='icon-captions-on'><use xlink:href='#icon-captions-on'></use></svg>", "<svg class='icon-captions-on'><use xlink:href='#icon-captions-on'></use></svg>",
"<svg><use xlink:href='#icon-captions-off'></use></svg>", "<svg><use xlink:href='#icon-captions-off'></use></svg>",
"<span class='sr-only'>Toggle Captions</span>", "<span class='sr-only'>Toggle Captions</span>",
"</label>", "</button>",
"<button type='button' data-player='fullscreen'>", "<button type='button' data-player='fullscreen'>",
"<svg class='icon-exit-fullscreen'><use xlink:href='#icon-exit-fullscreen'></use></svg>", "<svg class='icon-exit-fullscreen'><use xlink:href='#icon-exit-fullscreen'></use></svg>",
"<svg><use xlink:href='#icon-enter-fullscreen'></use></svg>", "<svg><use xlink:href='#icon-enter-fullscreen'></use></svg>",

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

2
dist/sprite.svg vendored

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

2
docs/dist/docs.css vendored

File diff suppressed because one or more lines are too long

2
docs/dist/docs.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
var templates = {}; var templates = {};
templates['controls'] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("<div class=\"player-controls\">");t.b("\n" + i);t.b(" <div class=\"player-progress\">");t.b("\n" + i);t.b(" <label for=\"seek{id}\" class=\"sr-only\">Seek</label>");t.b("\n" + i);t.b(" <input id=\"seek{id}\" class=\"player-progress-seek\" type=\"range\" min=\"0\" max=\"100\" step=\"0.5\" value=\"0\" data-player=\"seek\">");t.b("\n" + i);t.b(" <progress class=\"player-progress-played\" max=\"100\" value=\"0\">");t.b("\n" + i);t.b(" <span>0</span>% played");t.b("\n" + i);t.b(" </progress>");t.b("\n" + i);t.b(" <progress class=\"player-progress-buffer\" max=\"100\" value=\"0\">");t.b("\n" + i);t.b(" <span>0</span>% buffered");t.b("\n" + i);t.b(" </progress>");t.b("\n" + i);t.b(" </div>");t.b("\n" + i);t.b(" <span class=\"player-controls-left\">");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"restart\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-restart\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Restart</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"rewind\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-rewind\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Rewind {seektime} secs</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"play\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-play\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Play</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"pause\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-pause\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Pause</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"fast-forward\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-fast-forward\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Forward {seektime} secs</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <span class=\"player-time\">");t.b("\n" + i);t.b(" <span class=\"sr-only\">Current time</span>");t.b("\n" + i);t.b(" <span class=\"player-current-time\">00:00</span>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b(" <span class=\"player-time\">");t.b("\n" + i);t.b(" <span class=\"sr-only\">Duration</span>");t.b("\n" + i);t.b(" <span class=\"player-duration\">00:00</span>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b(" <span class=\"player-controls-right\">");t.b("\n" + i);t.b(" <input class=\"inverted sr-only\" id=\"mute{id}\" type=\"checkbox\" data-player=\"mute\">");t.b("\n" + i);t.b(" <label id=\"mute{id}\" for=\"mute{id}\">");t.b("\n" + i);t.b(" <svg class=\"icon-muted\"><use xlink:href=\"#icon-muted\"></use></svg>");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-volume\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Toggle Mute</span>");t.b("\n" + i);t.b(" </label>");t.b("\n");t.b("\n" + i);t.b(" <label for=\"volume{id}\" class=\"sr-only\">Volume</label>");t.b("\n" + i);t.b(" <input id=\"volume{id}\" class=\"player-volume\" type=\"range\" min=\"0\" max=\"10\" step=\"0.5\" value=\"0\" data-player=\"volume\">");t.b("\n");t.b("\n" + i);t.b(" <input class=\"sr-only\" id=\"captions{id}\" type=\"checkbox\" data-player=\"captions\">");t.b("\n" + i);t.b(" <label for=\"captions{id}\">");t.b("\n" + i);t.b(" <svg class=\"icon-captions-on\"><use xlink:href=\"#icon-captions-on\"></use></svg>");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-captions-off\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Toggle Captions</span>");t.b("\n" + i);t.b(" </label>");t.b("\n");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"fullscreen\">");t.b("\n" + i);t.b(" <svg class=\"icon-exit-fullscreen\"><use xlink:href=\"#icon-exit-fullscreen\"></use></svg>");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-enter-fullscreen\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Toggle Fullscreen</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b("</div>");return t.fl(); },partials: {}, subs: { }}); templates['controls'] = new Hogan.Template({code: function (c,p,i) { var t=this;t.b(i=i||"");t.b("<div class=\"player-controls\">");t.b("\n" + i);t.b(" <div class=\"player-progress\">");t.b("\n" + i);t.b(" <label for=\"seek{id}\" class=\"sr-only\">Seek</label>");t.b("\n" + i);t.b(" <input id=\"seek{id}\" class=\"player-progress-seek\" type=\"range\" min=\"0\" max=\"100\" step=\"0.5\" value=\"0\" data-player=\"seek\">");t.b("\n" + i);t.b(" <progress class=\"player-progress-played\" max=\"100\" value=\"0\">");t.b("\n" + i);t.b(" <span>0</span>% played");t.b("\n" + i);t.b(" </progress>");t.b("\n" + i);t.b(" <progress class=\"player-progress-buffer\" max=\"100\" value=\"0\">");t.b("\n" + i);t.b(" <span>0</span>% buffered");t.b("\n" + i);t.b(" </progress>");t.b("\n" + i);t.b(" </div>");t.b("\n" + i);t.b(" <span class=\"player-controls-left\">");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"restart\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-restart\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Restart</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"rewind\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-rewind\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Rewind {seektime} secs</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"play\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-play\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Play</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"pause\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-pause\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Pause</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"fast-forward\">");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-fast-forward\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Forward {seektime} secs</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <span class=\"player-time\">");t.b("\n" + i);t.b(" <span class=\"sr-only\">Current time</span>");t.b("\n" + i);t.b(" <span class=\"player-current-time\">00:00</span>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b(" <span class=\"player-time\">");t.b("\n" + i);t.b(" <span class=\"sr-only\">Duration</span>");t.b("\n" + i);t.b(" <span class=\"player-duration\">00:00</span>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b(" <span class=\"player-controls-right\">");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"mute\">");t.b("\n" + i);t.b(" <svg class=\"icon-muted\"><use xlink:href=\"#icon-muted\"></use></svg>");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-volume\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Toggle Mute</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <label for=\"volume{id}\" class=\"sr-only\">Volume</label>");t.b("\n" + i);t.b(" <input id=\"volume{id}\" class=\"player-volume\" type=\"range\" min=\"0\" max=\"10\" step=\"0.5\" value=\"0\" data-player=\"volume\">");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"captions\">");t.b("\n" + i);t.b(" <svg class=\"icon-captions-on\"><use xlink:href=\"#icon-captions-on\"></use></svg>");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-captions-off\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Toggle Captions</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" <button type=\"button\" data-player=\"fullscreen\">");t.b("\n" + i);t.b(" <svg class=\"icon-exit-fullscreen\"><use xlink:href=\"#icon-exit-fullscreen\"></use></svg>");t.b("\n" + i);t.b(" <svg><use xlink:href=\"#icon-enter-fullscreen\"></use></svg>");t.b("\n" + i);t.b(" <span class=\"sr-only\">Toggle Fullscreen</span>");t.b("\n" + i);t.b(" </button>");t.b("\n" + i);t.b(" </span>");t.b("\n" + i);t.b("</div>");return t.fl(); },partials: {}, subs: { }});

View File

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

View File

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

View File

@ -10,6 +10,7 @@ plyr.setup({
volume: 9, volume: 9,
title: "Video demo", title: "Video demo",
html: templates.controls.render({}), html: templates.controls.render({}),
tooltips: true,
captions: { captions: {
defaultActive: true defaultActive: true
}, },
@ -107,7 +108,7 @@ plyr.setup({
// Add star // Add star
function formatGitHubCount(count) { function formatGitHubCount(count) {
return "&bigstar; " + count; return "&#9733; " + count;
} }
// Check if it's in session storage first // Check if it's in session storage first

View File

@ -0,0 +1,237 @@
/*
* classList.js: Cross-browser full element.classList implementation.
* 1.1.20150312
*
* By Eli Grey, http://eligrey.com
* License: Dedicated to the public domain.
* See https://github.com/eligrey/classList.js/blob/master/LICENSE.md
*/
/*global self, document, DOMException */
/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
if ("document" in self) {
// Full polyfill for browsers with no classList support
if (!("classList" in document.createElement("_"))) {
(function (view) {
"use strict";
if (!('Element' in view)) return;
var
classListProp = "classList"
, protoProp = "prototype"
, elemCtrProto = view.Element[protoProp]
, objCtr = Object
, strTrim = String[protoProp].trim || function () {
return this.replace(/^\s+|\s+$/g, "");
}
, arrIndexOf = Array[protoProp].indexOf || function (item) {
var
i = 0
, len = this.length
;
for (; i < len; i++) {
if (i in this && this[i] === item) {
return i;
}
}
return -1;
}
// Vendors: please allow content code to instantiate DOMExceptions
, DOMEx = function (type, message) {
this.name = type;
this.code = DOMException[type];
this.message = message;
}
, checkTokenAndGetIndex = function (classList, token) {
if (token === "") {
throw new DOMEx(
"SYNTAX_ERR"
, "An invalid or illegal string was specified"
);
}
if (/\s/.test(token)) {
throw new DOMEx(
"INVALID_CHARACTER_ERR"
, "String contains an invalid character"
);
}
return arrIndexOf.call(classList, token);
}
, ClassList = function (elem) {
var
trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
, classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
, i = 0
, len = classes.length
;
for (; i < len; i++) {
this.push(classes[i]);
}
this._updateClassName = function () {
elem.setAttribute("class", this.toString());
};
}
, classListProto = ClassList[protoProp] = []
, classListGetter = function () {
return new ClassList(this);
}
;
// Most DOMException implementations don't allow calling DOMException's toString()
// on non-DOMExceptions. Error's toString() is sufficient here.
DOMEx[protoProp] = Error[protoProp];
classListProto.item = function (i) {
return this[i] || null;
};
classListProto.contains = function (token) {
token += "";
return checkTokenAndGetIndex(this, token) !== -1;
};
classListProto.add = function () {
var
tokens = arguments
, i = 0
, l = tokens.length
, token
, updated = false
;
do {
token = tokens[i] + "";
if (checkTokenAndGetIndex(this, token) === -1) {
this.push(token);
updated = true;
}
}
while (++i < l);
if (updated) {
this._updateClassName();
}
};
classListProto.remove = function () {
var
tokens = arguments
, i = 0
, l = tokens.length
, token
, updated = false
, index
;
do {
token = tokens[i] + "";
index = checkTokenAndGetIndex(this, token);
while (index !== -1) {
this.splice(index, 1);
updated = true;
index = checkTokenAndGetIndex(this, token);
}
}
while (++i < l);
if (updated) {
this._updateClassName();
}
};
classListProto.toggle = function (token, force) {
token += "";
var
result = this.contains(token)
, method = result ?
force !== true && "remove"
:
force !== false && "add"
;
if (method) {
this[method](token);
}
if (force === true || force === false) {
return force;
} else {
return !result;
}
};
classListProto.toString = function () {
return this.join(" ");
};
if (objCtr.defineProperty) {
var classListPropDesc = {
get: classListGetter
, enumerable: true
, configurable: true
};
try {
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
} catch (ex) { // IE 8 doesn't support enumerable:true
if (ex.number === -0x7FF5EC54) {
classListPropDesc.enumerable = false;
objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
}
}
} else if (objCtr[protoProp].__defineGetter__) {
elemCtrProto.__defineGetter__(classListProp, classListGetter);
}
}(self));
} else {
// There is full or partial native classList support, so just check if we need
// to normalize the add/remove and toggle APIs.
(function () {
"use strict";
var testElement = document.createElement("_");
testElement.classList.add("c1", "c2");
// Polyfill for IE 10/11 and Firefox <26, where classList.add and
// classList.remove exist but support only one argument at a time.
if (!testElement.classList.contains("c2")) {
var createMethod = function(method) {
var original = DOMTokenList.prototype[method];
DOMTokenList.prototype[method] = function(token) {
var i, len = arguments.length;
for (i = 0; i < len; i++) {
token = arguments[i];
original.call(this, token);
}
};
};
createMethod('add');
createMethod('remove');
}
testElement.classList.toggle("c3", false);
// Polyfill for IE 10 and Firefox <24, where classList.toggle does not
// support the second argument.
if (testElement.classList.contains("c3")) {
var _toggle = DOMTokenList.prototype.toggle;
DOMTokenList.prototype.toggle = function(token, force) {
if (1 in arguments && !this.contains(token) === !force) {
return force;
} else {
return _toggle.call(this, token);
}
};
}
testElement = null;
}());
}
}

View File

@ -17,7 +17,7 @@
html { html {
height: 100%; height: 100%;
font-size: 100%; font-size: 100%;
background: linear-gradient(#fff, @body-background); background: linear-gradient(#fff, @body-background) fixed;
} }
body { body {
font-family: "Avenir", "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: "Avenir", "Helvetica Neue", Helvetica, Arial, sans-serif;
@ -25,6 +25,7 @@ body {
text-align: center; text-align: center;
color: @gray; color: @gray;
.font-smoothing(on); .font-smoothing(on);
padding: 0 (@padding-base / 2);
} }
// Header // Header

View File

@ -25,6 +25,7 @@ nav {
position: relative; position: relative;
margin: 0 auto @padding-base; margin: 0 auto @padding-base;
max-width: @example-width-video; max-width: @example-width-video;
white-space: nowrap;
&::before { &::before {
content: ""; content: "";
@ -101,7 +102,8 @@ nav {
} }
} }
.btn-primary { .btn-primary {
background: linear-gradient(@link-color, darken(@link-color, 3%)); background-image: linear-gradient(@link-color, darken(@link-color, 3%));
background-color: @link-color;
border-color: darken(@link-color, 10%); border-color: darken(@link-color, 10%);
box-shadow: 0 1px 1px rgba(0,0,0, .15); box-shadow: 0 1px 1px rgba(0,0,0, .15);
text-shadow: 0 1px 1px rgba(0,0,0, .1); text-shadow: 0 1px 1px rgba(0,0,0, .1);

View File

@ -22,9 +22,22 @@
overflow: hidden; overflow: hidden;
} }
} }
// Base styles
.example-video .player { .example-video .player {
max-width: @example-width-video; max-width: @example-width-video;
video,
iframe {
border-radius: @border-radius-base;
}
iframe {
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
}
}
// Style full supported player
.example-video .player-video,
.example-video .player-youtube {
video, video,
iframe { iframe {
border-radius: @border-radius-base @border-radius-base 0 0; border-radius: @border-radius-base @border-radius-base 0 0;
@ -35,5 +48,14 @@
&-fullscreen, &-fullscreen,
&.fullscreen-active { &.fullscreen-active {
max-width: none; max-width: none;
.player-controls,
video,
iframe {
border-radius: 0;
}
iframe {
-webkit-mask-image: none;
}
} }
} }

View File

@ -40,23 +40,18 @@
</span> </span>
</span> </span>
<span class="player-controls-right"> <span class="player-controls-right">
<input class="inverted sr-only" id="mute{id}" type="checkbox" data-player="mute"> <button type="button" data-player="mute">
<label id="mute{id}" for="mute{id}">
<svg class="icon-muted"><use xlink:href="#icon-muted"></use></svg> <svg class="icon-muted"><use xlink:href="#icon-muted"></use></svg>
<svg><use xlink:href="#icon-volume"></use></svg> <svg><use xlink:href="#icon-volume"></use></svg>
<span class="sr-only">Toggle Mute</span> <span class="sr-only">Toggle Mute</span>
</label> </button>
<label for="volume{id}" class="sr-only">Volume</label> <label for="volume{id}" class="sr-only">Volume</label>
<input id="volume{id}" class="player-volume" type="range" min="0" max="10" step="0.5" value="0" data-player="volume"> <input id="volume{id}" class="player-volume" type="range" min="0" max="10" step="0.5" value="0" data-player="volume">
<button type="button" data-player="captions">
<input class="sr-only" id="captions{id}" type="checkbox" data-player="captions">
<label for="captions{id}">
<svg class="icon-captions-on"><use xlink:href="#icon-captions-on"></use></svg> <svg class="icon-captions-on"><use xlink:href="#icon-captions-on"></use></svg>
<svg><use xlink:href="#icon-captions-off"></use></svg> <svg><use xlink:href="#icon-captions-off"></use></svg>
<span class="sr-only">Toggle Captions</span> <span class="sr-only">Toggle Captions</span>
</label> </button>
<button type="button" data-player="fullscreen"> <button type="button" data-player="fullscreen">
<svg class="icon-exit-fullscreen"><use xlink:href="#icon-exit-fullscreen"></use></svg> <svg class="icon-exit-fullscreen"><use xlink:href="#icon-exit-fullscreen"></use></svg>
<svg><use xlink:href="#icon-enter-fullscreen"></use></svg> <svg><use xlink:href="#icon-enter-fullscreen"></use></svg>

View File

@ -165,11 +165,6 @@ build.templates();
build.less(bundles.docs.less, "docs"); build.less(bundles.docs.less, "docs");
build.js(bundles.docs.js, "docs"); build.js(bundles.docs.js, "docs");
// Default gulp task
gulp.task("default", function(){
run("templates", tasks.js, tasks.less, "sprite");
});
// Build all JS (inc. templates) // Build all JS (inc. templates)
gulp.task("js", function(){ gulp.task("js", function(){
run("templates", tasks.js); run("templates", tasks.js);
@ -193,6 +188,11 @@ gulp.task("watch", function () {
gulp.watch(paths.docs.src.templates, ["js"]); gulp.watch(paths.docs.src.templates, ["js"]);
}); });
// Default gulp task
gulp.task("default", function(){
run("templates", tasks.js, tasks.less, "sprite", "watch");
});
// Publish a version to CDN and docs // Publish a version to CDN and docs
// -------------------------------------------- // --------------------------------------------
@ -203,7 +203,7 @@ maxAge = 31536000, // seconds 1 year
options = { options = {
cdn: { cdn: {
headers: { headers: {
"Cache-Control": "max-age=" + maxAge + ", no-transform, public", "Cache-Control": "max-age=" + maxAge,
"Vary": "Accept-Encoding" "Vary": "Accept-Encoding"
}, },
gzippedOnly: true gzippedOnly: true

View File

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

View File

@ -9,8 +9,8 @@ A simple, accessible HTML5 media player.
We wanted a lightweight, accessible and customisable 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 customisable 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.
## Features ## Features
- **Accessible** - full support for captions and screen readers. - **Accessible** - full support for VTT captions and screen readers.
- **Lightweight** - just 6.4KB minified and gzipped. - **Lightweight** - just 8KB minified and gzipped.
- **[Customisable](#html)** - make the player look how you want with the markup you want. - **[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. - **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks.
- **Responsive** - as you'd expect these days. - **Responsive** - as you'd expect these days.
@ -18,6 +18,7 @@ We wanted a lightweight, accessible and customisable media player that just supp
- **[Embedded Video](#embeds)** - support for YouTube (Vimeo soon). - **[Embedded Video](#embeds)** - support for YouTube (Vimeo soon).
- **[API](#api)** - toggle playback, volume, seeking, and more. - **[API](#api)** - toggle playback, volume, seeking, and more.
- **[Fullscreen](#fullscreen)** - supports native fullscreen with fallback to "full window" modes. - **[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. - **No dependencies** - written in vanilla JavaScript, no jQuery required.
Oh and yes, it works with Bootstrap. Oh and yes, it works with Bootstrap.
@ -39,7 +40,7 @@ If you have any cool ideas or features, please let me know by [creating an issue
Check `docs/index.html` and `docs/dist/docs.js` for an example setup. Check `docs/index.html` and `docs/dist/docs.js` for an example setup.
**Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.2.1/plyr.js` to `https://cdn.plyr.io/1.2.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.3.0/plyr.js` to `https://cdn.plyr.io/1.3.0/plyr.js`
### Bower ### Bower
If bower is your thang, you can grab Plyr using: If bower is your thang, you can grab Plyr using:
@ -59,11 +60,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: If you want to use our CDN, you can use the following:
```html ```html
<link rel="stylesheet" href="https://cdn.plyr.io/1.2.1/plyr.css"> <link rel="stylesheet" href="https://cdn.plyr.io/1.3.0/plyr.css">
<script src="https://cdn.plyr.io/1.2.1/plyr.js"></script> <script src="https://cdn.plyr.io/1.3.0/plyr.js"></script>
``` ```
You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.2.1/sprite.svg`. You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.3.0/sprite.svg`.
### CSS ### CSS
If you want to use the default css, add the `plyr.css` file from /dist into your head, or even better use `plyr.less` or `plyr.sass` file included in `/src` in your build to save a request. If you want to use the default css, add the `plyr.css` file from /dist into your head, or even better use `plyr.less` or `plyr.sass` file included in `/src` in your build to save a request.
@ -182,6 +183,12 @@ You can pass the following options to the setup method using `plyr.setup({...})`
<td><code>["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"]</code></td> <td><code>["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"]</code></td>
<td>Toggle which control elements you would like to display when using the default controls html. If you specify a <code>html</code> option, this is redundant. The default value is to display everything.</td> <td>Toggle which control elements you would like to display when using the default controls html. If you specify a <code>html</code> option, this is redundant. The default value is to display everything.</td>
</tr> </tr>
<tr>
<td><code>i18n</code></td>
<td>Object</td>
<td><code><a href="controls.md">See controls.md</a></code></td>
<td>Used for internationalisation (i18n) of the tooltips/labels within the buttons.</td>
</tr>
<tr> <tr>
<td><code>iconPrefix</code></td> <td><code>iconPrefix</code></td>
<td>String</td> <td>String</td>
@ -360,6 +367,9 @@ Here's a list of the methods supported:
<strong>array</strong><br> <strong>array</strong><br>
<code>.source([{ src: "/path/to/video.webm", type: "video/webm", ...more attributes... }, { src: "/path/to/video.mp4", type: "video/mp4", ...more attributes... }])`</code><br> <code>.source([{ src: "/path/to/video.webm", type: "video/webm", ...more attributes... }, { src: "/path/to/video.mp4", type: "video/mp4", ...more attributes... }])`</code><br>
This will inject a child `source` element for every element in the array with the specified attributes. `src` is the only required attribute although adding `type` is recommended as it helps the browser decide which file to download and play. This will inject a child `source` element for every element in the array with the specified attributes. `src` is the only required attribute although adding `type` is recommended as it helps the browser decide which file to download and play.
<br><br>
<strong>YouTube</strong><br>
Currently this API method only accepts a YouTube ID when used with a YouTube player. I will add URL support soon, along with being able to swap between types (e.g. YouTube to Audio or Video and vice versa.)
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr // Plyr
// plyr.js v1.2.1 // plyr.js v1.3.0
// https://github.com/selz/plyr // https://github.com/selz/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
@ -59,7 +59,7 @@
loading: "loading", loading: "loading",
tooltip: "player-tooltip", tooltip: "player-tooltip",
hidden: "sr-only", hidden: "sr-only",
hover: "hover", hover: "player-hover",
captions: { captions: {
enabled: "captions-enabled", enabled: "captions-enabled",
active: "captions-active" active: "captions-active"
@ -83,7 +83,21 @@
key: "plyr_volume" key: "plyr_volume"
}, },
controls: ["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"], controls: ["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"],
onSetup: function() {} i18n: {
restart: "Restart",
rewind: "Rewind {seektime} secs",
play: "Play",
pause: "Pause",
forward: "Forward {seektime} secs",
played: "played",
buffered: "buffered",
currentTime: "Current time",
duration: "Duration",
volume: "Volume",
toggleMute: "Toggle Mute",
toggleCaptions: "Toggle Captions",
toggleFullscreen: "Toggle Fullscreen"
}
}; };
// Build the default HTML // Build the default HTML
@ -95,10 +109,10 @@
"<label for='seek{id}' class='sr-only'>Seek</label>", "<label for='seek{id}' class='sr-only'>Seek</label>",
"<input id='seek{id}' class='player-progress-seek' type='range' min='0' max='100' step='0.5' value='0' data-player='seek'>", "<input id='seek{id}' class='player-progress-seek' type='range' min='0' max='100' step='0.5' value='0' data-player='seek'>",
"<progress class='player-progress-played' max='100' value='0'>", "<progress class='player-progress-played' max='100' value='0'>",
"<span>0</span>% played", "<span>0</span>% " + config.i18n.played,
"</progress>", "</progress>",
"<progress class='player-progress-buffer' max='100' value='0'>", "<progress class='player-progress-buffer' max='100' value='0'>",
"<span>0</span>% buffered", "<span>0</span>% " + config.i18n.buffered,
"</progress>", "</progress>",
"</div>", "</div>",
"<span class='player-controls-left'>"]; "<span class='player-controls-left'>"];
@ -108,7 +122,7 @@
html.push( html.push(
"<button type='button' data-player='restart'>", "<button type='button' data-player='restart'>",
"<svg><use xlink:href='#" + config.iconPrefix + "-restart'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-restart'></use></svg>",
"<span class='sr-only'>Restart</span>", "<span class='sr-only'>" + config.i18n.restart + "</span>",
"</button>" "</button>"
); );
} }
@ -118,7 +132,7 @@
html.push( html.push(
"<button type='button' data-player='rewind'>", "<button type='button' data-player='rewind'>",
"<svg><use xlink:href='#" + config.iconPrefix + "-rewind'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-rewind'></use></svg>",
"<span class='sr-only'>Rewind {seektime} secs</span>", "<span class='sr-only'>" + config.i18n.rewind + "</span>",
"</button>" "</button>"
); );
} }
@ -128,11 +142,11 @@
html.push( html.push(
"<button type='button' data-player='play'>", "<button type='button' data-player='play'>",
"<svg><use xlink:href='#" + config.iconPrefix + "-play'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-play'></use></svg>",
"<span class='sr-only'>Play</span>", "<span class='sr-only'>" + config.i18n.play + "</span>",
"</button>", "</button>",
"<button type='button' data-player='pause'>", "<button type='button' data-player='pause'>",
"<svg><use xlink:href='#" + config.iconPrefix + "-pause'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-pause'></use></svg>",
"<span class='sr-only'>Pause</span>", "<span class='sr-only'>" + config.i18n.pause + "</span>",
"</button>" "</button>"
); );
} }
@ -142,7 +156,7 @@
html.push( html.push(
"<button type='button' data-player='fast-forward'>", "<button type='button' data-player='fast-forward'>",
"<svg><use xlink:href='#" + config.iconPrefix + "-fast-forward'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-fast-forward'></use></svg>",
"<span class='sr-only'>Forward {seektime} secs</span>", "<span class='sr-only'>" + config.i18n.forward + "</span>",
"</button>" "</button>"
); );
} }
@ -151,7 +165,7 @@
if(_inArray(config.controls, "current-time")) { if(_inArray(config.controls, "current-time")) {
html.push( html.push(
"<span class='player-time'>", "<span class='player-time'>",
"<span class='sr-only'>Current time</span>", "<span class='sr-only'>" + config.i18n.currentTime + "</span>",
"<span class='player-current-time'>00:00</span>", "<span class='player-current-time'>00:00</span>",
"</span>" "</span>"
); );
@ -161,7 +175,7 @@
if(_inArray(config.controls, "duration")) { if(_inArray(config.controls, "duration")) {
html.push( html.push(
"<span class='player-time'>", "<span class='player-time'>",
"<span class='sr-only'>Duration</span>", "<span class='sr-only'>" + config.i18n.duration + "</span>",
"<span class='player-duration'>00:00</span>", "<span class='player-duration'>00:00</span>",
"</span>" "</span>"
); );
@ -176,19 +190,18 @@
// Toggle mute button // Toggle mute button
if(_inArray(config.controls, "mute")) { if(_inArray(config.controls, "mute")) {
html.push( html.push(
"<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>", "<button type='button' data-player='mute'>",
"<label id='mute{id}' for='mute{id}'>",
"<svg class='icon-muted'><use xlink:href='#" + config.iconPrefix + "-muted'></use></svg>", "<svg class='icon-muted'><use xlink:href='#" + config.iconPrefix + "-muted'></use></svg>",
"<svg><use xlink:href='#" + config.iconPrefix + "-volume'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-volume'></use></svg>",
"<span class='sr-only'>Toggle Mute</span>", "<span class='sr-only'>" + config.i18n.toggleMute + "</span>",
"</label>" "</button>"
); );
} }
// Volume range control // Volume range control
if(_inArray(config.controls, "volume")) { if(_inArray(config.controls, "volume")) {
html.push( html.push(
"<label for='volume{id}' class='sr-only'>Volume</label>", "<label for='volume{id}' class='sr-only'>" + config.i18n.volume + "</label>",
"<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>" "<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>"
); );
} }
@ -196,12 +209,11 @@
// Toggle captions button // Toggle captions button
if(_inArray(config.controls, "captions")) { if(_inArray(config.controls, "captions")) {
html.push( html.push(
"<input class='sr-only' id='captions{id}' type='checkbox' data-player='captions'>", "<button type='button' data-player='captions'>",
"<label for='captions{id}'>",
"<svg class='icon-captions-on'><use xlink:href='#" + config.iconPrefix + "-captions-on'></use></svg>", "<svg class='icon-captions-on'><use xlink:href='#" + config.iconPrefix + "-captions-on'></use></svg>",
"<svg><use xlink:href='#" + config.iconPrefix + "-captions-off'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-captions-off'></use></svg>",
"<span class='sr-only'>Toggle Captions</span>", "<span class='sr-only'>" + config.i18n.toggleCaptions + "</span>",
"</label>" "</button>"
); );
} }
@ -211,7 +223,7 @@
"<button type='button' data-player='fullscreen'>", "<button type='button' data-player='fullscreen'>",
"<svg class='icon-exit-fullscreen'><use xlink:href='#" + config.iconPrefix + "-exit-fullscreen'></use></svg>", "<svg class='icon-exit-fullscreen'><use xlink:href='#" + config.iconPrefix + "-exit-fullscreen'></use></svg>",
"<svg><use xlink:href='#" + config.iconPrefix + "-enter-fullscreen'></use></svg>", "<svg><use xlink:href='#" + config.iconPrefix + "-enter-fullscreen'></use></svg>",
"<span class='sr-only'>Toggle Fullscreen</span>", "<span class='sr-only'>" + config.i18n.toggleFullscreen + "</span>",
"</button>" "</button>"
); );
} }
@ -478,18 +490,15 @@
element.dispatchEvent(fauxEvent); element.dispatchEvent(fauxEvent);
} }
// Toggle checkbox // Toggle aria-pressed state on a toggle button
function _toggleCheckbox(event) { function _toggleState(target, state) {
// Only listen for return key // Get state
if(event.keyCode && event.keyCode != 13) { state = (typeof state === "boolean" ? state : !target.getAttribute("aria-pressed"));
return true;
}
// Toggle the checkbox // Set the attribute on target
event.target.checked = !event.target.checked; target.setAttribute("aria-pressed", state);
// Trigger change event return state;
_triggerEvent(event.target, "change");
} }
// Get percentage // Get percentage
@ -529,12 +538,12 @@
}, },
browserPrefixes = "webkit moz o ms khtml".split(" "); browserPrefixes = "webkit moz o ms khtml".split(" ");
// check for native support // Check for native support
if (typeof document.cancelFullScreen != "undefined") { if (typeof document.cancelFullScreen != "undefined") {
fullscreen.supportsFullScreen = true; fullscreen.supportsFullScreen = true;
} }
else { else {
// check for fullscreen support by vendor prefix // Check for fullscreen support by vendor prefix
for (var i = 0, il = browserPrefixes.length; i < il; i++ ) { for (var i = 0, il = browserPrefixes.length; i < il; i++ ) {
fullscreen.prefix = browserPrefixes[i]; fullscreen.prefix = browserPrefixes[i];
@ -551,12 +560,6 @@
} }
} }
// Safari doesn't support the ALLOW_KEYBOARD_INPUT flag (for security) so set it to not supported
// https://bugs.webkit.org/show_bug.cgi?id=121496
if(fullscreen.prefix === "webkit" && !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)) {
fullscreen.supportsFullScreen = false;
}
// Update methods to do something useful // Update methods to do something useful
if (fullscreen.supportsFullScreen) { if (fullscreen.supportsFullScreen) {
// Yet again Microsoft awesomeness, // Yet again Microsoft awesomeness,
@ -565,9 +568,8 @@
fullscreen.isFullScreen = function(element) { fullscreen.isFullScreen = function(element) {
if(typeof element == "undefined") { if(typeof element == "undefined") {
element = document; element = document.body;
} }
switch (this.prefix) { switch (this.prefix) {
case "": case "":
return document.fullscreenElement == element; return document.fullscreenElement == element;
@ -578,7 +580,10 @@
} }
}; };
fullscreen.requestFullScreen = function(element) { fullscreen.requestFullScreen = function(element) {
return (this.prefix === "") ? element.requestFullScreen() : element[this.prefix + (this.prefix == "ms" ? "RequestFullscreen" : "RequestFullScreen")](this.prefix === "webkit" ? element.ALLOW_KEYBOARD_INPUT : null); if(typeof element == "undefined") {
element = document.body;
}
return (this.prefix === "") ? element.requestFullScreen() : element[this.prefix + (this.prefix == "ms" ? "RequestFullscreen" : "RequestFullScreen")]();
}; };
fullscreen.cancelFullScreen = function() { fullscreen.cancelFullScreen = function() {
return (this.prefix === "") ? document.cancelFullScreen() : document[this.prefix + (this.prefix == "ms" ? "ExitFullscreen" : "CancelFullScreen")](); return (this.prefix === "") ? document.cancelFullScreen() : document[this.prefix + (this.prefix == "ms" ? "ExitFullscreen" : "CancelFullScreen")]();
@ -641,7 +646,7 @@
player.currentCaption = player.captions[player.subcount][1]; player.currentCaption = player.captions[player.subcount][1];
// Render the caption // Render the caption
player.captionsContainer.innerHTML = player.currentCaption; player.captionsContainer.innerHTML = player.currentCaption.trim();
} }
else { else {
// Clear the caption // Clear the caption
@ -660,7 +665,7 @@
if (config.captions.defaultActive) { if (config.captions.defaultActive) {
_toggleClass(player.container, config.classes.captions.active, true); _toggleClass(player.container, config.classes.captions.active, true);
player.buttons.captions.checked = true; _toggleState(player.buttons.captions, true);
} }
} }
@ -799,15 +804,15 @@
} }
} }
// Setup aria attributes // Setup aria attribute for play
function _setupAria() { function _setupPlayAria() {
// If there's no play button, bail // If there's no play button, bail
if(!player.buttons.play) { if(!player.buttons.play) {
return; return;
} }
// Find the current text // Find the current text
var label = player.buttons.play.innerText || "Play"; var label = player.buttons.play.innerText || config.i18n.play;
// If there's a media title set, use that for the label // If there's a media title set, use that for the label
if (typeof(config.title) !== "undefined" && config.title.length) { if (typeof(config.title) !== "undefined" && config.title.length) {
@ -852,12 +857,12 @@
// Cache the container // Cache the container
player.videoContainer = wrapper; player.videoContainer = wrapper;
} }
}
// YouTube // YouTube
if(player.type == "youtube") { if(player.type == "youtube") {
_setupYouTube(player.media.getAttribute("data-video-id")); _setupYouTube(player.media.getAttribute("data-video-id"));
} }
}
// Autoplay // Autoplay
if(player.media.getAttribute("autoplay") !== null) { if(player.media.getAttribute("autoplay") !== null) {
@ -910,17 +915,17 @@
videoId: id, videoId: id,
playerVars: { playerVars: {
autoplay: 0, autoplay: 0,
controls: 0, controls: (player.supported.full ? 0 : 1),
vq: "hd720",
rel: 0, rel: 0,
showinfo: 0, showinfo: 0,
iv_load_policy: 3, iv_load_policy: 3,
cc_lang_pref: "en", cc_lang_pref: "en",
wmode: "transparent", wmode: "transparent",
modestbranding: 1 modestbranding: 1,
disablekb: 1
}, },
events: { events: {
onReady: function(event) { "onReady": function(event) {
// Get the instance // Get the instance
var instance = event.target; var instance = event.target;
@ -929,7 +934,7 @@
player.media.pause = function() { instance.pauseVideo(); }; player.media.pause = function() { instance.pauseVideo(); };
player.media.stop = function() { instance.stopVideo(); }; player.media.stop = function() { instance.stopVideo(); };
player.media.duration = instance.getDuration(); player.media.duration = instance.getDuration();
player.media.paused = (instance.getPlayerState() == 2); player.media.paused = true;
player.media.currentTime = instance.getCurrentTime(); player.media.currentTime = instance.getCurrentTime();
player.media.muted = instance.isMuted(); player.media.muted = instance.isMuted();
@ -953,6 +958,7 @@
} }
}, 200); }, 200);
if(player.supported.full) {
// Only setup controls once // Only setup controls once
if(!player.container.querySelectorAll(config.selectors.controls).length) { if(!player.container.querySelectorAll(config.selectors.controls).length) {
_setupInterface(); _setupInterface();
@ -962,8 +968,9 @@
if(config.displayDuration) { if(config.displayDuration) {
_displayDuration(); _displayDuration();
} }
}
}, },
onStateChange: function(event) { "onStateChange": function(event) {
// Get the instance // Get the instance
var instance = event.target; var instance = event.target;
@ -1012,10 +1019,10 @@
function _setupCaptions() { function _setupCaptions() {
if(player.type === "video") { if(player.type === "video") {
// Inject the container // Inject the container
player.videoContainer.insertAdjacentHTML("afterbegin", "<div class='" + config.selectors.captions.replace(".", "") + "'></div>"); player.videoContainer.insertAdjacentHTML("afterbegin", "<div class='" + config.selectors.captions.replace(".", "") + "' aria-live='assertive'><span></span></div>");
// Cache selector // Cache selector
player.captionsContainer = _getElement(config.selectors.captions); player.captionsContainer = _getElement(config.selectors.captions).querySelector("span");
// Determine if HTML5 textTracks is supported // Determine if HTML5 textTracks is supported
player.usingTextTracks = false; player.usingTextTracks = false;
@ -1030,8 +1037,8 @@
for (var i = 0; i < children.length; i++) { for (var i = 0; i < children.length; i++) {
if (children[i].nodeName.toLowerCase() === "track") { if (children[i].nodeName.toLowerCase() === "track") {
kind = children[i].getAttribute("kind"); kind = children[i].kind;
if (kind === "captions") { if (kind === "captions" || kind === "subtitles") {
captionSrc = children[i].getAttribute("src"); captionSrc = children[i].getAttribute("src");
} }
} }
@ -1083,14 +1090,14 @@
for (var y=0; y < tracks.length; y++) { for (var y=0; y < tracks.length; y++) {
var track = tracks[y]; var track = tracks[y];
if (track.kind === "captions") { if (track.kind === "captions" || track.kind === "subtitles") {
_on(track, "cuechange", function() { _on(track, "cuechange", function() {
// Clear container // Clear container
player.captionsContainer.innerHTML = ""; player.captionsContainer.innerHTML = "";
// Display a cue, if there is one // Display a cue, if there is one
if (this.activeCues[0] && this.activeCues[0].hasOwnProperty("text")) { if (this.activeCues[0] && this.activeCues[0].hasOwnProperty("text")) {
player.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML()); player.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim());
} }
}); });
} }
@ -1172,6 +1179,9 @@
_log("Fullscreen not supported and fallback disabled."); _log("Fullscreen not supported and fallback disabled.");
} }
// Toggle state
_toggleState(player.buttons.fullscreen, false);
// Set control hide class hook // Set control hide class hook
if(config.fullscreen.hideControls) { if(config.fullscreen.hideControls) {
_toggleClass(player.container, config.classes.fullscreen.hideControls, true); _toggleClass(player.container, config.classes.fullscreen.hideControls, true);
@ -1226,7 +1236,8 @@
// Seek to time // Seek to time
// The input parameter can be an event or a number // The input parameter can be an event or a number
function _seek(input) { function _seek(input) {
var targetTime = 0; var targetTime = 0,
paused = player.media.paused;
// Explicit position // Explicit position
if (typeof input === "number") { if (typeof input === "number") {
@ -1256,7 +1267,11 @@
// YouTube // YouTube
if(player.type == "youtube") { if(player.type == "youtube") {
player.embed.seekTo(player.media.currentTime); player.embed.seekTo(targetTime);
if(paused) {
_pause();
}
// Trigger timeupdate // Trigger timeupdate
_triggerEvent(player.media, "timeupdate"); _triggerEvent(player.media, "timeupdate");
@ -1316,13 +1331,16 @@
// Set class hook // Set class hook
_toggleClass(player.container, config.classes.fullscreen.active, player.isFullscreen); _toggleClass(player.container, config.classes.fullscreen.active, player.isFullscreen);
// Set button state
_toggleState(player.buttons.fullscreen, player.isFullscreen);
// Toggle controls visibility based on mouse movement and location // Toggle controls visibility based on mouse movement and location
var hoverTimer, isMouseOver = false; var hoverTimer, isMouseOver = false;
// Show the player controls // Show the player controls
function _showControls() { function _showControls() {
// Set shown class // Set shown class
_toggleClass(player.controls, config.classes.hover, true); _toggleClass(player.container, config.classes.hover, true);
// Clear timer every movement // Clear timer every movement
window.clearTimeout(hoverTimer); window.clearTimeout(hoverTimer);
@ -1330,7 +1348,7 @@
// If the mouse is not over the controls, set a timeout to hide them // If the mouse is not over the controls, set a timeout to hide them
if(!isMouseOver) { if(!isMouseOver) {
hoverTimer = window.setTimeout(function() { hoverTimer = window.setTimeout(function() {
_toggleClass(player.controls, config.classes.hover, false); _toggleClass(player.container, config.classes.hover, false);
}, 2000); }, 2000);
} }
} }
@ -1401,10 +1419,13 @@
// Mute // Mute
function _toggleMute(muted) { function _toggleMute(muted) {
// If the method is called without parameter, toggle based on current value // If the method is called without parameter, toggle based on current value
if(typeof muted === "undefined") { if(typeof muted !== "boolean") {
muted = !player.media.muted; muted = !player.media.muted;
} }
// Set button state
_toggleState(player.buttons.mute, muted);
// Set mute on the player // Set mute on the player
player.media.muted = muted; player.media.muted = muted;
@ -1437,7 +1458,7 @@
// Update checkbox for mute state // Update checkbox for mute state
if(player.supported.full && player.buttons.mute) { if(player.supported.full && player.buttons.mute) {
player.buttons.mute.checked = (volume === 0); _toggleState(player.buttons.mute, (volume === 0));
} }
} }
@ -1449,11 +1470,14 @@
} }
// If the method is called without parameter, toggle based on current value // If the method is called without parameter, toggle based on current value
if(typeof show === "undefined") { if(typeof show !== "boolean") {
show = (player.container.className.indexOf(config.classes.captions.active) === -1); show = (player.container.className.indexOf(config.classes.captions.active) === -1);
player.buttons.captions.checked = show;
} }
// Toggle state
_toggleState(player.buttons.captions, show);
// Add class hook
_toggleClass(player.container, config.classes.captions.active, show); _toggleClass(player.container, config.classes.captions.active, show);
} }
@ -1675,6 +1699,34 @@
// IE doesn't support input event, so we fallback to change // IE doesn't support input event, so we fallback to change
var inputEvent = (player.browser.name == "IE" ? "change" : "input"); var inputEvent = (player.browser.name == "IE" ? "change" : "input");
// Detect tab focus
function checkFocus() {
var focused = document.activeElement;
if (!focused || focused == document.body) {
focused = null;
}
else if (document.querySelector){
focused = document.querySelector(":focus");
}
for (var button in player.buttons) {
var element = player.buttons[button];
_toggleClass(element, "tab-focus", (element === focused));
}
}
_on(window, "keyup", function(event) {
var code = (event.keyCode ? event.keyCode : event.which);
if(code == 9) { checkFocus(); }
});
for (var button in player.buttons) {
var element = player.buttons[button];
_on(element, "blur", function() {
_toggleClass(element, "tab-focus", false);
});
}
// Play // Play
_on(player.buttons.play, "click", function() { _on(player.buttons.play, "click", function() {
_play(); _play();
@ -1705,9 +1757,7 @@
}); });
// Mute // Mute
_on(player.buttons.mute, "change", function() { _on(player.buttons.mute, "click", _toggleMute);
_toggleMute(this.checked);
});
// Fullscreen // Fullscreen
_on(player.buttons.fullscreen, "click", _toggleFullscreen); _on(player.buttons.fullscreen, "click", _toggleFullscreen);
@ -1727,9 +1777,7 @@
_on(player.media, "loadedmetadata", _displayDuration); _on(player.media, "loadedmetadata", _displayDuration);
// Captions // Captions
_on(player.buttons.captions, "change", function() { _on(player.buttons.captions, "click", _toggleCaptions);
_toggleCaptions(this.checked);
});
// Handle the media finishing // Handle the media finishing
_on(player.media, "ended", function() { _on(player.media, "ended", function() {
@ -1754,9 +1802,6 @@
// Loading // Loading
_on(player.media, "waiting canplay seeked", _checkLoading); _on(player.media, "waiting canplay seeked", _checkLoading);
// Toggle checkboxes on return key (as they look like buttons)
_on(player.checkboxes, "keyup", _toggleCheckbox);
// Click video // Click video
if(player.type === "video" && config.click) { if(player.type === "video" && config.click) {
_on(player.videoContainer, "click", function() { _on(player.videoContainer, "click", function() {
@ -1874,7 +1919,7 @@
} }
// Set up aria-label for Play button with the title option // Set up aria-label for Play button with the title option
_setupAria(); _setupPlayAria();
} }
// Successful setup // Successful setup
@ -1956,7 +2001,7 @@
case "youtube": case "youtube":
basic = true; basic = true;
full = !oldIE; full = (!oldIE && !iPhone);
break; break;
default: default:
@ -2000,8 +2045,10 @@
element.plyr = (Object.keys(instance).length ? instance : false); element.plyr = (Object.keys(instance).length ? instance : false);
// Callback // Callback
if(typeof config.onSetup === "function") {
config.onSetup.apply(element.plyr); config.onSetup.apply(element.plyr);
} }
}
// Add to return array even if it's already setup // Add to return array even if it's already setup
players.push(element.plyr); players.push(element.plyr);

View File

@ -17,7 +17,11 @@
// Font sizes // Font sizes
@font-size-small: 14px; @font-size-small: 14px;
@font-size-base: 16px; @font-size-base: 16px;
@font-size-large: ceil((@font-size-base * 1.5));
// 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);
// Controls // Controls
@control-spacing: 10px; @control-spacing: 10px;
@ -28,6 +32,7 @@
// Tooltips // Tooltips
@tooltip-bg: @controls-bg; @tooltip-bg: @controls-bg;
@tooltip-border-color: @off-white;
@tooltip-color: @control-color; @tooltip-color: @control-color;
@tooltip-padding: @control-spacing; @tooltip-padding: @control-spacing;
@tooltip-arrow-size: 5px; @tooltip-arrow-size: 5px;
@ -188,26 +193,31 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
padding: 20px; padding: (@control-spacing * 2) (@control-spacing * 2) (@control-spacing * 3);
min-height: 2.5em;
color: #fff; color: #fff;
font-size: @font-size-base; font-size: @font-size-captions-base;
font-weight: 600;
text-shadow:
-1px -1px 0 @gray,
1px -1px 0 @gray,
-1px 1px 0 @gray,
1px 1px 0 @gray;
text-align: center; text-align: center;
.font-smoothing(); .font-smoothing();
span {
border-radius: 2px;
padding: 3px 10px;
background: rgba(0,0,0, .9);
}
span:empty {
display: none;
}
@media (min-width: @bp-captions-large) { @media (min-width: @bp-captions-large) {
font-size: @font-size-large; font-size: @font-size-captions-medium;
} }
} }
&.captions-active &-captions { &.captions-active &-captions {
display: block; display: block;
} }
&.fullscreen-active &-captions {
font-size: @font-size-captions-large;
}
// Player controls // Player controls
&-controls { &-controls {
@ -235,16 +245,19 @@
} }
} }
input + label, // Buttons
button { button {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
margin: 0 2px; margin: 0 2px;
padding: (@control-spacing / 2) @control-spacing; padding: (@control-spacing / 2) @control-spacing;
overflow: hidden;
transition: background .3s ease, color .3s ease, opacity .3s ease; border: 0;
background: transparent;
border-radius: 3px; border-radius: 3px;
cursor: pointer; cursor: pointer;
color: @control-color;
transition: background .3s ease, color .3s ease, opacity .3s ease;
svg { svg {
width: 18px; width: 18px;
@ -253,41 +266,27 @@
fill: currentColor; fill: currentColor;
transition: fill .3s ease; transition: fill .3s ease;
} }
}
input + label,
.inverted:checked + label {
opacity: .5;
}
button,
.inverted + label,
input:checked + label {
color: @control-color;
opacity: 1;
}
button {
border: 0;
background: transparent;
overflow: hidden;
}
// Specificity for overriding .inverted // Hover and tab focus
button:focus, &.tab-focus,
button:hover, &:hover {
[type="checkbox"]:focus + label,
[type="checkbox"] + label:hover {
background: @control-bg-hover; background: @control-bg-hover;
color: @control-color-hover; color: @control-color-hover;
opacity: 1;
} }
button:focus, // Default focus
input:focus + label { &:focus {
outline: 0; outline: 0;
} }
}
// Hide toggle icons by default
.icon-exit-fullscreen, .icon-exit-fullscreen,
.icon-muted, .icon-muted,
.icon-captions-on { .icon-captions-on {
display: none; display: none;
} }
// Player time
.player-time { .player-time {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
@ -308,7 +307,7 @@
// Add a slash in before // Add a slash in before
&::before { &::before {
content: "\2044"; content: '\2044';
margin-right: @control-spacing; margin-right: @control-spacing;
} }
} }
@ -316,7 +315,6 @@
// Tooltips // Tooltips
&-tooltip { &-tooltip {
visibility: hidden;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
bottom: 100%; bottom: 100%;
@ -325,6 +323,7 @@
opacity: 0; opacity: 0;
background: @tooltip-bg; background: @tooltip-bg;
border: 1px solid @tooltip-border-color;
border-radius: @tooltip-radius; border-radius: @tooltip-radius;
color: @tooltip-color; color: @tooltip-color;
font-size: @font-size-small; font-size: @font-size-small;
@ -335,30 +334,27 @@
transform-origin: 50% 100%; transform-origin: 50% 100%;
transition: transform .2s .1s ease, opacity .2s .1s ease; transition: transform .2s .1s ease, opacity .2s .1s ease;
// Arrow
&::after { &::after {
content: ""; content: '';
display: block;
position: absolute; position: absolute;
z-index: 1;
top: 100%;
left: 50%; left: 50%;
bottom: -@tooltip-arrow-size; display: block;
margin-left: -@tooltip-arrow-size; width: 10px;
width: 0; height: 10px;
height: 0; background: @tooltip-bg;
transition: inherit; transform: translate(-50%, -50%) rotate(45deg) translateY(1px);
border-style: solid; border: 1px solid @tooltip-border-color;
border-width: @tooltip-arrow-size @tooltip-arrow-size 0 @tooltip-arrow-size; border-width: 0 1px 1px 0;
border-color: @controls-bg transparent transparent;
} }
} }
label:hover .player-tooltip,
input:focus + label .player-tooltip,
button:hover .player-tooltip, button:hover .player-tooltip,
button:focus .player-tooltip { button.tab-focus:focus .player-tooltip {
visibility: visible;
opacity: 1; opacity: 1;
transform: translate(-50%, 0) scale(1); transform: translate(-50%, 0) scale(1);
} }
label:hover .player-tooltip,
button:hover .player-tooltip { button:hover .player-tooltip {
z-index: 3; z-index: 3;
} }
@ -376,7 +372,7 @@
&-buffer[value], &-buffer[value],
&-played[value], &-played[value],
&-seek[type=range] { &-seek[type='range'] {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@ -416,7 +412,7 @@
// Seek control // Seek control
// <input[type='range']> element // <input[type='range']> element
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
&-seek[type=range] { &-seek[type='range'] {
z-index: 4; z-index: 4;
cursor: pointer; cursor: pointer;
outline: 0; outline: 0;
@ -491,7 +487,7 @@
// Volume control // Volume control
// <input[type='range']> element // <input[type='range']> element
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
&-volume[type=range] { &-volume[type='range'] {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
-webkit-appearance: none; -webkit-appearance: none;
@ -557,7 +553,6 @@
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
&.ios &-volume, &.ios &-volume,
&.ios [data-player='mute'], &.ios [data-player='mute'],
&.ios [data-player='mute'] + label,
&-audio.ios &-controls-right { &-audio.ios &-controls-right {
display: none; display: none;
} }
@ -596,15 +591,6 @@
.player-video-wrapper { .player-video-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;
.player-captions {
top: auto;
bottom: 90px;
@media (min-width: @bp-control-split) {
bottom: 60px;
}
}
} }
.player-controls { .player-controls {
position: absolute; position: absolute;
@ -614,13 +600,29 @@
} }
// Hide controls when playing in full screen // Hide controls when playing in full screen
&.fullscreen-hide-controls.playing .player-controls { &.fullscreen-hide-controls.playing {
.player-controls {
transform: translateY(100%) translateY(@control-spacing / 2); transform: translateY(100%) translateY(@control-spacing / 2);
transition: transform .3s .2s ease; transition: transform .3s .2s ease;
}
&.hover { &.player-hover .player-controls {
transform: translateY(0); transform: translateY(0);
} }
.player-captions {
bottom: (@control-spacing / 2);
transition: bottom .3s .2s ease;
}
}
// Captions
.player-captions,
&.fullscreen-hide-controls.playing.player-hover .player-captions {
top: auto;
bottom: 90px;
@media (min-width: @bp-control-split) {
bottom: 60px;
}
} }
} }
@ -637,15 +639,11 @@
// Some options are hidden by default // Some options are hidden by default
[data-player='captions'], [data-player='captions'],
[data-player='captions'] + label, [data-player='fullscreen'] {
[data-player='fullscreen'],
[data-player='fullscreen'] + label {
display: none; display: none;
} }
&.captions-enabled [data-player='captions'], &.captions-enabled [data-player='captions'],
&.captions-enabled [data-player='captions'] + label, &.fullscreen-enabled [data-player='fullscreen'] {
&.fullscreen-enabled [data-player='fullscreen'],
&.fullscreen-enabled [data-player='fullscreen'] + label {
display: inline-block; display: inline-block;
} }
} }

View File

@ -17,14 +17,30 @@ $off-white: #D6DADD !default;
// Font sizes // Font sizes
$font-size-small: 14px !default; $font-size-small: 14px !default;
$font-size-base: 16px !default; $font-size-base: 16px !default;
$font-size-large: ceil(($font-size-base * 1.5)) !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;
// Controls // Controls
$control-spacing: 10px !default; $control-spacing: 10px !default;
$controls-bg: #fff !default; $controls-bg: #fff !default;
$control-bg-hover: @blue !default; $control-bg-hover: $blue !default;
.contrast-control-color($controls-bg); $control-color: null !default;
.contrast-control-color-hover($control-bg-hover); $control-color-hover: null !default;
// Contrast
@if lightness($controls-bg) >= 65% {
$control-color: $gray-light;
} @else {
$control-color: $gray-lighter;
}
@if lightness($control-bg-hover) >= 65% {
$control-color-hover: $gray;
} @else {
$control-color-hover: #fff;
}
// Tooltips // Tooltips
$tooltip-bg: $controls-bg !default; $tooltip-bg: $controls-bg !default;
@ -59,27 +75,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
to { background-position: $progress-loading-size 0; } to { background-position: $progress-loading-size 0; }
} }
// Mixins
// -------------------------------
// Contrast
@mixin contrast-control-color($color: "") {
@if (lightness($color) >= 65%) {
$control-color: $gray-light;
}
@else if(lightness(@color) < 65%) {
$control-color: $gray-lighter;
}
}
@mixin contrast-control-color-hover($color: "") {
@if (lightness($color) >= 65%) {
$control-color-hover: $gray;
}
@else if (lightness($color) < 65%) {
$control-color-hover: #fff;
}
}
// Font smoothing // Font smoothing
@mixin font-smoothing($mode: on) @mixin font-smoothing($mode: on)
{ {
@ -98,7 +93,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
{ {
zoom: 1; zoom: 1;
&:before, &:before,
&:after { content: ""; display: table; } &:after { content: ''; display: table; }
&:after { clear: both; } &:after { clear: both; }
} }
// Tab focus styles // Tab focus styles
@ -108,7 +103,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
outline-offset: 0; outline-offset: 0;
} }
// Range mixins // <input type="range"> styling
@mixin volume-thumb() @mixin volume-thumb()
{ {
height: $volume-thumb-height; height: $volume-thumb-height;
@ -179,6 +174,21 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
vertical-align: middle; vertical-align: middle;
} }
// For embeds
&-video-embed {
padding-bottom: 56.25%; /* 16:9 */
height: 0;
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
}
// Captions // Captions
&-captions { &-captions {
display: none; display: none;
@ -186,26 +196,31 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
padding: 20px; padding: ($control-spacing * 2) ($control-spacing * 2) ($control-spacing * 3);
min-height: 2.5em;
color: #fff; color: #fff;
font-size: $font-size-base; font-size: $font-size-captions-base;
font-weight: 600;
text-shadow:
-1px -1px 0 $gray,
1px -1px 0 $gray,
-1px 1px 0 $gray,
1px 1px 0 $gray;
text-align: center; text-align: center;
@include font-smoothing(); @include font-smoothing();
@media (min-width: $bp-captions-large) { span {
font-size: $font-size-large; border-radius: 2px;
padding: 3px 10px;
background: rgba(0,0,0, .9);
}
span:empty {
display: none;
}
@media (min-width: @bp-captions-large) {
font-size: $font-size-captions-medium;
} }
} }
&.captions-active &-captions { &.captions-active &-captions {
display: block; display: block;
} }
&.fullscreen-active &-captions {
font-size: $font-size-captions-large;
}
// Player controls // Player controls
&-controls { &-controls {
@ -233,16 +248,19 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
} }
} }
input + label, // Buttons
button { button {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
margin: 0 2px; margin: 0 2px;
padding: ($control-spacing / 2) $control-spacing; padding: ($control-spacing / 2) $control-spacing;
overflow: hidden;
background .3s ease, color .3s ease, opacity .3s ease; border: 0;
background: transparent;
border-radius: 3px; border-radius: 3px;
cursor: pointer; cursor: pointer;
color: $control-color;
transition: background .3s ease, color .3s ease, opacity .3s ease;
svg { svg {
width: 18px; width: 18px;
@ -251,41 +269,27 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
fill: currentColor; fill: currentColor;
transition: fill .3s ease; transition: fill .3s ease;
} }
}
input + label,
.inverted:checked + label {
opacity: .5;
}
button,
.inverted + label,
input:checked + label {
color: $control-color;
opacity: 1;
}
button {
border: 0;
background: transparent;
overflow: hidden;
}
// Specificity for overriding .inverted // Hover and tab focus
button:focus, &.tab-focus,
button:hover, &:hover {
[type="checkbox"]:focus + label,
[type="checkbox"] + label:hover {
background: $control-bg-hover; background: $control-bg-hover;
color: $control-color-hover; color: $control-color-hover;
opacity: 1;
} }
button:focus, // Default focus
input:focus + label { &:focus {
outline: 0; outline: 0;
} }
}
// Hide toggle icons by default
.icon-exit-fullscreen, .icon-exit-fullscreen,
.icon-muted, .icon-muted,
.icon-captions-on { .icon-captions-on {
display: none; display: none;
} }
// Time display
.player-time { .player-time {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
@ -306,7 +310,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// Add a slash in before // Add a slash in before
&::before { &::before {
content: "\2044"; content: '\2044';
margin-right: $control-spacing; margin-right: $control-spacing;
} }
} }
@ -314,7 +318,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// Tooltips // Tooltips
&-tooltip { &-tooltip {
visibility: hidden;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
bottom: 100%; bottom: 100%;
@ -334,7 +337,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
transition: transform .2s .1s ease, opacity .2s .1s ease; transition: transform .2s .1s ease, opacity .2s .1s ease;
&::after { &::after {
content: ""; content: '';
display: block; display: block;
position: absolute; position: absolute;
left: 50%; left: 50%;
@ -348,15 +351,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
border-color: $controls-bg transparent transparent; border-color: $controls-bg transparent transparent;
} }
} }
label:hover .player-tooltip,
input:focus + label .player-tooltip,
button:hover .player-tooltip, button:hover .player-tooltip,
button:focus .player-tooltip { button:focus .player-tooltip {
visibility: visible;
opacity: 1; opacity: 1;
transform: translate(-50%, 0) scale(1); transform: translate(-50%, 0) scale(1);
} }
label:hover .player-tooltip,
button:hover .player-tooltip { button:hover .player-tooltip {
z-index: 3; z-index: 3;
} }
@ -374,7 +373,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
&-buffer[value], &-buffer[value],
&-played[value], &-played[value],
&-seek[type=range] { &-seek[type='range'] {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@ -414,7 +413,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// Seek control // Seek control
// <input[type='range']> element // <input[type='range']> element
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
&-seek[type=range] { &-seek[type='range'] {
z-index: 4; z-index: 4;
cursor: pointer; cursor: pointer;
outline: 0; outline: 0;
@ -489,7 +488,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// Volume control // Volume control
// <input[type='range']> element // <input[type='range']> element
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
&-volume[type=range] { &-volume[type='range'] {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
-webkit-appearance: none; -webkit-appearance: none;
@ -555,7 +554,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
&.ios &-volume, &.ios &-volume,
&.ios [data-player='mute'], &.ios [data-player='mute'],
&.ios [data-player='mute'] + label,
&-audio.ios &-controls-right { &-audio.ios &-controls-right {
display: none; display: none;
} }
@ -594,15 +592,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
.player-video-wrapper { .player-video-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;
.player-captions {
top: auto;
bottom: 90px;
@media (min-width: $bp-control-split) {
bottom: 60px;
}
}
} }
.player-controls { .player-controls {
position: absolute; position: absolute;
@ -612,13 +601,29 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
} }
// Hide controls when playing in full screen // Hide controls when playing in full screen
&.fullscreen-hide-controls.playing .player-controls { &.fullscreen-hide-controls.playing {
.player-controls {
transform: translateY(100%) translateY($control-spacing / 2); transform: translateY(100%) translateY($control-spacing / 2);
transition: transform .3s .2s ease; transition: transform .3s .2s ease;
}
&.hover { &.player-hover .player-controls {
transform: translateY(0); transform: translateY(0);
} }
.player-captions {
bottom: ($control-spacing / 2);
transition: bottom .3s .2s ease;
}
}
// Captions
.player-captions,
&.fullscreen-hide-controls.playing.player-hover .player-captions {
top: auto;
bottom: 90px;
@media (min-width: $bp-control-split) {
bottom: 60px;
}
} }
} }
@ -635,15 +640,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// Some options are hidden by default // Some options are hidden by default
[data-player='captions'], [data-player='captions'],
[data-player='captions'] + label, [data-player='fullscreen'] {
[data-player='fullscreen'],
[data-player='fullscreen'] + label {
display: none; display: none;
} }
&.captions-enabled [data-player='captions'], &.captions-enabled [data-player='captions'],
&.captions-enabled [data-player='captions'] + label, &.fullscreen-enabled [data-player='fullscreen'] {
&.fullscreen-enabled [data-player='fullscreen'],
&.fullscreen-enabled [data-player='fullscreen'] + label {
display: inline-block; display: inline-block;
} }
} }

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>icon-captions-off</title>
<desc>Created with Sketch.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z" id="Shape" sketch:type="MSShapeGroup"></path> <path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z" id="Shape" sketch:type="MSShapeGroup"></path>

Before

Width:  |  Height:  |  Size: 747 B

After

Width:  |  Height:  |  Size: 562 B

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>icon-captions-on</title>
<desc>Created with Sketch.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z" id="Shape" sketch:type="MSShapeGroup"></path> <path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z" id="Shape" sketch:type="MSShapeGroup"></path>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 863 B

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>expand</title>
<desc>Created with Sketch.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<g id="expand" sketch:type="MSLayerGroup" transform="translate(-1.000000, -1.000000)"> <g id="expand" sketch:type="MSLayerGroup" transform="translate(-1.000000, -1.000000)">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>collapse</title>
<desc>Created with Sketch.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1"> <g id="Page-1" stroke="none" stroke-width="1">
<g id="collapse" sketch:type="MSLayerGroup" transform="translate(-1.000000, -1.000000)"> <g id="collapse" sketch:type="MSLayerGroup" transform="translate(-1.000000, -1.000000)">

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io --> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="18" viewBox="0 0 18 18">
<path d="M17.569 8.246l-10.569-6.246c-0.552 0-1 0.448-1 1v1.954l-5-2.954c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l5-2.955v1.955c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754zM6 10.722l-4 2.364v-8.172l4 2.364v3.444zM8 13.086v-8.172l6.915 4.086-6.915 4.086z"></path> <path d="M17.569 8.246l-10.569-6.246c-0.552 0-1 0.448-1 1v1.954l-5-2.954c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l5-2.955v1.955c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754zM6 10.722l-4 2.364v-8.172l4 2.364v3.444zM8 13.086v-8.172l6.915 4.086-6.915 4.086z"></path>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 480 B

View File

@ -1,9 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>muted</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<g id="sound" sketch:type="MSLayerGroup" transform="translate(0.000000, 2.000000)"> <g id="sound" sketch:type="MSLayerGroup" transform="translate(0.000000, 2.000000)">
<path d="M9.214,0 C9.103,0 8.989,0.032 8.88,0.101 L4.832,2.911 C4.749,2.969 4.65,3 4.549,3 L0.996,3 C0.446,3 1.33226763e-15,3.448 1.33226763e-15,4 L1.33226763e-15,10 C1.33226763e-15,10.552 0.446,11 0.996,11 L4.549,11 C4.651,11 4.749,11.031 4.832,11.089 L8.88,13.899 C8.989,13.968 9.103,14 9.214,14 C9.606,14 9.961,13.6 9.961,13.051 L9.961,0.95 C9.961,0.4 9.606,0.001 9.214,0.001 L9.214,0 Z M7.969,10.834 L5.582,9.177 C5.416,9.062 5.218,8.999 5.016,8.999 L2.491,8.999 C2.216,8.999 1.993,8.775 1.993,8.499 L1.993,5.499 C1.993,5.223 2.216,4.999 2.491,4.999 L5.016,4.999 C5.218,4.999 5.416,4.937 5.582,4.821 L7.969,3.164 L7.969,10.833 L7.969,10.834 Z" id="Shape" sketch:type="MSShapeGroup"></path> <path d="M9.214,0 C9.103,0 8.989,0.032 8.88,0.101 L4.832,2.911 C4.749,2.969 4.65,3 4.549,3 L0.996,3 C0.446,3 1.33226763e-15,3.448 1.33226763e-15,4 L1.33226763e-15,10 C1.33226763e-15,10.552 0.446,11 0.996,11 L4.549,11 C4.651,11 4.749,11.031 4.832,11.089 L8.88,13.899 C8.989,13.968 9.103,14 9.214,14 C9.606,14 9.961,13.6 9.961,13.051 L9.961,0.95 C9.961,0.4 9.606,0.001 9.214,0.001 L9.214,0 Z M7.969,10.834 L5.582,9.177 C5.416,9.062 5.218,8.999 5.016,8.999 L2.491,8.999 C2.216,8.999 1.993,8.775 1.993,8.499 L1.993,5.499 C1.993,5.223 2.216,4.999 2.491,4.999 L5.016,4.999 C5.218,4.999 5.416,4.937 5.582,4.821 L7.969,3.164 L7.969,10.833 L7.969,10.834 Z" id="Shape" sketch:type="MSShapeGroup"></path>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>pause</title>
<desc>Created with Sketch.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<g id="pause" sketch:type="MSLayerGroup" transform="translate(2.000000, 2.000000)"> <g id="pause" sketch:type="MSLayerGroup" transform="translate(2.000000, 2.000000)">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 927 B

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io --> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="18" viewBox="0 0 18 18">
<path d="M5 4.914l6.915 4.086-6.915 4.086v-8.172zM4 2c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754l-10.569-6.246z"></path> <path d="M5 4.914l6.915 4.086-6.915 4.086v-8.172zM4 2c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754l-10.569-6.246z"></path>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 360 B

View File

@ -1,9 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>icon-restart</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<path d="M17,2 C16.448,2 16,2.448 16,3 L16,7.318 L7,2 C6.448,2 6,2.448 6,3 L6,4.954 L1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L6,13.045 L6,15 C6,15.552 6.448,16 7,16 L16,10.682 L16,15 C16,15.552 16.448,16 17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L17,2 Z M6,10.722 L2,13.086 L2,4.914 L6,7.278 L6,10.722 L6,10.722 Z M8,13.086 L8,4.914 L14.915,9 L8,13.086 L8,13.086 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(9.000000, 9.000000) scale(-1, 1) translate(-9.000000, -9.000000) "></path> <path d="M17,2 C16.448,2 16,2.448 16,3 L16,7.318 L7,2 C6.448,2 6,2.448 6,3 L6,4.954 L1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L6,13.045 L6,15 C6,15.552 6.448,16 7,16 L16,10.682 L16,15 C16,15.552 16.448,16 17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L17,2 Z M6,10.722 L2,13.086 L2,4.914 L6,7.278 L6,10.722 L6,10.722 Z M8,13.086 L8,4.914 L14.915,9 L8,13.086 L8,13.086 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(9.000000, 9.000000) scale(-1, 1) translate(-9.000000, -9.000000) "></path>
</g> </g>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 859 B

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="18px" height="21px" viewBox="0 0 18 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> <svg viewBox="0 0 18 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>rewind</title>
<desc>Created with Sketch.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage">
<path d="M17.569,9.246 L7,3 C6.448,3 6,3.448 6,4 L6,5.954 L1,3 C0.448,3 0,3.448 0,4 L0,16 C0,16.552 0.448,17 1,17 L6,14.045 L6,16 C6,16.552 6.448,17 7,17 L17.569,10.754 C17.836,10.596 18,10.31 18,10 C18,9.69 17.836,9.403 17.569,9.246 L17.569,9.246 Z M6,11.722 L2,14.086 L2,5.914 L6,8.278 L6,11.722 L6,11.722 Z M8,14.086 L8,5.914 L14.915,10 L8,14.086 L8,14.086 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(9.000000, 10.000000) rotate(-180.000000) translate(-9.000000, -10.000000) "></path> <path d="M17.569,9.246 L7,3 C6.448,3 6,3.448 6,4 L6,5.954 L1,3 C0.448,3 0,3.448 0,4 L0,16 C0,16.552 0.448,17 1,17 L6,14.045 L6,16 C6,16.552 6.448,17 7,17 L17.569,10.754 C17.836,10.596 18,10.31 18,10 C18,9.69 17.836,9.403 17.569,9.246 L17.569,9.246 Z M6,11.722 L2,14.086 L2,5.914 L6,8.278 L6,11.722 L6,11.722 Z M8,14.086 L8,5.914 L14.915,10 L8,14.086 L8,14.086 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(9.000000, 10.000000) rotate(-180.000000) translate(-9.000000, -10.000000) "></path>

Before

Width:  |  Height:  |  Size: 1021 B

After

Width:  |  Height:  |  Size: 847 B

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io --> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="18" viewBox="0 0 18 18">
<path d="M10.214 2c-0.111 0-0.225 0.032-0.334 0.101l-4.048 2.81c-0.083 0.058-0.182 0.089-0.283 0.089h-3.553c-0.55 0-0.996 0.448-0.996 1v6c0 0.552 0.446 1 0.996 1h3.553c0.102 0 0.2 0.031 0.283 0.089l4.048 2.81c0.109 0.069 0.223 0.101 0.334 0.101 0.392 0 0.747-0.4 0.747-0.949v-12.101c0-0.55-0.355-0.949-0.747-0.949zM8.969 12.834l-2.387-1.657c-0.166-0.115-0.364-0.178-0.566-0.178h-2.525c-0.275 0-0.498-0.224-0.498-0.5v-3c0-0.276 0.223-0.5 0.498-0.5h2.525c0.202 0 0.4-0.062 0.566-0.178l2.387-1.657v7.669z"></path> <path d="M10.214 2c-0.111 0-0.225 0.032-0.334 0.101l-4.048 2.81c-0.083 0.058-0.182 0.089-0.283 0.089h-3.553c-0.55 0-0.996 0.448-0.996 1v6c0 0.552 0.446 1 0.996 1h3.553c0.102 0 0.2 0.031 0.283 0.089l4.048 2.81c0.109 0.069 0.223 0.101 0.334 0.101 0.392 0 0.747-0.4 0.747-0.949v-12.101c0-0.55-0.355-0.949-0.747-0.949zM8.969 12.834l-2.387-1.657c-0.166-0.115-0.364-0.178-0.566-0.178h-2.525c-0.275 0-0.498-0.224-0.498-0.5v-3c0-0.276 0.223-0.5 0.498-0.5h2.525c0.202 0 0.4-0.062 0.566-0.178l2.387-1.657v7.669z"></path>
<path d="M16.934 8.799c-0.086-1.748-1.514-2.991-2.507-3.649-0.47-0.312-1.094-0.122-1.325 0.408l-0.038 0.086c-0.188 0.431-0.045 0.939 0.336 1.194 0.706 0.473 1.586 1.247 1.624 2.065 0.032 0.676-0.553 1.468-1.663 2.27-0.398 0.288-0.529 0.839-0.285 1.275l0.042 0.075c0.266 0.475 0.866 0.624 1.3 0.312 1.74-1.251 2.586-2.606 2.516-4.037z"></path> <path d="M16.934 8.799c-0.086-1.748-1.514-2.991-2.507-3.649-0.47-0.312-1.094-0.122-1.325 0.408l-0.038 0.086c-0.188 0.431-0.045 0.939 0.336 1.194 0.706 0.473 1.586 1.247 1.624 2.065 0.032 0.676-0.553 1.468-1.663 2.27-0.398 0.288-0.529 0.839-0.285 1.275l0.042 0.075c0.266 0.475 0.866 0.624 1.3 0.312 1.74-1.251 2.586-2.606 2.516-4.037z"></path>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1018 B