Compare commits

...

19 Commits

Author SHA1 Message Date
7c5f38311b Bug fixes for controls changes 2015-04-04 12:51:24 +11:00
e568bc9c8d Controls improvements
- Added an option to toggle which controls display
- Better handle missing controls
2015-04-04 12:32:37 +11:00
c2c4172634 Clarified the option 2015-03-30 21:04:38 +11:00
73de5b5773 Added displayDuration option, small bug fix
- Using the native VTT cues, sometimes cues would not disappear
2015-03-30 21:03:48 +11:00
aa1fed0b16 Fixed bug with media longer than 60 minutes (Fixes #69) 2015-03-30 19:17:27 +11:00
22331ae9f1 Added mention 2015-03-22 23:24:15 +11:00
8b436276bf Fixed bug with caption toggle, hide controls in fullscreen 2015-03-22 21:26:29 +11:00
c61db87fd6 API improvements 2015-03-22 11:05:28 +11:00
388cb4df39 Keyboard accessibility improvements (Fixes #66)
- Enter now works on checkboxes within the controls
2015-03-21 17:00:05 +11:00
9feffb2972 Version bump 2015-03-15 10:18:56 +11:00
acea5cdb24 Built js 2015-03-15 10:14:00 +11:00
55ed577b6a Indentation
Converted to 4 space width tabbing
2015-03-15 10:12:36 +11:00
20b206a161 Merge pull request #62 from brunowego/patch-1
Updated SASS support
2015-03-15 10:00:00 +11:00
9c028a0ecc Updated SASS support 2015-03-14 15:50:32 -03:00
b677c3d7ad Merge branch 'master' of https://github.com/selz/plyr
Conflicts:
	dist/plyr.js
	src/js/plyr.js
2015-03-10 23:57:36 +11:00
aa6bc2df2f Fixes for volume control on iOS 2015-03-10 23:54:52 +11:00
a16579fd21 Fix for repo url 2015-03-09 11:53:26 +11:00
ae5a816df1 Fix for potential issue with .tagName 2015-03-09 11:51:01 +11:00
1532f2ab23 Added tooltip option (Fixes #50) 2015-03-09 00:47:38 +11:00
22 changed files with 2149 additions and 1575 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ node_modules
.DS_Store .DS_Store
aws.json aws.json
docs/index.dev.html docs/index.dev.html
*.mp4

View File

@ -1,33 +1,33 @@
{ {
"name": "plyr", "name": "plyr",
"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",
"keywords": [ "keywords": [
"Audio", "Audio",
"Video", "Video",
"HTML5 Audio", "HTML5 Audio",
"HTml5 Video" "HTml5 Video"
], ],
"authors": [ "authors": [
"Sam Potts <me@sampotts.me>" "Sam Potts <me@sampotts.me>"
], ],
"dependencies": {}, "dependencies": {},
"main": [ "main": [
"dist/plyr.css", "dist/plyr.css",
"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.sass",
"src/js/plyr.js" "src/js/plyr.js"
], ],
"ignore": [ "ignore": [
"node_modules", "node_modules",
"bower_components", "bower_components",
".gitignore" ".gitignore"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/selz/plyr.git" "url": "git://github.com/selz/plyr.git"
}, },
"license": "MIT" "license": "MIT"
} }

View File

@ -1,25 +1,25 @@
{ {
"plyr": { "plyr": {
"less": { "less": {
"plyr.css": ["src/less/plyr.less"] "plyr.css": ["src/less/plyr.less"]
}, },
"sass": { "sass": {
"plyr.css": ["src/less/plyr.sass"] "plyr.css": ["src/less/plyr.sass"]
}, },
"js": { "js": {
"plyr.js": ["src/js/plyr.js"] "plyr.js": ["src/js/plyr.js"]
} }
}, },
"docs": { "docs": {
"less": { "less": {
"docs.css": ["docs/src/less/docs.less"] "docs.css": ["docs/src/less/docs.less"]
}, },
"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/dist/templates.js", "docs/dist/templates.js",
"docs/src/js/docs.js" "docs/src/js/docs.js"
] ]
} }
} }
} }

View File

