Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
4f0633fdc1 | |||
f41854ebe7 | |||
f398266206 | |||
4c17f98520 | |||
df84ce6e90 | |||
7161378da1 | |||
224b612ae7 | |||
19d7522722 | |||
ceace2a678 | |||
d627454b2a | |||
7ccbfad6ad | |||
91f8a158d2 | |||
8925dcde01 | |||
530abac3a7 | |||
e702d9a881 | |||
b0aeccb793 | |||
43d8d748ce | |||
b43ea5c7d3 | |||
f56759222d | |||
c8b7bb570c | |||
d536b29550 | |||
ecbda018c5 | |||
5187311ff0 | |||
d9a94ac7b0 | |||
3526e322ef | |||
99cabd545d | |||
1f7f7b10de | |||
b2421b592a | |||
5322f4c62f | |||
7ab8647fc8 | |||
50c76f3d7e | |||
2f4c56176d | |||
7c5f38311b | |||
e568bc9c8d | |||
c2c4172634 | |||
73de5b5773 | |||
aa1fed0b16 | |||
22331ae9f1 | |||
8b436276bf | |||
c61db87fd6 | |||
388cb4df39 | |||
9feffb2972 | |||
acea5cdb24 | |||
55ed577b6a | |||
20b206a161 | |||
9c028a0ecc | |||
b677c3d7ad | |||
aa6bc2df2f | |||
a16579fd21 | |||
ae5a816df1 | |||
1532f2ab23 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ node_modules
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
aws.json
|
aws.json
|
||||||
docs/index.dev.html
|
docs/index.dev.html
|
||||||
|
*.mp4
|
||||||
|
62
bower.json
62
bower.json
@ -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"
|
||||||
}
|
}
|
46
bundles.json
46
bundles.json
@ -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"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
58
changelog.md
58
changelog.md
@ -1,17 +1,65 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.1.5
|
||||||
|
- Fix for incorrect `isFullscreen()` return value in Mozilla (Fixes #38)
|
||||||
|
|
||||||
|
## v1.1.4
|
||||||
|
- Minor bug fixes
|
||||||
|
|
||||||
|
## v1.1.3
|
||||||
|
- Fixes for random id used in controls with multiple instances and one call to setup
|
||||||
|
- Audio player UI improvements
|
||||||
|
|
||||||
|
## v1.1.2
|
||||||
|
- Added an onSetup callback option
|
||||||
|
- Added fullscreen API methods `toggleFullscreen()` (must be user iniated), and `isFullscreen()`
|
||||||
|
|
||||||
|
## 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 +68,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
|
||||||
|
24
controls.md
24
controls.md
@ -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
2
dist/plyr.css
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.js
vendored
2
dist/plyr.js
vendored
File diff suppressed because one or more lines are too long
2
dist/sprite.svg
vendored
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.3 KiB |
2
docs/dist/docs.css
vendored
2
docs/dist/docs.css
vendored
@ -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}}.actions{list-style:none;margin:0;padding:0;font-size:0}.actions li{display:inline-block;margin-top:10px;font-size:16px;font-size:1rem;white-space:nowrap}.actions li+li{margin-left:20px}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,.btn-count{display:inline-block;vertical-align:middle;border-radius:3px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-weight:600;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn{padding:10px 20px;background:#3498db;border:0;color:#fff}.btn:focus,.btn:hover{color:#fff;background:#258cd1}.btn-twitter{background:#8799A2}.btn-twitter:focus,.btn-twitter:hover{background:#798d97}.btn-count{position:relative;margin-left:6px;padding:9px;background:#fff;border:1px solid #cbd0d3}.btn-count::before{content:"";position:absolute;display:block;width:8px;height:8px;left:1px;top:50%;margin-top:-4px;background:inherit;border:inherit;border-width:1px 0 0 1px;-webkit-transform:rotate(-45deg) translate(-50%,-50%);transform:rotate(-45deg) translate(-50%,-50%)}.example-audio .player,.example-video .player{margin:0 auto 20px}.example-audio .player-controls,.example-video .player-controls{border-radius:0 0 4px 4px}.example-audio .player{max-width:520px}.example-audio .player-controls{border-radius:4px}.example-audio .player-progress{border-radius:4px 4px 0 0;overflow:hidden}.example-video .player{max-width:1200px}.example-video .player video{border-radius:4px 4px 0 0}.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
2
docs/dist/docs.js
vendored
File diff suppressed because one or more lines are too long
2
docs/dist/templates.js
vendored
2
docs/dist/templates.js
vendored
@ -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: { }});
|
@ -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.13/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>
|
159
docs/index.html
159
docs/index.html
@ -1,79 +1,100 @@
|
|||||||
<!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="https://cdn.plyr.io/1.1.13/plyr.css?1">
|
||||||
|
|
||||||
<!-- Docs styles -->
|
<!-- Docs styles -->
|
||||||
<link rel="stylesheet" href="//cdn.plyr.io/1.0.23/docs.css">
|
<link rel="stylesheet" href="https://cdn.plyr.io/1.1.13/docs.css?1">
|
||||||
</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 by <a href="https://twitter.com/sam_potts" target="_blank">@sam_potts</a></p>
|
||||||
<a href="https://github.com/selz/plyr" target="_blank" class="btn">Download on GitHub</a>
|
<ul class="actions">
|
||||||
</header>
|
<li>
|
||||||
|
<a href="https://github.com/selz/plyr" target="_blank" class="btn btn-download">Download on GitHub</a>
|
||||||
|
<span class="btn-count js-stargazers-count">…</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://twitter.com/intent/tweet?text=A+simple+HTML5+media+player+with+custom+controls+and+WebVTT+captions.&url=http%3A%2F%2Fplyr.io&via=Sam_Potts" target="_blank" class="btn btn-twitter js-popup" data-window-height="250" data-window-width="500">Tweet</a>
|
||||||
|
<span class="btn-count js-tweet-count">…</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</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="https://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="https://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="https://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="https://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>
|
<a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
|
||||||
<a href="//cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
</video>
|
<small>Big Buck Bunny. More info can be found at <a href="https://peach.blender.org" target="_blank">peach.blender.org</a>.</small>
|
||||||
</div>
|
</section>
|
||||||
<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 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="https://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="https://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>
|
<a href="https://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>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
</audio>
|
<small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small>
|
||||||
</div>
|
</section>
|
||||||
<small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small>
|
</main>
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>Used by …</p>
|
<p>Used by …</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.13/sprite.svg");
|
||||||
|
</script>
|
||||||
|
|
||||||
<!-- Docs script -->
|
<!-- Plyr core script -->
|
||||||
<script src="//cdn.plyr.io/1.0.23/docs.js"></script>
|
<script src="https://cdn.plyr.io/1.1.13/plyr.js?1"></script>
|
||||||
</body>
|
|
||||||
</html>
|
<!-- Docs script -->
|
||||||
|
<script src="https://cdn.plyr.io/1.1.13/docs.js?1"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
@ -7,13 +7,136 @@
|
|||||||
// Setup the player
|
// Setup the player
|
||||||
plyr.setup({
|
plyr.setup({
|
||||||
debug: true,
|
debug: true,
|
||||||
|
volume: 9,
|
||||||
title: "Video demo",
|
title: "Video demo",
|
||||||
html: templates.controls.render({}),
|
html: templates.controls.render({}),
|
||||||
captions: {
|
captions: {
|
||||||
defaultActive: true
|
defaultActive: true
|
||||||
|
},
|
||||||
|
onSetup: function() {
|
||||||
|
var player = this,
|
||||||
|
type = player.media.tagName.toLowerCase(),
|
||||||
|
toggle = document.querySelector("[data-toggle='fullscreen']");
|
||||||
|
|
||||||
|
console.log("✓ Setup done for <" + type + ">");
|
||||||
|
|
||||||
|
if(type === "video" && toggle) {
|
||||||
|
toggle.addEventListener("click", player.toggleFullscreen, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
function popup(event) {
|
||||||
|
// Prevent the link opening
|
||||||
|
if(event.target.nodeName.toLowerCase() == "a") {
|
||||||
|
if(event.preventDefault) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event.returnValue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var link = event.target,
|
||||||
|
url = link.href,
|
||||||
|
width = link.getAttribute("data-window-width") || 600,
|
||||||
|
height = link.getAttribute("data-window-height") || 600,
|
||||||
|
name = link.getAttribute("data-window-name") || "popup";
|
||||||
|
|
||||||
|
// If window exists, just focus it
|
||||||
|
if(window["window-"+name] && !window["window-"+name].closed) {
|
||||||
|
window["window-"+name].focus();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Get position
|
||||||
|
var left = window.screenLeft !== undefined ? window.screenLeft : screen.left;
|
||||||
|
var top = window.screenTop !== undefined ? window.screenTop : screen.top;
|
||||||
|
|
||||||
|
// Open in the centre of the screen
|
||||||
|
var x = (screen.width / 2) - (width / 2) + left,
|
||||||
|
y = (screen.height / 2) - (height / 2) + top;
|
||||||
|
|
||||||
|
// Open that window
|
||||||
|
window["window-"+name] = window.open(url, name, "top=" + y +",left="+ x +",width=" + width + ",height=" + height);
|
||||||
|
|
||||||
|
// Focus new window
|
||||||
|
window["window-"+name].focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger popups
|
||||||
|
document.querySelector(".js-popup").addEventListener("click", popup);
|
||||||
|
|
||||||
|
// Get JSONP
|
||||||
|
function getJSONP(url, callback) {
|
||||||
|
var name = "jsonp_callback_" + Math.round(100000 * Math.random());
|
||||||
|
|
||||||
|
// Cleanup to prevent memory leaks and hit original callback
|
||||||
|
window[name] = function(data) {
|
||||||
|
delete window[name];
|
||||||
|
document.body.removeChild(script);
|
||||||
|
callback(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a faux script
|
||||||
|
var script = document.createElement("script");
|
||||||
|
script.setAttribute("src", url + (url.indexOf("?") >= 0 ? "&" : "?") + "callback=" + name);
|
||||||
|
|
||||||
|
// Inject to the body
|
||||||
|
document.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get star count
|
||||||
|
var storageSupported = ("sessionStorage" in window),
|
||||||
|
selectors = {
|
||||||
|
github: ".js-stargazers-count",
|
||||||
|
twitter: ".js-tweet-count"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Display the count next to the button
|
||||||
|
function displayCount(selector, count) {
|
||||||
|
document.querySelector(selector).innerHTML = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add star
|
||||||
|
function formatGitHubCount(count) {
|
||||||
|
return "★ " + count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's in session storage first
|
||||||
|
if(storageSupported && "github_stargazers" in window.sessionStorage) {
|
||||||
|
displayCount(selectors.github, formatGitHubCount(window.sessionStorage.github_stargazers));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getJSONP("https://api.github.com/repos/selz/plyr?access_token=a46ac653210ba6a6be44260c29c333470c3fbbf5", function (json) {
|
||||||
|
if (json && typeof json.data.stargazers_count !== "undefined") {
|
||||||
|
// Update UI
|
||||||
|
displayCount(selectors.github, formatGitHubCount(json.data.stargazers_count));
|
||||||
|
|
||||||
|
// Store in session storage
|
||||||
|
window.sessionStorage.github_stargazers = json.data.stargazers_count;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get tweet count
|
||||||
|
if(storageSupported && "tweets" in window.sessionStorage) {
|
||||||
|
displayCount(selectors.twitter, window.sessionStorage.tweets);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getJSONP("https://cdn.api.twitter.com/1/urls/count.json?url=plyr.io", function (json) {
|
||||||
|
if (json && typeof json.count !== "undefined") {
|
||||||
|
// Update UI
|
||||||
|
displayCount(selectors.twitter, json.count);
|
||||||
|
|
||||||
|
// Store in session storage
|
||||||
|
window.sessionStorage.tweets = json.count;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Google analytics
|
// Google analytics
|
||||||
// For demo site (http://[www.]plyr.io) only
|
// For demo site (http://[www.]plyr.io) only
|
||||||
if(document.domain.indexOf("plyr.io") > -1) {
|
if(document.domain.indexOf("plyr.io") > -1) {
|
||||||
|
@ -12,153 +12,222 @@
|
|||||||
// 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;
|
||||||
|
@arrow-size: 8px;
|
||||||
|
|
||||||
// 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 {
|
.actions {
|
||||||
text-decoration: none;
|
list-style: none;
|
||||||
color: @link-color;
|
margin: 0;
|
||||||
border-bottom: 1px solid currentColor;
|
padding: 0;
|
||||||
transition: all .3s ease;
|
font-size: 0;
|
||||||
|
|
||||||
&:hover,
|
li {
|
||||||
&:focus {
|
display: inline-block;
|
||||||
color: #000;
|
margin-top: (@padding-base / 2);
|
||||||
}
|
.font-size();
|
||||||
&:focus {
|
white-space: nowrap;
|
||||||
.tab-focus();
|
}
|
||||||
}
|
li + li {
|
||||||
&.logo {
|
margin-left: @padding-base;
|
||||||
border: 0;
|
}
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: @link-color;
|
||||||
|
border-bottom: 1px solid currentColor;
|
||||||
|
transition: all .3s ease;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
.tab-focus();
|
||||||
|
}
|
||||||
|
&.logo {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn,
|
||||||
|
.btn-count {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
border-radius: 3px;
|
||||||
|
.font-smoothing(on);
|
||||||
|
font-weight: 600;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-block;
|
padding: (@padding-base / 2) @padding-base;
|
||||||
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);
|
&:hover,
|
||||||
font-weight: 600;
|
&:focus {
|
||||||
border-radius: 3px;
|
color: #fff;
|
||||||
user-select: none;
|
background: darken(@link-color, 5%);
|
||||||
|
}
|
||||||
&:hover,
|
|
||||||
&:focus {
|
&-twitter {
|
||||||
color: #fff;
|
background: #8799A2;
|
||||||
background: darken(@link-color, 5%);
|
|
||||||
}
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background: darken(#8799A2, 5%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn-count {
|
||||||
|
position: relative;
|
||||||
|
margin-left: 6px;
|
||||||
|
padding: ((@padding-base / 2) - 1px);
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid @gray-light;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
width: @arrow-size;
|
||||||
|
height: @arrow-size;
|
||||||
|
left: 1px;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -(@arrow-size / 2);
|
||||||
|
|
||||||
|
background: inherit;
|
||||||
|
border: inherit;
|
||||||
|
border-width: 1px 0 0 1px;
|
||||||
|
transform: rotate(-45deg) translate(-50%, -50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Players
|
// Example players
|
||||||
.example-audio .player {
|
|
||||||
max-width: 480px;
|
|
||||||
}
|
|
||||||
.example-video .player {
|
|
||||||
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,
|
&-controls {
|
||||||
&.fullscreen-active {
|
border-radius: 0 0 4px 4px;
|
||||||
max-width: none;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.example-audio .player {
|
||||||
|
max-width: 520px;
|
||||||
|
|
||||||
|
&-controls {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
&-progress {
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.example-video .player {
|
||||||
|
max-width: 1200px;
|
||||||
|
|
||||||
|
video {
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
|
&-fullscreen,
|
||||||
|
&.fullscreen-active {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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>
|
356
gulpfile.js
356
gulpfile.js
@ -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");
|
||||||
});
|
});
|
15
package.json
15
package.json
@ -1,27 +1,28 @@
|
|||||||
{
|
{
|
||||||
"name": "plyr",
|
"name": "plyr",
|
||||||
"version": "1.0.23",
|
"version": "1.1.13",
|
||||||
"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",
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"gulp": "~3.8.6",
|
"gulp": "^3.8.6",
|
||||||
"gulp-autoprefixer": "^0.0.8",
|
"gulp-autoprefixer": "^0.0.8",
|
||||||
"gulp-concat": "~2.3.3",
|
"gulp-concat": "^2.3.3",
|
||||||
"gulp-gzip": "^1.0.0",
|
"gulp-gzip": "^1.0.0",
|
||||||
"gulp-hogan-compile": "^0.4.1",
|
"gulp-hogan-compile": "^0.4.1",
|
||||||
"gulp-less": "~1.3.1",
|
"gulp-less": "^1.3.1",
|
||||||
"gulp-minify-css": "~0.3.6",
|
"gulp-minify-css": "^0.3.6",
|
||||||
"gulp-open": "^0.3.2",
|
"gulp-open": "^0.3.2",
|
||||||
"gulp-rename": "^1.2.0",
|
"gulp-rename": "^1.2.0",
|
||||||
"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",
|
||||||
"gulp-util": "~2.2.20",
|
"gulp-util": "^2.2.20",
|
||||||
"run-sequence": "^0.3.6"
|
"run-sequence": "^0.3.6"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
135
readme.md
135
readme.md
@ -3,14 +3,14 @@ A simple, accessible HTML5 media player.
|
|||||||
|
|
||||||
[Checkout the demo](http://plyr.io)
|
[Checkout the demo](http://plyr.io)
|
||||||
|
|
||||||
[](http://plyr.io)
|
[](http://plyr.io)
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
We wanted a lightweight, accessible and customisable media player that just supports *modern* 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* 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 captions and screen readers.
|
||||||
- **Lightweight** - just 5.7KB minified and gzipped.
|
- **Lightweight** - just 6.4KB minified and gzipped.
|
||||||
- **Customisable** - make the player look how you want with the markup you want.
|
- **Customisable** - make the player look how you want with the markup you want.
|
||||||
- **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks.
|
- **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks.
|
||||||
- **Responsive** - as you'd expect these days.
|
- **Responsive** - as you'd expect these days.
|
||||||
@ -25,11 +25,10 @@ Oh and yes, it works with Bootstrap.
|
|||||||
Check out [the changelog](changelog.md)
|
Check out [the changelog](changelog.md)
|
||||||
|
|
||||||
## Planned development
|
## Planned development
|
||||||
- Accept a string selector, a node, or a nodelist for the `container` property of `selectors`.
|
|
||||||
- Multiple language captions (with selection)
|
|
||||||
- Playlists (audio and video)
|
- Playlists (audio and video)
|
||||||
- Set source by API
|
- YouTube and Vimeo support
|
||||||
- Tooltip option (for seeking and controls)
|
- Playback speed
|
||||||
|
- Multiple language captions (with selection)
|
||||||
... and whatever else has been raised in [issues](https://github.com/Selz/plyr/issues)
|
... and whatever else has been raised in [issues](https://github.com/Selz/plyr/issues)
|
||||||
|
|
||||||
If you have any cool ideas or features, please let me know by [creating an issue](https://github.com/Selz/plyr/issues/new) or of course, forking and sending a pull request.
|
If you have any cool ideas or features, please let me know by [creating an issue](https://github.com/Selz/plyr/issues/new) or of course, forking and sending a pull request.
|
||||||
@ -38,7 +37,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.13/plyr.js` to `https://cdn.plyr.io/1.1.13/plyr.js`
|
||||||
|
|
||||||
### Bower
|
### Bower
|
||||||
If bower is your thang, you can grab Plyr using:
|
If bower is your thang, you can grab Plyr using:
|
||||||
@ -47,15 +46,22 @@ bower install plyr
|
|||||||
```
|
```
|
||||||
More info on setting up dependencies can be found in the [Bower Docs](http://bower.io/docs/creating-packages/#maintaining-dependencies)
|
More info on setting up dependencies can be found in the [Bower Docs](http://bower.io/docs/creating-packages/#maintaining-dependencies)
|
||||||
|
|
||||||
|
### Ember
|
||||||
|
The awesome [@louisrudner](https://twitter.com/louisrudner) has created an ember component, available by running:
|
||||||
|
```
|
||||||
|
ember addon:install ember-cli-plyr
|
||||||
|
```
|
||||||
|
More info is on [npm](https://www.npmjs.com/package/ember-cli-plyr) and [GitHub](https://github.com/louisrudner/ember-cli-plyr)
|
||||||
|
|
||||||
### CDN
|
### CDN
|
||||||
If you want to use our CDN, you can use the following. HTTPS (SSL) is supported.
|
If you want to use our CDN, you can use the following:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<link rel="stylesheet" href="//cdn.plyr.io/1.0.23/plyr.css">
|
<link rel="stylesheet" href="https://cdn.plyr.io/1.1.13/plyr.css">
|
||||||
<script src="//cdn.plyr.io/1.0.23/plyr.js"></script>
|
<script src="https://cdn.plyr.io/1.1.13/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 `https://cdn.plyr.io/1.1.13/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.
|
||||||
@ -92,18 +98,16 @@ and the AJAX technique here:
|
|||||||
The only extra markup that's needed to use plyr is a `<div>` wrapper. Replace the source, poster and captions with urls for your media.
|
The only extra markup that's needed to use plyr is a `<div>` wrapper. Replace the source, poster and captions with urls for your media.
|
||||||
```html
|
```html
|
||||||
<div class="player">
|
<div class="player">
|
||||||
<video poster="//cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin>
|
<video poster="https://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="https://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="https://cdn.selz.com/plyr/1.0/movie.webm" type="video/webm">
|
||||||
|
|
||||||
<!-- Text track file -->
|
<!-- Text track file -->
|
||||||
<track kind="captions" label="English captions" src="//cdn.selz.com/plyr/1.0/movie_captions_en.vtt" srclang="en" default>
|
<track kind="captions" label="English captions" src="https://cdn.selz.com/plyr/1.0/movie_captions_en.vtt" srclang="en" default>
|
||||||
|
|
||||||
<!-- Fallback for browsers that don't support the <video> element -->
|
<!-- Fallback for browsers that don't support the <video> element -->
|
||||||
<div>
|
<a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
|
||||||
<a href="//cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
|
|
||||||
</div>
|
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
@ -113,13 +117,11 @@ And the same for `<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="https://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="https://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>
|
<a href="https://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>
|
|
||||||
</audio>
|
</audio>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
@ -130,21 +132,17 @@ You'll notice the `crossorigin` attribute on the example `<video>` and `<audio>`
|
|||||||
More info on CORS here:
|
More info on CORS here:
|
||||||
[https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)
|
[https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)
|
||||||
|
|
||||||
###JavaScript
|
### JavaScript
|
||||||
Much of the behaviour of the player is configurable when initialising the library. Below is an example of a default instance.
|
Much of the behaviour of the player is configurable when initialising the library. Here's an example of a default setup:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="dist/plyr.js"></script>
|
<script src="dist/plyr.js"></script>
|
||||||
<script>
|
<script>plyr.setup();</script>
|
||||||
plyr.setup({
|
|
||||||
*options*
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Options
|
#### Options
|
||||||
|
|
||||||
You can pass the following options to the setup method.
|
You can pass the following options to the setup method using `plyr.setup({...})`.
|
||||||
|
|
||||||
<table class="table" width="100%">
|
<table class="table" width="100%">
|
||||||
<thead>
|
<thead>
|
||||||
@ -168,6 +166,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 +196,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><video></code>.</td>
|
<td>Click (or tap) will toggle pause/play of a <code><video></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 & :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 +224,25 @@ 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>—</td>
|
<td>—</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>—</td>
|
<td>—</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>—</td>
|
<td>—</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>
|
||||||
|
<td><code>onSetup</code></td>
|
||||||
|
<td>Function</td>
|
||||||
|
<td>—</td>
|
||||||
|
<td>This callback function is called on every new plyr instance created. The context (<code>this</code>) is the plyr instance itself.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -279,6 +301,11 @@ Here's a list of the methods supported:
|
|||||||
<td>Number</td>
|
<td>Number</td>
|
||||||
<td>Sets the player volume to the provided parameter. The value should be between 0 (muted) and 10 (loudest). If no parameter is provided, the default volume is used (5). Values over 10 are ignored.</td>
|
<td>Sets the player volume to the provided parameter. The value should be between 0 (muted) and 10 (loudest). If no parameter is provided, the default volume is used (5). Values over 10 are ignored.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>togglePlay()</code></td>
|
||||||
|
<td>Boolean</td>
|
||||||
|
<td>Toggles playback for the player based on either the boolean argument or it's current state.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>toggleMute()</code></td>
|
<td><code>toggleMute()</code></td>
|
||||||
<td>—</td>
|
<td>—</td>
|
||||||
@ -289,6 +316,16 @@ Here's a list of the methods supported:
|
|||||||
<td>—</td>
|
<td>—</td>
|
||||||
<td>Toggles whether captions are enabled.</td>
|
<td>Toggles whether captions are enabled.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>toggleFullscreen()</code></td>
|
||||||
|
<td>Event</td>
|
||||||
|
<td>Toggles fullscreen. This can only be initiated by a user gesture due to browser security, i.e. a user event such as click.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>isFullscreen()</code></td>
|
||||||
|
<td>—</td>
|
||||||
|
<td>Boolean returned if the player is in fullscreen.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>support(...)</code></td>
|
<td><code>support(...)</code></td>
|
||||||
<td>String</td>
|
<td>String</td>
|
||||||
@ -309,11 +346,21 @@ Here's a list of the methods supported:
|
|||||||
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.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>poster(...)</code></td>
|
<td><code>poster(...)</code></td>
|
||||||
<td>String</td>
|
<td>String</td>
|
||||||
<td>Set the poster url. This is supported for the <code>video</code> element only.</td>
|
<td>Set the poster url. This is supported for the <code>video</code> element only.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>destroy()</code></td>
|
||||||
|
<td>—</td>
|
||||||
|
<td>Destroys the plyr UI and any media event listeners, effectively restoring to the previous state before <code>setup()</code> was called.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>restore()</code></td>
|
||||||
|
<td>—</td>
|
||||||
|
<td>Reverses the effects of the <code>destroy()</code> method, restoring the UI and listeners.</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -332,11 +379,12 @@ A complete list of events can be found here:
|
|||||||
[Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html)
|
[Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html)
|
||||||
|
|
||||||
## Fullscreen
|
## Fullscreen
|
||||||
|
|
||||||
Fullscreen in Plyr is supported for all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). If you're using the default CSS, you can also use a "full browser" mode which will use the full browser window by adding the `player-fullscreen` class to your container.
|
Fullscreen in Plyr is supported for all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). If you're using the default CSS, you can also use a "full browser" mode which will use the full browser window by adding the `player-fullscreen` class to your container.
|
||||||
|
|
||||||
## Browser support
|
## Browser support
|
||||||
|
|
||||||
<table width="100%" style="text-align: center;">
|
<table width="100%" style="text-align: center">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Safari</td>
|
<td>Safari</td>
|
||||||
@ -353,15 +401,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>✖²</td>
|
<td>API²</td>
|
||||||
<td>✔³</td>
|
<td>✔³</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
¹ iPhone forces the native player for `<video>` so no customisation possible
|
¹ Mobile Safari on the iPhone forces the native player for `<video>` so no useful customisation is possible. `<audio>` elements have volume controls disabled.
|
||||||
|
|
||||||
² Native player used (no support for `<progress>` or `<input type="range">`)
|
² Native player used (no support for `<progress>` or `<input type="range">`) but the API is supported (v1.0.28+)
|
||||||
|
|
||||||
³ IE10 has no native fullscreen support, fallback can be used (see options)
|
³ IE10 has no native fullscreen support, fallback can be used (see options)
|
||||||
|
|
||||||
@ -374,19 +422,24 @@ If a User Agent is disabled but supports `<video>` and `<audio>` natively, it wi
|
|||||||
|
|
||||||
Any unsupported browsers will display links to download the media if the correct html is used.
|
Any unsupported browsers will display links to download the media if the correct html is used.
|
||||||
|
|
||||||
|
### Checking for support
|
||||||
|
There's an API method for checking support. You can call `plyr.supported()` and optionally pass a type to it, e.g. `plyr.supported("video")`. It will return an object with two keys; `basic` meaning there's basic support for that media type (or both if no type is passed) and `full` meaning there's full support for plyr.
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
If you find anything weird with Plyr, please let us know using the GitHub issues tracker.
|
If you find anything weird with Plyr, please let us know using the GitHub issues tracker.
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
Plyr is developed by Sam Potts ([@sam_potts](https://twitter.com/sam_potts)) ([sampotts.me](http://sampotts.me))
|
Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me](http://sampotts.me) with help from the awesome [contributors](https://github.com/Selz/plyr/graphs/contributors)
|
||||||
|
|
||||||
## 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)
|
||||||
@ -404,4 +457,4 @@ Also these links helped created Plyr:
|
|||||||
- [Styling the `<progress>` element - hongkiat.com](http://www.hongkiat.com/blog/html5-progress-bar/)
|
- [Styling the `<progress>` element - hongkiat.com](http://www.hongkiat.com/blog/html5-progress-bar/)
|
||||||
|
|
||||||
## Copyright and License
|
## Copyright and License
|
||||||
[The MIT license](license.md).
|
[The MIT license](license.md).
|
||||||
|
991
src/js/plyr.js
991
src/js/plyr.js
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
Reference in New Issue
Block a user