@ -1,17 +1,51 @@
# Changelog # Changelog
## v1.1.1
- Fix for unsupported browser handling
- Fix for config.controls having no effect
## v1.1.0
- Added config option to set which controls are shown (if using the default controls html) and better handling of missing controls
## v1.0.31
- Display duration on metadataloaded
## v1.0.30
- Fixed bug with media longer than 60 minutes (Fixes #69)
## v1.0.29
- Added option to hide controls on fullscreen (default `true`) while palying, after 1s. Pause, mouse hover on progress, or focus on a child control re-shows the controls. On touch a tap of the video (which plays/pauses the video by default) is required. (Fixes #47)
- Fixed a bug with caption toggle in 1.0.28
## v1.0.28
- Added API support for browsers that don't have full plyr support (pretty much <=IE9 and `<video>` on iPhone/iPod)
## v1.0.27
- Keyboard accessibility improvements (Fixes #66)
## v1.0.26
- Fixes for SASS (cheers @brunowego)
- Indentation reset to 4 spaces
## v1.0.25
- Fixes for iOS volume controls (hidden)
- Classnames for left/right controls changed
## v1.0.24
- Added tooltip option to display labels as tooltips (Fixes #50)
## v1.0.23 ## v1.0.23
- Handling loading states in the UI - Handling loading states in the UI (Fixes #36)
## v1.0.22 ## v1.0.22
- Added support() API method for checking mimetype support - Added support() API method for checking mimetype support
- Added source() API method for setting media source(s) - Added source() API method for setting media source(s) (Fixes #44)
- Added poster() API method for setting poster source - Added poster() API method for setting poster source
- Refactored captions logic for manual captions - Refactored captions logic for manual captions
## v1.0.21 ## v1.0.21
- Added an <input type="range"> for seeking to improve experience (and support dragging) - Added an <input type="range"> for seeking to improve experience (and support dragging) (Fixes #40, #42)
- Icons for restart and captions improved (and some IDs changed) - Icons for restart and captions improved (and some IDs changed) (Fixes #49)
## v1.0.20 ## v1.0.20
- Default controls included (Fixes #45) - Default controls included (Fixes #45)
@ -20,7 +54,7 @@
- License changed to MIT - License changed to MIT
## v1.0.19 ## v1.0.19
- Fixed firefox fullscreen issue (#38) - Fixed firefox fullscreen issue (Fixes #38)
## v1.0.18 ## v1.0.18
- Added CDN references - Added CDN references

View File

@ -2,7 +2,7 @@
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. Alternatively check out the `plyr.js` source. 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.
## Requirements ## Requirements
@ -13,11 +13,11 @@ You need to add several placeholders to your html template that are replaced whe
- `{id}` - the dynamically generated ID for the player (for form controls) - `{id}` - the dynamically generated ID for the player (for form controls)
- `{seektime}` - the seek time specified in options for fast forward and rewind - `{seektime}` - the seek time specified in options for fast forward and rewind
Currently all buttons and inputs need to be present for Plyr to work but later we'll make it more dynamic so if you omit a button or input, it'll still work. You can include only the controls you need when specifying custom html.
## Default ## Example
This is the default `html` option from `plyr.js`. This is an example `html` option with all controls.
```javascript ```javascript
["<div class='player-controls'>", ["<div class='player-controls'>",
@ -31,14 +31,14 @@ This is the default `html` option from `plyr.js`.
"<span>0</span>% buffered", "<span>0</span>% buffered",
"</progress>", "</progress>",
"</div>", "</div>",
"<span class='player-controls-playback'>", "<span class='player-controls-left'>",
"<button type='button' data-player='restart'>", "<button type='button' data-player='restart'>",
"<svg><use xlink:href='#icon-restart'></use></svg>", "<svg><use xlink:href='#icon-restart'></use></svg>",
"<span class='sr-only'>Restart</span>", "<span class='sr-only'>Restart</span>",
"</button>", "</button>",
"<button type='button' data-player='rewind'>", "<button type='button' data-player='rewind'>",
"<svg><use xlink:href='#icon-rewind'></use></svg>", "<svg><use xlink:href='#icon-rewind'></use></svg>",
"<span class='sr-only'>Rewind {seektime} seconds</span>", "<span class='sr-only'>Rewind {seektime} secs</span>",
"</button>", "</button>",
"<button type='button' data-player='play'>", "<button type='button' data-player='play'>",
"<svg><use xlink:href='#icon-play'></use></svg>", "<svg><use xlink:href='#icon-play'></use></svg>",
@ -50,14 +50,18 @@ This is the default `html` option from `plyr.js`.
"</button>", "</button>",
"<button type='button' data-player='fast-forward'>", "<button type='button' data-player='fast-forward'>",
"<svg><use xlink:href='#icon-fast-forward'></use></svg>", "<svg><use xlink:href='#icon-fast-forward'></use></svg>",
"<span class='sr-only'>Fast forward {seektime} seconds</span>", "<span class='sr-only'>Forward {seektime} secs</span>",
"</button>", "</button>",
"<span class='player-time'>", "<span class='player-time'>",
"<span class='sr-only'>Time</span>", "<span class='sr-only'>Current time</span>",
"<span class='player-current-time'>00:00</span>",
"</span>",
"<span class='player-time'>",
"<span class='sr-only'>Duration</span>",
"<span class='player-duration'>00:00</span>", "<span class='player-duration'>00:00</span>",
"</span>", "</span>",
"</span>", "</span>",
"<span class='player-controls-sound'>", "<span class='player-controls-right'>",
"<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>", "<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>",
"<label id='mute{id}' for='mute{id}'>", "<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>",
@ -75,7 +79,7 @@ This is the default `html` option from `plyr.js`.
"<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>",
"<span class='sr-only'>Toggle fullscreen</span>", "<span class='sr-only'>Toggle Fullscreen</span>",
"</button>", "</button>",
"</span>", "</span>",
"</div>"].join("\n"); "</div>"].join("\n");

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
docs/dist/docs.css vendored
View File

@ -1 +1 @@
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-medium.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-medium.woff) format("woff"),url(//cdn.plyr.io/fonts/avenir-medium.ttf) format("truetype");font-style:normal;font-weight:400}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-bold.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-bold.woff) format("woff"),url(//cdn.plyr.io/fonts/avenir-bold.ttf) format("truetype");font-style:normal;font-weight:600}*,::after,::before{box-sizing:border-box}body{font-family:Avenir,"Helvetica Neue",Helvetica,Arial,sans-serif;background:#fff;line-height:1.5;text-align:center;color:#6D797F}.error body,html.error{height:100%}.error body{width:100%;display:table;table-layout:fixed}.error main{display:table-cell;width:100%;vertical-align:middle}h1,h2{letter-spacing:-.025em;color:#2E3C44;margin:0 0 10px;line-height:1.2;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}h1{font-size:64px;font-size:4rem;color:#3498DB}p,small{margin:0 0 20px}small{display:block;padding:0 10px;font-size:14px;font-size:.9rem}header{padding:20px;margin-bottom:20px}header p{font-size:18px;font-size:1.1rem}@media (min-width:560px){header{padding-top:60px;padding-bottom:60px}}section{padding-bottom:20px}@media (min-width:560px){section{padding-bottom:40px}}a{text-decoration:none;color:#3498db;border-bottom:1px solid currentColor;transition:all .3s ease}a:focus,a:hover{color:#000}a:focus{outline:#343f4a dotted thin;outline-offset:1px}a.logo{border:0}.btn{display:inline-block;padding:10px 30px;background:#3498db;border:0;color:#fff;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:600;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:hover{color:#fff;background:#258cd1}.example-audio .player{max-width:480px}.example-video .player{max-width:1200px}.example-audio .player,.example-video .player{margin:0 auto 20px}.example-audio .player-fullscreen,.example-audio .player.fullscreen-active,.example-video .player-fullscreen,.example-video .player.fullscreen-active{max-width:none}footer{margin-bottom:20px}footer p{margin-bottom:10px} /*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-medium.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-medium.woff) format("woff"),url(//cdn.plyr.io/fonts/avenir-medium.ttf) format("truetype");font-style:normal;font-weight:400}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-bold.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-bold.woff) format("woff"),url(//cdn.plyr.io/fonts/avenir-bold.ttf) format("truetype");font-style:normal;font-weight:600}*,::after,::before{box-sizing:border-box}body{font-family:Avenir,"Helvetica Neue",Helvetica,Arial,sans-serif;background:#fff;line-height:1.5;text-align:center;color:#6D797F}.error body,html.error{height:100%}.error body{width:100%;display:table;table-layout:fixed}.error main{display:table-cell;width:100%;vertical-align:middle}h1,h2{letter-spacing:-.025em;color:#2E3C44;margin:0 0 10px;line-height:1.2;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}h1{font-size:64px;font-size:4rem;color:#3498DB}p,small{margin:0 0 20px}small{display:block;padding:0 10px;font-size:14px;font-size:.9rem}header{padding:20px;margin-bottom:20px}header p{font-size:18px;font-size:1.1rem}@media (min-width:560px){header{padding-top:60px;padding-bottom:60px}}section{padding-bottom:20px}@media (min-width:560px){section{padding-bottom:40px}}a{text-decoration:none;color:#3498db;border-bottom:1px solid currentColor;transition:all .3s ease}a:focus,a:hover{color:#000}a:focus{outline:#343f4a dotted thin;outline-offset:1px}a.logo{border:0}.btn{display:inline-block;padding:10px 30px;background:#3498db;border:0;color:#fff;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:600;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:hover{color:#fff;background:#258cd1}.example-audio .player{max-width:520px}.example-video .player{max-width:1200px}.example-audio .player,.example-video .player{margin:0 auto 20px}.example-audio .player-fullscreen,.example-audio .player.fullscreen-active,.example-video .player-fullscreen,.example-video .player.fullscreen-active{max-width:none}footer{margin-bottom:20px}footer p{margin-bottom:10px}

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-playback\">");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} seconds</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\">Fast forward {seektime} seconds</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\">Time</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-sound\">");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(" <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: { }});

View File

@ -1,18 +1,18 @@
<!doctype html> <!doctype html>
<html lang="en" class="error"> <html lang="en" class="error">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Doh. Looks like something went wrong.</title> <title>Doh. Looks like something went wrong.</title>
<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.0.23/docs.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.1/docs.css">
</head> </head>
<body> <body>
<main> <main>
<h1>Doh.</h1> <h1>Doh.</h1>
<p>Looks like something went wrong.</p> <p>Looks like something went wrong.</p>
<a href="http://plyr.io" class="btn">Back to plyr.io</a> <a href="http://plyr.io" class="btn">Back to plyr.io</a>
</main> </main>
</body> </body>
</html> </html>

View File

@ -1,79 +1,95 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Plyr - A simple HTML5 media player</title> <title>Plyr - A simple HTML5 media player</title>
<meta name="description" content="A simple HTML5 media player with custom controls and WebVTT captions."> <meta name="description" content="A simple HTML5 media player with custom controls and WebVTT captions.">
<meta name="author" content="Sam Potts"> <meta name="author" content="Sam Potts">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Styles --> <!-- Styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.23/plyr.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.1/plyr.css">
<!-- Docs styles --> <!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.23/docs.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.1/docs.css">
</head> </head>
<body> <body>
<header> <header>
<h1>Plyr</h1> <h1>Plyr</h1>
<p>A simple HTML5 media player with custom controls and WebVTT captions.</p> <p>A simple HTML5 media player with custom controls and WebVTT captions.</p>
<a href="https://github.com/selz/plyr" target="_blank" class="btn">Download on GitHub</a> <a href="https://github.com/selz/plyr" target="_blank" class="btn">Download on GitHub</a>
</header> </header>
<main> <main>
<section class="example-video"> <section class="example-video">
<div class="player"> <div class="player">
<video poster="//cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin> <video poster="//cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin>
<!-- Video files --> <!-- Video files -->
<source src="//cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4"> <source src="//cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4">
<source src="//cdn.selz.com/plyr/1.0/movie.webm" type="video/webm"> <source src="//cdn.selz.com/plyr/1.0/movie.webm" type="video/webm">
<!-- Text track file --> <!-- Text track file -->
<track kind="captions" label="English" srclang="en" src="//cdn.selz.com/plyr/1.0/en.vtt" default> <track kind="captions" label="English" srclang="en" src="//cdn.selz.com/plyr/1.0/en.vtt" default>
<!-- Fallback for browsers that don't support the <video> element --> <!-- Fallback for browsers that don't support the <video> element -->
<div> <div>
<a href="//cdn.selz.com/plyr/1.0/movie.mp4">Download</a> <a href="//cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
</div> </div>
</video> </video>
</div> </div>
<small>Big Buck Bunny. More info can be found at <a href="https://peach.blender.org" target="_blank">peach.blender.org</a>.</small> <small>Big Buck Bunny. More info can be found at <a href="https://peach.blender.org" target="_blank">peach.blender.org</a>.</small>
</section> </section>
<section class="example-audio"> <section class="example-audio">
<div class="player"> <div class="player">
<audio controls> <audio controls>
<!-- Audio files --> <!-- Audio files -->
<source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3" type="audio/mp3"> <source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3" type="audio/mp3">
<source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.ogg" type="audio/ogg"> <source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.ogg" type="audio/ogg">
<!-- Fallback for browsers that don't support the <audio> element --> <!-- Fallback for browsers that don't support the <audio> element -->
<div> <div>
<a href="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a> <a href="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a>
</div> </div>
</audio> </audio>
</div> </div>
<small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small> <small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small>
</section> </section>
</main> </main>
<footer> <footer>
<p>Used by &hellip;</p> <p>Used by &hellip;</p>
<a href="https://selz.com" target="_blank" class="logo"> <a href="https://selz.com" target="_blank" class="logo">
<img src="https://d33i624pw6jj68.cloudfront.net/static/img/logos/selz.svg" alt="Selz"> <img src="https://d33i624pw6jj68.cloudfront.net/static/img/logos/selz.svg" alt="Selz">
</a> </a>
</footer> </footer>
<!-- Load SVG defs --> <!-- Load SVG defs -->
<!-- You should bundle all SVG/Icons into one file using a build tool such as gulp and svg store --> <!-- You should bundle all SVG/Icons into one file using a build tool such as gulp and svg store -->
<script> <script>
(function(d,p){var a=new XMLHttpRequest(),b=d.body;a.open("GET",p,!0);a.send();a.onload=function(){var c=d.createElement("div");c.style.display="none";c.innerHTML=a.responseText;b.insertBefore(c,b.childNodes[0])}})(document,"//cdn.plyr.io/1.0.23/sprite.svg"); (function(d, u){
</script> var a = new XMLHttpRequest(),
b = d.body;
<!-- Plyr core script --> // Check for CORS support
<script src="//cdn.plyr.io/1.0.23/plyr.js"></script> // If you're loading from same domain, you can remove the if statement
if("withCredentials" in a) {
a.open("GET", u, true);
a.send();
a.onload = function(){
var c = d.createElement("div");
c.style.display="none";
c.innerHTML = a.responseText;
b.insertBefore(c, b.childNodes[0]);
}
}
})(document, "https://cdn.plyr.io/1.1.1/sprite.svg");
</script>
<!-- Docs script --> <!-- Plyr core script -->
<script src="//cdn.plyr.io/1.0.23/docs.js"></script> <script src="//cdn.plyr.io/1.1.1/plyr.js"></script>
</body>
<!-- Docs script -->
<script src="//cdn.plyr.io/1.1.1/docs.js"></script>
</body>
</html> </html>

View File

@ -12,153 +12,153 @@
// Variables // Variables
// --------------------------------------- // ---------------------------------------
// Colors // Colors
@blue: #3498DB; @blue: #3498DB;
@gray-dark: #343f4a; @gray-dark: #343f4a;
@gray: #565d64; @gray: #565d64;
@gray-light: #cbd0d3; @gray-light: #cbd0d3;
// Elements // Elements
@link-color: @blue; @link-color: @blue;
@padding-base: 20px; @padding-base: 20px;
// Breakpoints // Breakpoints
@screen-md: 768px; @screen-md: 768px;
// BORDER-BOX ALL THE THINGS! // BORDER-BOX ALL THE THINGS!
// http://paulirish.com/2012/box-sizing-border-box-ftw/ // http://paulirish.com/2012/box-sizing-border-box-ftw/
*, *::after, *::before { *, *::after, *::before {
box-sizing: border-box; box-sizing: border-box;
} }
// Base // Base
body { body {
font-family: "Avenir", "Helvetica Neue", Helvetica, Arial, sans-serif; font-family: "Avenir", "Helvetica Neue", Helvetica, Arial, sans-serif;
background: #fff; background: #fff;
line-height: 1.5; line-height: 1.5;
text-align: center; text-align: center;
color: #6D797F; color: #6D797F;
} }
// Error page // Error page
html.error, html.error,
.error body { .error body {
height: 100%; height: 100%;
} }
.error body { .error body {
width: 100%; width: 100%;
display: table; display: table;
table-layout: fixed; table-layout: fixed;
} }
.error main { .error main {
display: table-cell; display: table-cell;
width: 100%; width: 100%;
vertical-align: middle; vertical-align: middle;
} }
// Type // Type
h1, h1,
h2 { h2 {
letter-spacing: -.025em; letter-spacing: -.025em;
color: #2E3C44; color: #2E3C44;
margin: 0 0 (@padding-base / 2); margin: 0 0 (@padding-base / 2);
line-height: 1.2; line-height: 1.2;
.font-smoothing(); .font-smoothing();
} }
h1 { h1 {
.font-size(64); .font-size(64);
color: #3498DB; color: #3498DB;
} }
p, p,
small { small {
margin: 0 0 @padding-base; margin: 0 0 @padding-base;
} }
small { small {
display: block; display: block;
padding: 0 (@padding-base / 2); padding: 0 (@padding-base / 2);
.font-size(14); .font-size(14);
} }
// Header // Header
header { header {
padding: @padding-base; padding: @padding-base;
margin-bottom: @padding-base; margin-bottom: @padding-base;
p { p {
.font-size(18); .font-size(18);
} }
@media (min-width: 560px) { @media (min-width: 560px) {
padding-top: (@padding-base * 3); padding-top: (@padding-base * 3);
padding-bottom: (@padding-base * 3); padding-bottom: (@padding-base * 3);
} }
} }
// Sections // Sections
section { section {
padding-bottom: @padding-base; padding-bottom: @padding-base;
@media (min-width: 560px) { @media (min-width: 560px) {
padding-bottom: (@padding-base * 2); padding-bottom: (@padding-base * 2);
} }
} }
// Links & Buttons // Links & Buttons
a { a {
text-decoration: none; text-decoration: none;
color: @link-color; color: @link-color;
border-bottom: 1px solid currentColor; border-bottom: 1px solid currentColor;
transition: all .3s ease; transition: all .3s ease;
&:hover, &:hover,
&:focus { &:focus {
color: #000; color: #000;
} }
&:focus { &:focus {
.tab-focus(); .tab-focus();
} }
&.logo { &.logo {
border: 0; border: 0;
} }
} }
.btn { .btn {
display: inline-block; display: inline-block;
padding: (@padding-base / 2) (@padding-base * 1.5); padding: (@padding-base / 2) (@padding-base * 1.5);
background: @link-color; background: @link-color;
border: 0; border: 0;
color: #fff; color: #fff;
.font-smoothing(on); .font-smoothing(on);
font-weight: 600; font-weight: 600;
border-radius: 3px; border-radius: 3px;
user-select: none; user-select: none;
&:hover, &:hover,
&:focus { &:focus {
color: #fff; color: #fff;
background: darken(@link-color, 5%); background: darken(@link-color, 5%);
} }
} }
// Players // Players
.example-audio .player { .example-audio .player {
max-width: 480px; max-width: 520px;
} }
.example-video .player { .example-video .player {
max-width: 1200px; max-width: 1200px;
} }
.example-audio .player, .example-audio .player,
.example-video .player { .example-video .player {
margin: 0 auto @padding-base; margin: 0 auto @padding-base;
&-fullscreen, &-fullscreen,
&.fullscreen-active { &.fullscreen-active {
max-width: none; max-width: none;
} }
} }
// Footer // Footer
footer { footer {
margin-bottom: @padding-base; margin-bottom: @padding-base;
p { p {
margin-bottom: (@padding-base / 2); margin-bottom: (@padding-base / 2);
} }
} }

View File

@ -1,16 +1,16 @@
@font-face { @font-face {
font-family: "Avenir"; font-family: "Avenir";
src: url("//cdn.plyr.io/fonts/avenir-medium.woff2") format("woff2"), src: url("//cdn.plyr.io/fonts/avenir-medium.woff2") format("woff2"),
url("//cdn.plyr.io/fonts/avenir-medium.woff") format("woff"), url("//cdn.plyr.io/fonts/avenir-medium.woff") format("woff"),
url("//cdn.plyr.io/fonts/avenir-medium.ttf") format("truetype"); url("//cdn.plyr.io/fonts/avenir-medium.ttf") format("truetype");
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
} }
@font-face { @font-face {
font-family: "Avenir"; font-family: "Avenir";
src: url("//cdn.plyr.io/fonts/avenir-bold.woff2") format("woff2"), src: url("//cdn.plyr.io/fonts/avenir-bold.woff2") format("woff2"),
url("//cdn.plyr.io/fonts/avenir-bold.woff") format("woff"), url("//cdn.plyr.io/fonts/avenir-bold.woff") format("woff"),
url("//cdn.plyr.io/fonts/avenir-bold.ttf") format("truetype"); url("//cdn.plyr.io/fonts/avenir-bold.ttf") format("truetype");
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
} }

View File

@ -5,38 +5,38 @@
// Contain floats: nicolasgallagher.com/micro-clearfix-hack/ // Contain floats: nicolasgallagher.com/micro-clearfix-hack/
// --------------------------------------- // ---------------------------------------
.clearfix() { .clearfix() {
zoom: 1; zoom: 1;
&:before, &:before,
&:after { content: ""; display: table; } &:after { content: ""; display: table; }
&:after { clear: both; } &:after { clear: both; }
} }
// Webkit-style focus // Webkit-style focus
// --------------------------------------- // ---------------------------------------
.tab-focus() { .tab-focus() {
// Default // Default
outline: thin dotted @gray-dark; outline: thin dotted @gray-dark;
// Webkit // Webkit
//outline: 5px auto -webkit-focus-ring-color; //outline: 5px auto -webkit-focus-ring-color;
outline-offset: 1px; outline-offset: 1px;
} }
// Use rems for font sizing // Use rems for font sizing
// Leave <body> at 100%/16px // Leave <body> at 100%/16px
// --------------------------------------- // ---------------------------------------
.font-size(@font-size: 16){ .font-size(@font-size: 16){
@rem: round((@font-size / 16), 1); @rem: round((@font-size / 16), 1);
font-size: (@font-size * 1px); font-size: (@font-size * 1px);
font-size: ~"@{rem}rem"; font-size: ~"@{rem}rem";
} }
// Font smoothing // Font smoothing
// --------------------------------------- // ---------------------------------------
.font-smoothing(@mode: on) when (@mode = on) { .font-smoothing(@mode: on) when (@mode = on) {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
.font-smoothing(@mode: on) when (@mode = off) { .font-smoothing(@mode: on) when (@mode = off) {
-moz-osx-font-smoothing: auto; -moz-osx-font-smoothing: auto;
-webkit-font-smoothing: subpixel-antialiased; -webkit-font-smoothing: subpixel-antialiased;
} }

View File

@ -1,62 +1,66 @@
<div class="player-controls"> <div class="player-controls">
<div class="player-progress"> <div class="player-progress">
<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>% 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>% buffered
</progress> </progress>
</div> </div>
<span class="player-controls-playback"> <span class="player-controls-left">
<button type="button" data-player="restart"> <button type="button" data-player="restart">
<svg><use xlink:href="#icon-restart"></use></svg> <svg><use xlink:href="#icon-restart"></use></svg>
<span class="sr-only">Restart</span> <span class="sr-only">Restart</span>
</button> </button>
<button type="button" data-player="rewind"> <button type="button" data-player="rewind">
<svg><use xlink:href="#icon-rewind"></use></svg> <svg><use xlink:href="#icon-rewind"></use></svg>
<span class="sr-only">Rewind {seektime} seconds</span> <span class="sr-only">Rewind {seektime} secs</span>
</button> </button>
<button type="button" data-player="play"> <button type="button" data-player="play">
<svg><use xlink:href="#icon-play"></use></svg> <svg><use xlink:href="#icon-play"></use></svg>
<span class="sr-only">Play</span> <span class="sr-only">Play</span>
</button> </button>
<button type="button" data-player="pause"> <button type="button" data-player="pause">
<svg><use xlink:href="#icon-pause"></use></svg> <svg><use xlink:href="#icon-pause"></use></svg>
<span class="sr-only">Pause</span> <span class="sr-only">Pause</span>
</button> </button>
<button type="button" data-player="fast-forward"> <button type="button" data-player="fast-forward">
<svg><use xlink:href="#icon-fast-forward"></use></svg> <svg><use xlink:href="#icon-fast-forward"></use></svg>
<span class="sr-only">Fast forward {seektime} seconds</span> <span class="sr-only">Forward {seektime} secs</span>
</button> </button>
<span class="player-time"> <span class="player-time">
<span class="sr-only">Time</span> <span class="sr-only">Current time</span>
<span class="player-duration">00:00</span> <span class="player-current-time">00:00</span>
</span> </span>
</span> <span class="player-time">
<span class="player-controls-sound"> <span class="sr-only">Duration</span>
<input class="inverted sr-only" id="mute{id}" type="checkbox" data-player="mute"> <span class="player-duration">00:00</span>
<label id="mute{id}" for="mute{id}"> </span>
<svg class="icon-muted"><use xlink:href="#icon-muted"></use></svg> </span>
<svg><use xlink:href="#icon-volume"></use></svg> <span class="player-controls-right">
<span class="sr-only">Toggle Mute</span> <input class="inverted sr-only" id="mute{id}" type="checkbox" data-player="mute">
</label> <label id="mute{id}" for="mute{id}">
<svg class="icon-muted"><use xlink:href="#icon-muted"></use></svg>
<svg><use xlink:href="#icon-volume"></use></svg>
<span class="sr-only">Toggle Mute</span>
</label>
<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">
<input class="sr-only" id="captions{id}" type="checkbox" data-player="captions"> <input class="sr-only" id="captions{id}" type="checkbox" data-player="captions">
<label for="captions{id}"> <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> </label>
<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>
<span class="sr-only">Toggle fullscreen</span> <span class="sr-only">Toggle Fullscreen</span>
</button> </button>
</span> </span>
</div> </div>

View File

@ -4,59 +4,60 @@
/*global require, __dirname*/ /*global require, __dirname*/
/*jshint -W079 */ /*jshint -W079 */
var fs = require("fs"), var fs = require("fs"),
path = require("path"), path = require("path"),
gulp = require("gulp"), gulp = require("gulp"),
gutil = require("gulp-util"), gutil = require("gulp-util"),
concat = require("gulp-concat"), concat = require("gulp-concat"),
uglify = require("gulp-uglify"), uglify = require("gulp-uglify"),
less = require("gulp-less"), less = require("gulp-less"),
sass = require("gulp-sass"), sass = require("gulp-sass"),
minify = require("gulp-minify-css"), minify = require("gulp-minify-css"),
run = require("run-sequence"), run = require("run-sequence"),
prefix = require("gulp-autoprefixer"), prefix = require("gulp-autoprefixer"),
svgstore = require("gulp-svgstore"), svgstore = require("gulp-svgstore"),
svgmin = require("gulp-svgmin"), svgmin = require("gulp-svgmin"),
hogan = require("gulp-hogan-compile"), hogan = require("gulp-hogan-compile"),
rename = require("gulp-rename"), rename = require("gulp-rename"),
s3 = require("gulp-s3"), s3 = require("gulp-s3"),
gzip = require("gulp-gzip"), gzip = require("gulp-gzip"),
replace = require("gulp-replace"), replace = require("gulp-replace"),
open = require("gulp-open"); open = require("gulp-open"),
size = require("gulp-size");
var root = __dirname, var root = __dirname,
paths = { paths = {
plyr: { plyr: {
// Source paths // Source paths
src: { src: {
less: path.join(root, "src/less/**/*"), less: path.join(root, "src/less/**/*"),
sass: path.join(root, "src/sass/**/*"), sass: path.join(root, "src/sass/**/*"),
js: path.join(root, "src/js/**/*"), js: path.join(root, "src/js/**/*"),
sprite: path.join(root, "src/sprite/*.svg") sprite: path.join(root, "src/sprite/*.svg")
}, },
// Output paths // Output paths
output: path.join(root, "dist/") output: path.join(root, "dist/")
}, },
docs: { docs: {
// Source paths // Source paths
src: { src: {
less: path.join(root, "docs/src/less/**/*"), less: path.join(root, "docs/src/less/**/*"),
js: path.join(root, "docs/src/js/**/*"), js: path.join(root, "docs/src/js/**/*"),
templates: path.join(root, "docs/src/templates/*.html") templates: path.join(root, "docs/src/templates/*.html")
}, },
// Output paths // Output paths
output: path.join(root, "docs/dist/"), output: path.join(root, "docs/dist/"),
// Docs // Docs
root: path.join(root, "docs/") root: path.join(root, "docs/")
}, },
upload: [path.join(root, "dist/**"), path.join(root, "docs/dist/**")] upload: [path.join(root, "dist/**"), path.join(root, "docs/dist/**")]
}, },
// Task arrays // Task arrays
tasks = { tasks = {
less: [], less: [],
sass: [], sass: [],
js: [] js: []
}, },
// Fetch bundles from JSON // Fetch bundles from JSON
@ -69,88 +70,88 @@ function loadJSON(path) {
} }
var build = { var build = {
js: function (files, bundle) { js: function (files, bundle) {
for (var key in files) { for (var key in files) {
(function(key) { (function(key) {
var name = "js-" + key; var name = "js-" + key;
tasks.js.push(name); tasks.js.push(name);
gulp.task(name, function () { gulp.task(name, function () {
return gulp return gulp
.src(bundles[bundle].js[key]) .src(bundles[bundle].js[key])
.pipe(concat(key)) .pipe(concat(key))
.pipe(uglify()) .pipe(uglify())
.pipe(gulp.dest(paths[bundle].output)); .pipe(gulp.dest(paths[bundle].output));
}); });
})(key); })(key);
} }
}, },
less: function(files, bundle) { less: function(files, bundle) {
for (var key in files) { for (var key in files) {
(function (key) { (function (key) {
var name = "less-" + key; var name = "less-" + key;
tasks.less.push(name); tasks.less.push(name);
gulp.task(name, function () { gulp.task(name, function () {
return gulp return gulp
.src(bundles[bundle].less[key]) .src(bundles[bundle].less[key])
.pipe(less()) .pipe(less())
.on("error", gutil.log) .on("error", gutil.log)
.pipe(concat(key)) .pipe(concat(key))
.pipe(prefix(["last 2 versions"], { cascade: true })) .pipe(prefix(["last 2 versions"], { cascade: true }))
.pipe(minify()) .pipe(minify())
.pipe(gulp.dest(paths[bundle].output)); .pipe(gulp.dest(paths[bundle].output));
}); });
})(key); })(key);
} }
}, },
sass: function(files, bundle) { sass: function(files, bundle) {
for (var key in files) { for (var key in files) {
(function (key) { (function (key) {
var name = "sass-" + key; var name = "sass-" + key;
tasks.sass.push(name); tasks.sass.push(name);
gulp.task(name, function () { gulp.task(name, function () {
return gulp return gulp
.src(bundles[bundle].sass[key]) .src(bundles[bundle].sass[key])
.pipe(sass()) .pipe(sass())
.on("error", gutil.log) .on("error", gutil.log)
.pipe(concat(key)) .pipe(concat(key))
.pipe(prefix(["last 2 versions"], { cascade: true })) .pipe(prefix(["last 2 versions"], { cascade: true }))
.pipe(minify()) .pipe(minify())
.pipe(gulp.dest(paths[bundle].output)); .pipe(gulp.dest(paths[bundle].output));
}); });
})(key); })(key);
} }
}, },
sprite: function() { sprite: function() {
// Process Icons // Process Icons
gulp.task("sprite", function () { gulp.task("sprite", function () {
return gulp return gulp
.src(paths.plyr.src.sprite) .src(paths.plyr.src.sprite)
.pipe(svgmin({ .pipe(svgmin({
plugins: [{ plugins: [{
removeDesc: true removeDesc: true
}] }]
})) }))
.pipe(svgstore()) .pipe(svgstore())
.pipe(gulp.dest(paths.plyr.output)); .pipe(gulp.dest(paths.plyr.output));
}); });
}, },
templates: function() { templates: function() {
// Build templates // Build templates
gulp.task("templates", function () { gulp.task("templates", function () {
return gulp return gulp
.src(paths.docs.src.templates) .src(paths.docs.src.templates)
.pipe(hogan("templates.js", { .pipe(hogan("templates.js", {
wrapper: false, wrapper: false,
templateName: function (file) { templateName: function (file) {
return path.basename(file.relative.replace(/\\/g, "-"), path.extname(file.relative)); return path.basename(file.relative.replace(/\\/g, "-"), path.extname(file.relative));
} }
})) }))
.pipe(gulp.dest(paths.docs.output)); .pipe(gulp.dest(paths.docs.output));
}); });
} }
}; };
// Plyr core files // Plyr core files
@ -166,22 +167,22 @@ build.js(bundles.docs.js, "docs");
// Default gulp task // Default gulp task
gulp.task("default", function(){ gulp.task("default", function(){
run("templates", tasks.js, tasks.less, "sprite"); 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);
}); });
// Build SASS (for testing, default is LESS) // Build SASS (for testing, default is LESS)
gulp.task("sass", function(){ gulp.task("sass", function(){
run(tasks.sass); run(tasks.sass);
}); });
// Watch for file changes // Watch for file changes
gulp.task("watch", function () { gulp.task("watch", function () {
// Plyr core // Plyr core
gulp.watch(paths.plyr.src.js, tasks.js); gulp.watch(paths.plyr.src.js, tasks.js);
gulp.watch(paths.plyr.src.less, tasks.less); gulp.watch(paths.plyr.src.less, tasks.less);
gulp.watch(paths.plyr.src.sprite, "sprite"); gulp.watch(paths.plyr.src.sprite, "sprite");
@ -189,7 +190,7 @@ gulp.task("watch", function () {
// Docs // Docs
gulp.watch(paths.docs.src.js, tasks.js); gulp.watch(paths.docs.src.js, tasks.js);
gulp.watch(paths.docs.src.less, tasks.less); gulp.watch(paths.docs.src.less, tasks.less);
gulp.watch(paths.docs.src.templates, "js"); gulp.watch(paths.docs.src.templates, "js");
}); });
// Publish a version to CDN and docs // Publish a version to CDN and docs
@ -198,69 +199,78 @@ gulp.task("watch", function () {
// Some options // Some options
var aws = loadJSON(path.join(root, "aws.json")), var aws = loadJSON(path.join(root, "aws.json")),
version = package.version, version = package.version,
maxAge = 31536000, // seconds 1 year maxAge = 31536000, // seconds 1 year
options = { options = {
cdn: { cdn: {
headers: { headers: {
"Cache-Control": "max-age=" + maxAge + ", no-transform, public", "Cache-Control": "max-age=" + maxAge + ", no-transform, public",
"Vary": "Accept-Encoding" "Vary": "Accept-Encoding"
}, },
gzippedOnly: true gzippedOnly: true
}, },
docs: { docs: {
headers: { headers: {
"Cache-Control": "public, must-revalidate, proxy-revalidate, max-age=0", "Cache-Control": "public, must-revalidate, proxy-revalidate, max-age=0",
"Vary": "Accept-Encoding" "Vary": "Accept-Encoding"
}, },
gzippedOnly: true gzippedOnly: true
} }
}, },
cdnpath = new RegExp(aws.cdn.bucket + "\/(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)","gi"); cdnpath = new RegExp(aws.cdn.bucket + "\/(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)","gi");
// Publish version to CDN bucket // Publish version to CDN bucket
gulp.task("cdn", function () { gulp.task("cdn", function () {
console.log("Uploading " + version + " to " + aws.cdn.bucket); console.log("Uploading " + version + " to " + aws.cdn.bucket);
// Upload to CDN // Upload to CDN
gulp.src(paths.upload) gulp.src(paths.upload)
.pipe(rename(function (path) { .pipe(size({
path.dirname = path.dirname.replace(".", version); showFiles: true,
})) gzip: true
.pipe(gzip()) }))
.pipe(s3(aws.cdn, options.cdn)); .pipe(rename(function (path) {
path.dirname = path.dirname.replace(".", version);
}))
.pipe(gzip())
.pipe(s3(aws.cdn, options.cdn));
}); });
// Publish to Docs bucket // Publish to Docs bucket
gulp.task("docs", function () { gulp.task("docs", function () {
console.log("Uploading " + version + " docs to " + aws.docs.bucket); console.log("Uploading " + version + " docs to " + aws.docs.bucket);
// Replace versioned files in *.html // Replace versioned files in readme.md
gulp.src([paths.docs.root + "*.html"]) gulp.src([root + "/readme.md"])
.pipe(replace(cdnpath, aws.cdn.bucket + "/" + version)) .pipe(replace(cdnpath, aws.cdn.bucket + "/" + version))
.pipe(gulp.dest(paths.docs.root)) .pipe(gulp.dest(root));
.pipe(gzip())
.pipe(s3(aws.docs, options.docs));
// Upload error.html to cdn using docs options // Replace versioned files in *.html
gulp.src([paths.docs.root + "error.html"]) gulp.src([paths.docs.root + "*.html"])
.pipe(gzip()) .pipe(replace(cdnpath, aws.cdn.bucket + "/" + version))
.pipe(s3(aws.cdn, options.docs)); .pipe(gulp.dest(paths.docs.root))
.pipe(gzip())
.pipe(s3(aws.docs, options.docs));
// Upload error.html to cdn using docs options
gulp.src([paths.docs.root + "error.html"])
.pipe(gzip())
.pipe(s3(aws.cdn, options.docs));
}); });
// Open the docs site to check it's sweet // Open the docs site to check it's sweet
gulp.task("open", function () { gulp.task("open", function () {
console.log("Opening " + aws.docs.bucket + "..."); console.log("Opening " + aws.docs.bucket + "...");
// A file must be specified or gulp will skip the task // A file must be specified or gulp will skip the task
// Doesn't matter which file since we set the URL above // Doesn't matter which file since we set the URL above
// Weird, I know... // Weird, I know...
gulp.src([paths.docs.root + "index.html"]) gulp.src([paths.docs.root + "index.html"])
.pipe(open("", { .pipe(open("", {
url: "http://" + aws.docs.bucket url: "http://" + aws.docs.bucket
})); }));
}); });
// Do everything // Do everything
gulp.task("publish", function () { gulp.task("publish", function () {
run("templates", tasks.js, tasks.less, "sprite", "cdn", "docs", "open"); run("templates", tasks.js, tasks.less, "sprite", "cdn", "docs", "open");
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "plyr", "name": "plyr",
"version": "1.0.23", "version": "1.1.1",
"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",
@ -18,6 +18,7 @@
"gulp-replace": "^0.5.3", "gulp-replace": "^0.5.3",
"gulp-s3": "^0.3.0", "gulp-s3": "^0.3.0",
"gulp-sass": "^1.3.3", "gulp-sass": "^1.3.3",
"gulp-size": "^1.2.1",
"gulp-svgmin": "^1.0.0", "gulp-svgmin": "^1.0.0",
"gulp-svgstore": "^5.0.0", "gulp-svgstore": "^5.0.0",
"gulp-uglify": "~0.3.1", "gulp-uglify": "~0.3.1",

View File

@ -10,7 +10,7 @@ We wanted a lightweight, accessible and customisable media player that just supp
## Features ## Features
- **Accessible** - full support for captions and screen readers. - **Accessible** - full support for captions and screen readers.
- **Lightweight** - just 5.7KB minified and gzipped. - **Lightweight** - just 6KB minified and gzipped.
- **Customisable** - make the player look how you want with the markup you want. - **Customisable** - make the player look how you want with the markup you want.
- **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks. - **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks.
- **Responsive** - as you'd expect these days. - **Responsive** - as you'd expect these days.
@ -38,7 +38,7 @@ If you have any cool ideas or features, please let me know by [creating an issue
Check `docs/index.html` and `docs/dist/docs.js` for an example setup. Check `docs/index.html` and `docs/dist/docs.js` for an example setup.
**Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.0.23/plyr.js` to `https://cdn.plyr.io/1.0.23/plyr.js` **Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.1.1/plyr.js` to `https://cdn.plyr.io/1.1.1/plyr.js`
### Bower ### Bower
If bower is your thang, you can grab Plyr using: If bower is your thang, you can grab Plyr using:
@ -51,11 +51,11 @@ More info on setting up dependencies can be found in the [Bower Docs](http://bow
If you want to use our CDN, you can use the following. HTTPS (SSL) is supported. If you want to use our CDN, you can use the following. HTTPS (SSL) is supported.
```html ```html
<link rel="stylesheet" href="//cdn.plyr.io/1.0.23/plyr.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.1.1/plyr.css">
<script src="//cdn.plyr.io/1.0.23/plyr.js"></script> <script src="//cdn.plyr.io/1.1.1/plyr.js"></script>
``` ```
You can also access the `sprite.svg` file at `//cdn.plyr.io/1.0.23/sprite.svg`. You can also access the `sprite.svg` file at `//cdn.plyr.io/1.1.1/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.
@ -168,6 +168,12 @@ You can pass the following options to the setup method.
<td><code><a href="controls.md">See controls.md</a></code></td> <td><code><a href="controls.md">See controls.md</a></code></td>
<td>See <a href="controls.md">controls.md</a> for more info on how the html needs to be structured.</td> <td>See <a href="controls.md">controls.md</a> for more info on how the html needs to be structured.</td>
</tr> </tr>
<tr>
<td><code>controls</code></td>
<td>Array</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>
</tr>
<tr> <tr>
<td><code>debug</code></td> <td><code>debug</code></td>
<td>Boolean</td> <td>Boolean</td>
@ -192,6 +198,18 @@ You can pass the following options to the setup method.
<td><code>true</code></td> <td><code>true</code></td>
<td>Click (or tap) will toggle pause/play of a <code>&lt;video&gt;</code>.</td> <td>Click (or tap) will toggle pause/play of a <code>&lt;video&gt;</code>.</td>
</tr> </tr>
<tr>
<td><code>tooltips</code></td>
<td>Boolean</td>
<td><code>false</code></td>
<td>Display control labels as tooltips on :hover &amp; :focus (by default, the labels are screen reader only).</td>
</tr>
<tr>
<td><code>displayDuration</code></td>
<td>Boolean</td>
<td><code>true</code></td>
<td>Displays the duration of the media on the "metadataloaded" event (on startup) in the current time display. This will only work if the `preload` attribute is not set to `none` (or is not set at all) and you choose not to display the duration (see <code>controls</code> option).</td>
</tr>
<tr> <tr>
<td><code>selectors</code></td> <td><code>selectors</code></td>
<td>Object</td> <td>Object</td>
@ -208,19 +226,19 @@ You can pass the following options to the setup method.
<td><code>captions</code></td> <td><code>captions</code></td>
<td>Object</td> <td>Object</td>
<td>&mdash;</td> <td>&mdash;</td>
<td>This currently contains one property `defaultActive` which toggles if captions should be on by default. The default value is <code>false</code>.</td> <td>One property <code>defaultActive</code> which toggles if captions should be on by default. The default value is <code>false</code>.</td>
</tr> </tr>
<tr> <tr>
<td><code>fullscreen</code></td> <td><code>fullscreen</code></td>
<td>Object</td> <td>Object</td>
<td>&mdash;</td> <td>&mdash;</td>
<td>This currently contains two properties;<code>enabled</code> which toggles if fullscreen should be enabled (if the browser supports it). The default value is <code>true</code>. Also an extra property called <code>fallback</code> which will enable a full window view for older browsers. The default value is <code>true</code>.</td> <td>Three properties; <code>enabled</code> which toggles if fullscreen should be enabled (if the browser supports it). The default value is <code>true</code>. A <code>fallback</code> property which will enable a full window view for older browsers. The default value is <code>true</code>. A <code>hideControls</code> property which will hide the controls when fullscreen is active and the video is playing, after 1s. The controls reappear on hover of the progress bar (mouse), focusing a child control or pausing the video (by tap/click of video if `click` is `true`). The default value is <code>true</code>.</td>
</tr> </tr>
<tr> <tr>
<td><code>storage</code></td> <td><code>storage</code></td>
<td>Object</td> <td>Object</td>
<td>&mdash;</td> <td>&mdash;</td>
<td>This currently contains one property `enabled` which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later.</td> <td>Two properties; <code>enabled</code> which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later. The second property <code>key</code> is the key used for the local storage. The default is <code>plyr_volume</code> until more settings are stored.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -353,15 +371,15 @@ Fullscreen in Plyr is supported for all browsers that [currently support it](htt
<td>✔</td> <td>✔</td>
<td>✔</td> <td>✔</td>
<td>✔</td> <td>✔</td>
<td>&sup2;</td> <td>API&sup2;</td>
<td>✔&sup3;</td> <td>✔&sup3;</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
&sup1; iPhone forces the native player for `<video>` so no customisation possible &sup1; Mobile Safari on the iPhone forces the native player for `<video>` so no useful customisation is possible. `<audio>` elements have volume controls disabled.
&sup2; Native player used (no support for `<progress>` or `<input type="range">`) &sup2; Native player used (no support for `<progress>` or `<input type="range">`) but the API is supported (v1.0.28+)
&sup3; IE10 has no native fullscreen support, fallback can be used (see options) &sup3; IE10 has no native fullscreen support, fallback can be used (see options)
@ -383,10 +401,12 @@ Plyr is developed by Sam Potts ([@sam_potts](https://twitter.com/sam_potts)) ([s
## Mentions ## Mentions
- [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) - [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/)
- [HTML5 Weekly #177](http://html5weekly.com/issues/177) - [HTML5 Weekly #177](http://html5weekly.com/issues/177)
- [Responsive Design #149](http://us4.campaign-archive2.com/?u=559bc631fe5294fc66f5f7f89&id=451a61490f)
- [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/) - [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/)
- [Hacker News](https://news.ycombinator.com/item?id=9136774) - [Hacker News](https://news.ycombinator.com/item?id=9136774)
- [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04) - [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04)
- [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player) - [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player)
- [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images)
## Used by ## Used by
- [Selz.com](https://selz.com) - [Selz.com](https://selz.com)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff