Compare commits

...

68 Commits

Author SHA1 Message Date
4f0633fdc1 SASS for previous change 2015-06-08 21:46:47 +10:00
f41854ebe7 Minor tweak to hiding controls in fullscreen 2015-06-08 21:43:49 +10:00
f398266206 Chrome Canary Fix 2015-06-07 23:20:33 +10:00
4c17f98520 TogglePlay API method (Fixes #86), Volume border (Fixes #87), Chrome Subs (Fixes #90) 2015-06-07 23:00:26 +10:00
df84ce6e90 Docs 2015-05-18 15:11:16 +10:00
7161378da1 Bug fix 2015-05-18 15:10:40 +10:00
224b612ae7 Bug fix 2015-05-18 14:46:21 +10:00
19d7522722 Fixes bug with 1.1.8 volume 2015-05-18 14:43:45 +10:00
ceace2a678 setVolume() API method improvements (Fixes #83) 2015-05-18 13:50:44 +10:00
d627454b2a Restore classname on destroy 2015-05-17 17:33:46 +10:00
7ccbfad6ad New API methods (fixes #77), Fix for non strict mode (fixes #78) 2015-05-17 17:23:09 +10:00
91f8a158d2 Update index.html 2015-04-19 23:47:46 +10:00
8925dcde01 Update readme.md 2015-04-19 23:45:25 +10:00
530abac3a7 Update readme.md 2015-04-15 01:15:05 +10:00
e702d9a881 Update readme.md 2015-04-15 01:14:36 +10:00
b0aeccb793 Update readme.md 2015-04-11 11:19:19 +10:00
43d8d748ce Merge pull request #76 from robinpoort/feature/sass-variables
Make SCSS variables optional
2015-04-11 09:29:04 +10:00
b43ea5c7d3 adding !default to variables so they are easily overwritable 2015-04-10 15:13:02 +02:00
f56759222d Update readme.md 2015-04-10 13:38:49 +10:00
c8b7bb570c Update readme.md 2015-04-10 13:37:55 +10:00
d536b29550 Update readme.md 2015-04-10 13:36:51 +10:00
ecbda018c5 Merge branch 'master' of github.com:selz/plyr
# Conflicts:
#	src/js/plyr.js
2015-04-10 07:17:23 +10:00
5187311ff0 Bug fix for isFullscreen() in Mozilla (Fixes #38) 2015-04-10 07:16:53 +10:00
d9a94ac7b0 Version bump 2015-04-08 13:42:34 +10:00
3526e322ef Minor bug fixes 2015-04-06 19:42:26 +10:00
99cabd545d Fix for generated IDs for controls, UI tweak for audio 2015-04-06 13:25:36 +10:00
1f7f7b10de Docs tweak 2015-04-06 12:06:34 +10:00
b2421b592a Merge branch 'master' of github.com:selz/plyr 2015-04-06 11:47:43 +10:00
5322f4c62f Fullscreen API methods (Fixes #74), onSetup callback 2015-04-06 11:47:23 +10:00
7ab8647fc8 Merge pull request #75 from franks921/fs-fix-localstorage-volume-settings
fix: use custom localStorage key for volume setting
2015-04-05 21:39:08 +10:00
50c76f3d7e fix: use custom localStorage key for volume setting 2015-04-05 13:26:17 +02:00
2f4c56176d Updated screenshot 2015-04-04 12:58:09 +11:00
7c5f38311b Bug fixes for controls changes 2015-04-04 12:51:24 +11:00
e568bc9c8d Controls improvements
- Added an option to toggle which controls display
- Better handle missing controls
2015-04-04 12:32:37 +11:00
c2c4172634 Clarified the option 2015-03-30 21:04:38 +11:00
73de5b5773 Added displayDuration option, small bug fix
- Using the native VTT cues, sometimes cues would not disappear
2015-03-30 21:03:48 +11:00
aa1fed0b16 Fixed bug with media longer than 60 minutes (Fixes #69) 2015-03-30 19:17:27 +11:00
22331ae9f1 Added mention 2015-03-22 23:24:15 +11:00
8b436276bf Fixed bug with caption toggle, hide controls in fullscreen 2015-03-22 21:26:29 +11:00
c61db87fd6 API improvements 2015-03-22 11:05:28 +11:00
388cb4df39 Keyboard accessibility improvements (Fixes #66)
- Enter now works on checkboxes within the controls
2015-03-21 17:00:05 +11:00
9feffb2972 Version bump 2015-03-15 10:18:56 +11:00
acea5cdb24 Built js 2015-03-15 10:14:00 +11:00
55ed577b6a Indentation
Converted to 4 space width tabbing
2015-03-15 10:12:36 +11:00
20b206a161 Merge pull request #62 from brunowego/patch-1
Updated SASS support
2015-03-15 10:00:00 +11:00
9c028a0ecc Updated SASS support 2015-03-14 15:50:32 -03:00
b677c3d7ad Merge branch 'master' of https://github.com/selz/plyr
Conflicts:
	dist/plyr.js
	src/js/plyr.js
2015-03-10 23:57:36 +11:00
aa6bc2df2f Fixes for volume control on iOS 2015-03-10 23:54:52 +11:00
a16579fd21 Fix for repo url 2015-03-09 11:53:26 +11:00
ae5a816df1 Fix for potential issue with .tagName 2015-03-09 11:51:01 +11:00
1532f2ab23 Added tooltip option (Fixes #50) 2015-03-09 00:47:38 +11:00
5370fc5c83 Loading state handling
Fixes #36
2015-03-08 01:24:23 +11:00
8482a1a320 Updated captions 2015-03-07 19:39:01 +11:00
f3603ac3fa Size updated 2015-03-07 19:27:11 +11:00
44fe647a49 Typo 2015-03-07 19:25:25 +11:00
928a89e599 More formatting 2015-03-07 19:24:41 +11:00
80d6d806c4 Formatting 2015-03-07 19:21:54 +11:00
aeecf40191 Slight tweaks 2015-03-07 19:17:57 +11:00
f368ed572d source(), poster() and supports() API methods 2015-03-07 19:12:56 +11:00
5291bf616e More work on source change 2015-03-07 12:24:07 +11:00
a00407a475 Removed extra log 2015-03-06 17:47:08 +11:00
4f47ec49b1 Work on source update and caption fixes 2015-03-06 17:46:06 +11:00
c48afb7880 Merge remote-tracking branch 'origin/master' into develop 2015-03-06 12:21:51 +11:00
5d3fb359b8 Note about demo code 2015-03-06 12:20:47 +11:00
0227dfa7d8 Working on source() api method 2015-03-06 01:51:12 +11:00
b9915b4b94 Removed notes 2015-03-06 01:50:37 +11:00
f4c1313c19 Updated screenshot 2015-03-05 23:36:45 +11:00
7681d63876 Removed progress transition as it feels laggy 2015-03-05 23:27:53 +11:00
25 changed files with 2934 additions and 1741 deletions

1
.gitignore vendored
View File

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

View File

@ -1,33 +1,33 @@
{
"name": "plyr",
"description": "A simple HTML5 media player using custom controls",
"homepage": "http://plyr.io",
"keywords": [
"Audio",
"Video",
"HTML5 Audio",
"HTml5 Video"
],
"authors": [
"Sam Potts <me@sampotts.me>"
],
"dependencies": {},
"main": [
"dist/plyr.css",
"dist/plyr.js",
"dist/sprite.svg",
"src/less/plyr.less",
"src/sass/plyr.sass",
"src/js/plyr.js"
],
"ignore": [
"node_modules",
"bower_components",
".gitignore"
],
"repository": {
"type": "git",
"url": "git://github.com/selz/plyr.git"
},
"license": "MIT"
"name": "plyr",
"description": "A simple HTML5 media player using custom controls",
"homepage": "http://plyr.io",
"keywords": [
"Audio",
"Video",
"HTML5 Audio",
"HTml5 Video"
],
"authors": [
"Sam Potts <me@sampotts.me>"
],
"dependencies": {},
"main": [
"dist/plyr.css",
"dist/plyr.js",
"dist/sprite.svg",
"src/less/plyr.less",
"src/sass/plyr.sass",
"src/js/plyr.js"
],
"ignore": [
"node_modules",
"bower_components",
".gitignore"
],
"repository": {
"type": "git",
"url": "git://github.com/selz/plyr.git"
},
"license": "MIT"
}

View File

@ -1,25 +1,25 @@
{
"plyr": {
"less": {
"plyr.css": ["src/less/plyr.less"]
},
"sass": {
"plyr.css": ["src/less/plyr.sass"]
},
"js": {
"plyr.js": ["src/js/plyr.js"]
}
},
"docs": {
"less": {
"docs.css": ["docs/src/less/docs.less"]
},
"js": {
"docs.js": [
"docs/src/js/lib/hogan-3.0.2.mustache.js",
"docs/dist/templates.js",
"docs/src/js/docs.js"
]
}
}
"plyr": {
"less": {
"plyr.css": ["src/less/plyr.less"]
},
"sass": {
"plyr.css": ["src/less/plyr.sass"]
},
"js": {
"plyr.js": ["src/js/plyr.js"]
}
},
"docs": {
"less": {
"docs.css": ["docs/src/less/docs.less"]
},
"js": {
"docs.js": [
"docs/src/js/lib/hogan-3.0.2.mustache.js",
"docs/dist/templates.js",
"docs/src/js/docs.js"
]
}
}
}

View File

@ -1,8 +1,65 @@
# 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
- Handling loading states in the UI (Fixes #36)
## v1.0.22
- Added support() API method for checking mimetype support
- Added source() API method for setting media source(s) (Fixes #44)
- Added poster() API method for setting poster source
- Refactored captions logic for manual captions
## v1.0.21
- Added an <input type="range"> for seeking to improve experience (and support dragging)
- Icons for restart and captions improved (and some IDs changed)
- 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) (Fixes #49)
## v1.0.20
- Default controls included (Fixes #45)
@ -11,7 +68,7 @@
- License changed to MIT
## v1.0.19
- Fixed firefox fullscreen issue (#38)
- Fixed firefox fullscreen issue (Fixes #38)
## v1.0.18
- Added CDN references

View File

@ -2,7 +2,7 @@
This is the markup that is rendered for the Plyr controls. You can use the default controls or provide a customized version of markup based on your needs.
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
@ -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)
- `{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
["<div class='player-controls'>",
@ -31,14 +31,14 @@ This is the default `html` option from `plyr.js`.
"<span>0</span>% buffered",
"</progress>",
"</div>",
"<span class='player-controls-playback'>",
"<span class='player-controls-left'>",
"<button type='button' data-player='restart'>",
"<svg><use xlink:href='#icon-restart'></use></svg>",
"<span class='sr-only'>Restart</span>",
"</button>",
"<button type='button' data-player='rewind'>",
"<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 type='button' data-player='play'>",
"<svg><use xlink:href='#icon-play'></use></svg>",
@ -50,14 +50,18 @@ This is the default `html` option from `plyr.js`.
"</button>",
"<button type='button' data-player='fast-forward'>",
"<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>",
"<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>",
"</span>",
"<span class='player-controls-sound'>",
"<span class='player-controls-right'>",
"<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>",
"<label id='mute{id}' for='mute{id}'>",
"<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'>",
"<svg class='icon-exit-fullscreen'><use xlink:href='#icon-exit-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>",
"</span>",
"</div>"].join("\n");

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

2
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
View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

@ -1,18 +1,18 @@
<!doctype html>
<html lang="en" class="error">
<head>
<meta charset="utf-8" />
<title>Doh. Looks like something went wrong.</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<head>
<meta charset="utf-8" />
<title>Doh. Looks like something went wrong.</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.21/docs.css">
</head>
<body>
<main>
<h1>Doh.</h1>
<p>Looks like something went wrong.</p>
<a href="http://plyr.io" class="btn">Back to plyr.io</a>
</main>
</body>
<!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.1.13/docs.css">
</head>
<body>
<main>
<h1>Doh.</h1>
<p>Looks like something went wrong.</p>
<a href="http://plyr.io" class="btn">Back to plyr.io</a>
</main>
</body>
</html>

View File

@ -1,79 +1,100 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<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="author" content="Sam Potts">
<meta name="viewport" content="width=device-width, initial-scale=1">
<head>
<meta charset="utf-8" />
<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="author" content="Sam Potts">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.21/plyr.css">
<!-- Styles -->
<link rel="stylesheet" href="https://cdn.plyr.io/1.1.13/plyr.css?1">
<!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.21/docs.css">
</head>
<body>
<header>
<h1>Plyr</h1>
<p>A simple HTML5 media player with custom controls and WebVTT captions.</p>
<a href="https://github.com/selz/plyr" target="_blank" class="btn">Download on GitHub</a>
</header>
<!-- Docs styles -->
<link rel="stylesheet" href="https://cdn.plyr.io/1.1.13/docs.css?1">
</head>
<body>
<header>
<h1>Plyr</h1>
<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>
<ul class="actions">
<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">&hellip;</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">&hellip;</span>
</li>
</ul>
</header>
<main>
<section class="example-video">
<div class="player">
<video poster="//cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin>
<!-- Video files -->
<source src="//cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4">
<source src="//cdn.selz.com/plyr/1.0/movie.webm" type="video/webm">
<!-- Text track file -->
<track kind="captions" label="English" srclang="en" src="//cdn.selz.com/plyr/1.0/movie_en_captions.vtt" default>
<!-- Fallback for browsers that don't support the <video> element -->
<div>
<a href="//cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
</div>
</video>
</div>
<small>Big Buck Bunny. More info can be found at <a href="https://peach.blender.org" target="_blank">peach.blender.org</a>.</small>
</section>
<main>
<section class="example-video">
<div class="player">
<video poster="https://cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin>
<!-- Video files -->
<source src="https://cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4">
<source src="https://cdn.selz.com/plyr/1.0/movie.webm" type="video/webm">
<!-- Text track file -->
<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 -->
<a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
</video>
</div>
<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">
<div class="player">
<audio controls>
<!-- Audio files -->
<source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3" type="audio/mp3">
<source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.ogg" type="audio/ogg">
<!-- Fallback for browsers that don't support the <audio> element -->
<div>
<a href="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a>
</div>
</audio>
</div>
<small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small>
</section>
</main>
<section class="example-audio">
<div class="player">
<audio controls>
<!-- Audio files -->
<source src="https://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.ogg" type="audio/ogg">
<!-- Fallback for browsers that don't support the <audio> element -->
<a href="https://cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a>
</audio>
</div>
<small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small>
</section>
</main>
<footer>
<p>Used by &hellip;</p>
<a href="https://selz.com" target="_blank" class="logo">
<img src="https://d33i624pw6jj68.cloudfront.net/static/img/logos/selz.svg" alt="Selz">
</a>
</footer>
<footer>
<p>Used by &hellip;</p>
<a href="https://selz.com" target="_blank" class="logo">
<img src="https://d33i624pw6jj68.cloudfront.net/static/img/logos/selz.svg" alt="Selz">
</a>
</footer>
<!-- Load SVG defs -->
<!-- You should bundle all SVG/Icons into one file using a build tool such as gulp and svg store -->
<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.21/sprite.svg");
</script>
<!-- Load SVG defs -->
<!-- You should bundle all SVG/Icons into one file using a build tool such as gulp and svg store -->
<script>
(function(d, u){
var a = new XMLHttpRequest(),
b = d.body;
<!-- Plyr core script -->
<script src="//cdn.plyr.io/1.0.21/plyr.js"></script>
// Check for CORS support
// 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 -->
<script src="//cdn.plyr.io/1.0.21/docs.js"></script>
</body>
</html>
<!-- Plyr core script -->
<script src="https://cdn.plyr.io/1.1.13/plyr.js?1"></script>
<!-- Docs script -->
<script src="https://cdn.plyr.io/1.1.13/docs.js?1"></script>
</body>
</html>

View File

@ -7,13 +7,136 @@
// Setup the player
plyr.setup({
debug: true,
volume: 9,
title: "Video demo",
html: templates.controls.render({}),
captions: {
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 "&bigstar; " + 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
// For demo site (http://[www.]plyr.io) only
if(document.domain.indexOf("plyr.io") > -1) {

View File

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

View File

@ -1,16 +1,16 @@
@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-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;
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;
}

View File

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

View File

@ -1,62 +1,66 @@
<div class="player-controls">
<div class="player-progress">
<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">
<progress class="player-progress-played" max="100" value="0">
<span>0</span>% played
</progress>
<progress class="player-progress-buffer" max="100" value="0">
<span>0</span>% buffered
</progress>
</div>
<span class="player-controls-playback">
<button type="button" data-player="restart">
<svg><use xlink:href="#icon-restart"></use></svg>
<span class="sr-only">Restart</span>
</button>
<button type="button" data-player="rewind">
<svg><use xlink:href="#icon-rewind"></use></svg>
<span class="sr-only">Rewind {seektime} seconds</span>
</button>
<button type="button" data-player="play">
<svg><use xlink:href="#icon-play"></use></svg>
<span class="sr-only">Play</span>
</button>
<button type="button" data-player="pause">
<svg><use xlink:href="#icon-pause"></use></svg>
<span class="sr-only">Pause</span>
</button>
<button type="button" data-player="fast-forward">
<svg><use xlink:href="#icon-fast-forward"></use></svg>
<span class="sr-only">Fast forward {seektime} seconds</span>
</button>
<span class="player-time">
<span class="sr-only">Time</span>
<span class="player-duration">00:00</span>
</span>
</span>
<span class="player-controls-sound">
<input class="inverted sr-only" id="mute{id}" type="checkbox" data-player="mute">
<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>
<div class="player-progress">
<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">
<progress class="player-progress-played" max="100" value="0">
<span>0</span>% played
</progress>
<progress class="player-progress-buffer" max="100" value="0">
<span>0</span>% buffered
</progress>
</div>
<span class="player-controls-left">
<button type="button" data-player="restart">
<svg><use xlink:href="#icon-restart"></use></svg>
<span class="sr-only">Restart</span>
</button>
<button type="button" data-player="rewind">
<svg><use xlink:href="#icon-rewind"></use></svg>
<span class="sr-only">Rewind {seektime} secs</span>
</button>
<button type="button" data-player="play">
<svg><use xlink:href="#icon-play"></use></svg>
<span class="sr-only">Play</span>
</button>
<button type="button" data-player="pause">
<svg><use xlink:href="#icon-pause"></use></svg>
<span class="sr-only">Pause</span>
</button>
<button type="button" data-player="fast-forward">
<svg><use xlink:href="#icon-fast-forward"></use></svg>
<span class="sr-only">Forward {seektime} secs</span>
</button>
<span class="player-time">
<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>
</span>
<span class="player-controls-right">
<input class="inverted sr-only" id="mute{id}" type="checkbox" data-player="mute">
<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>
<input id="volume{id}" class="player-volume" type="range" min="0" max="10" step="0.5" value="0" data-player="volume">
<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 class="sr-only" id="captions{id}" type="checkbox" data-player="captions">
<label for="captions{id}">
<svg class="icon-captions-on"><use xlink:href="#icon-captions-on"></use></svg>
<svg><use xlink:href="#icon-captions-off"></use></svg>
<span class="sr-only">Toggle Captions</span>
</label>
<input class="sr-only" id="captions{id}" type="checkbox" data-player="captions">
<label for="captions{id}">
<svg class="icon-captions-on"><use xlink:href="#icon-captions-on"></use></svg>
<svg><use xlink:href="#icon-captions-off"></use></svg>
<span class="sr-only">Toggle Captions</span>
</label>
<button type="button" data-player="fullscreen">
<svg class="icon-exit-fullscreen"><use xlink:href="#icon-exit-fullscreen"></use></svg>
<svg><use xlink:href="#icon-enter-fullscreen"></use></svg>
<span class="sr-only">Toggle fullscreen</span>
</button>
</span>
<button type="button" data-player="fullscreen">
<svg class="icon-exit-fullscreen"><use xlink:href="#icon-exit-fullscreen"></use></svg>
<svg><use xlink:href="#icon-enter-fullscreen"></use></svg>
<span class="sr-only">Toggle Fullscreen</span>
</button>
</span>
</div>

View File

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

View File

@ -1,9 +0,0 @@
Loading
--------------
http://stackoverflow.com/questions/8685038/tell-whether-video-is-loaded-or-not-in-javascript
http://stackoverflow.com/questions/5181865/checking-if-a-html5-video-is-ready
Events
--------------
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events

View File

@ -1,27 +1,28 @@
{
"name": "plyr",
"version": "1.0.21",
"version": "1.1.13",
"description": "A simple HTML5 media player using custom controls",
"homepage": "http://plyr.io",
"main": "gulpfile.js",
"dependencies": {},
"devDependencies": {
"gulp": "~3.8.6",
"gulp": "^3.8.6",
"gulp-autoprefixer": "^0.0.8",
"gulp-concat": "~2.3.3",
"gulp-concat": "^2.3.3",
"gulp-gzip": "^1.0.0",
"gulp-hogan-compile": "^0.4.1",
"gulp-less": "~1.3.1",
"gulp-minify-css": "~0.3.6",
"gulp-less": "^1.3.1",
"gulp-minify-css": "^0.3.6",
"gulp-open": "^0.3.2",
"gulp-rename": "^1.2.0",
"gulp-replace": "^0.5.3",
"gulp-s3": "^0.3.0",
"gulp-sass": "^1.3.3",
"gulp-size": "^1.2.1",
"gulp-svgmin": "^1.0.0",
"gulp-svgstore": "^5.0.0",
"gulp-uglify": "~0.3.1",
"gulp-util": "~2.2.20",
"gulp-uglify": "^0.3.1",
"gulp-util": "^2.2.20",
"run-sequence": "^0.3.6"
},
"scripts": {

188
readme.md
View File

@ -3,14 +3,14 @@ A simple, accessible HTML5 media player.
[Checkout the demo](http://plyr.io)
[![Image of Plyr](https://cdn.plyr.io/static/plyr.png)](http://plyr.io)
[![Image of Plyr](https://cdn.plyr.io/static/plyr.png?2)](http://plyr.io)
## 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.
## Features
- **Accessible** - full support for captions and screen readers.
- **Lightweight** - just 5.3KB minified and gzipped.
- **Lightweight** - just 6.4KB minified and gzipped.
- **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.
- **Responsive** - as you'd expect these days.
@ -25,18 +25,19 @@ Oh and yes, it works with Bootstrap.
Check out [the changelog](changelog.md)
## 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)
- Set source by API
- Tooltip option (for seeking and controls)
- YouTube and Vimeo support
- Playback speed
- Multiple language captions (with selection)
... 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.
## Implementation
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.1.13/plyr.js` to `https://cdn.plyr.io/1.1.13/plyr.js`
### Bower
If bower is your thang, you can grab Plyr using:
@ -45,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)
### 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
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
<link rel="stylesheet" href="//cdn.plyr.io/1.0.21/plyr.css">
<script src="//cdn.plyr.io/1.0.21/plyr.js"></script>
<link rel="stylesheet" href="https://cdn.plyr.io/1.1.13/plyr.css">
<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.21/sprite.svg`.
You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.1.13/sprite.svg`.
### 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.
@ -90,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.
```html
<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 -->
<source src="//cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4">
<source src="//cdn.selz.com/plyr/1.0/movie.webm" type="video/webm">
<source src="https://cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4">
<source src="https://cdn.selz.com/plyr/1.0/movie.webm" type="video/webm">
<!-- 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 -->
<div>
<a href="//cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
</div>
<a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a>
</video>
</div>
```
@ -111,13 +117,11 @@ And the same for `<audio>`
<div class="player">
<audio controls>
<!-- Audio files -->
<source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3" type="audio/mp3">
<source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.ogg" type="audio/ogg">
<source src="https://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.ogg" type="audio/ogg">
<!-- Fallback for browsers that don't support the <audio> element -->
<div>
<a href="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a>
</div>
<a href="https://cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a>
</audio>
</div>
```
@ -128,21 +132,17 @@ You'll notice the `crossorigin` attribute on the example `<video>` and `<audio>`
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)
###JavaScript
Much of the behaviour of the player is configurable when initialising the library. Below is an example of a default instance.
### JavaScript
Much of the behaviour of the player is configurable when initialising the library. Here's an example of a default setup:
```html
<script src="dist/plyr.js"></script>
<script>
plyr.setup({
*options*
});
</script>
<script>plyr.setup();</script>
```
#### 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%">
<thead>
@ -166,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>See <a href="controls.md">controls.md</a> for more info on how the html needs to be structured.</td>
</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>
<td><code>debug</code></td>
<td>Boolean</td>
@ -188,13 +194,25 @@ You can pass the following options to the setup method.
<td><code>click</code></td>
<td>Boolean</td>
<td><code>true</code></td>
<td>Click (or tap) will toggle pause/play of a `<video>`.</td>
<td>Click (or tap) will toggle pause/play of a <code>&lt;video&gt;</code>.</td>
</tr>
<tr>
<td><code>tooltips</code></td>
<td>Boolean</td>
<td><code>false</code></td>
<td>Display control labels as tooltips on :hover &amp; :focus (by default, the labels are screen reader only).</td>
</tr>
<tr>
<td><code>displayDuration</code></td>
<td>Boolean</td>
<td><code>true</code></td>
<td>Displays the duration of the media on the "metadataloaded" event (on startup) in the current time display. This will only work if the `preload` attribute is not set to `none` (or is not set at all) and you choose not to display the duration (see <code>controls</code> option).</td>
</tr>
<tr>
<td><code>selectors</code></td>
<td>Object</td>
<td>&mdash;</td>
<td>See `plyr.js` in `/src` for more info. The only option you might want to change is `player` which is the hook used for Plyr, the default is `.player`.</td>
<td>See <code>plyr.js</code> in <code>/src</code> for more info. The only option you might want to change is <code>player</code> which is the hook used for Plyr, the default is <code>.player</code>.</td>
</tr>
<tr>
<td><code>classes</code></td>
@ -206,19 +224,25 @@ You can pass the following options to the setup method.
<td><code>captions</code></td>
<td>Object</td>
<td>&mdash;</td>
<td>This currently contains one property `defaultActive` which toggles if captions should be on by default. The default value is `false`.</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>
<td><code>fullscreen</code></td>
<td>Object</td>
<td>&mdash;</td>
<td>This currently contains two properties; `enabled` which toggles if fullscreen should be enabled (if the browser supports it). The default value is `true`. Also an extra property called `fallback` which will enable a 'full window' view for older browsers. The default value is `true`.</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>
<td><code>storage</code></td>
<td>Object</td>
<td>&mdash;</td>
<td>This currently contains one property `enabled` which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later.</td>
<td>Two properties; <code>enabled</code> which toggles if local storage should be enabled (if the browser supports it). The default value is `true`. This enables storing user settings, currently it only stores volume but more will be added later. The second property <code>key</code> is the key used for the local storage. The default is <code>plyr_volume</code> until more settings are stored.</td>
</tr>
<tr>
<td><code>onSetup</code></td>
<td>Function</td>
<td>&mdash;</td>
<td>This callback function is called on every new plyr instance created. The context (<code>this</code>) is the plyr instance itself.</td>
</tr>
</tbody>
</table>
@ -243,50 +267,100 @@ Here's a list of the methods supported:
</thead>
<tbody>
<tr>
<td><code>play</code></td>
<td><code>play()</code></td>
<td>&mdash;</td>
<td>Plays the media</td>
</tr>
<tr>
<td><code>pause</code></td>
<td><code>pause()</code></td>
<td>&mdash;</td>
<td>Pauses the media</td>
</tr>
<tr>
<td><code>restart</code></td>
<td><code>restart()</code></td>
<td>&mdash;</td>
<td>Restarts playback</td>
</tr>
<tr>
<td><code>rewind</code></td>
<td><code>rewind(...)</code></td>
<td>Number</td>
<td>Rewinds by the provided parameter, in seconds. If no parameter is provided, the default seekInterval is used (10 seconds).</td>
</tr>
<tr>
<td><code>forward</code></td>
<td><code>forward(...)</code></td>
<td>Number</td>
<td>Fast forwards by the provided parameter, in seconds. If no parameter is provided, the default seekInterval is used (10 seconds).</td>
</tr>
<tr>
<td><code>seek</code></td>
<td><code>seek(...)</code></td>
<td>Number</td>
<td>Seeks the media to the provided parameter, time in seconds.</td>
</tr>
<tr>
<td><code>setVolume</code></td>
<td><code>setVolume(...)</code></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>
</tr>
<tr>
<td><code>toggleMute</code></td>
<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>
<td><code>toggleMute()</code></td>
<td>&mdash;</td>
<td>Toggles mute for the player.</td>
</tr>
<tr>
<td><code>toggleCaptions</code></td>
<td><code>toggleCaptions()</code></td>
<td>&mdash;</td>
<td>Toggles whether captions are enabled.</td>
</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>&mdash;</td>
<td>Boolean returned if the player is in fullscreen.</td>
</tr>
<tr>
<td><code>support(...)</code></td>
<td>String</td>
<td>Determine if a player supports a certain MIME type.</td>
</tr>
<tr>
<td><code>source(...)</code></td>
<td>String or Array</td>
<td>
Set the media source.
<br><br>
<strong>string</strong><br>
<code>.source("/path/to/video.mp4")</code><br>
This will set the <code>src</code> attribute on the <code>video</code> or <code>audio</code> element.
<br><br>
<strong>array</strong><br>
<code>.source([{ src: "/path/to/video.webm", type: "video/webm", ...more attributes... }, { src: "/path/to/video.mp4", type: "video/mp4", ...more attributes... }])`</code><br>
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>
</tr>
<tr>
<td><code>poster(...)</code></td>
<td>String</td>
<td>Set the poster url. This is supported for the <code>video</code> element only.</td>
</tr>
<tr>
<td><code>destroy()</code></td>
<td>&mdash;</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>&mdash;</td>
<td>Reverses the effects of the <code>destroy()</code> method, restoring the UI and listeners.</td>
</tr>
</tbody>
</table>
@ -305,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)
## 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.
## Browser support
<table width="100%" style="text-align: center;">
<table width="100%" style="text-align: center">
<thead>
<tr>
<td>Safari</td>
@ -322,19 +397,21 @@ Fullscreen in Plyr is supported for all browsers that [currently support it](htt
</thead>
<tbody>
<tr>
<td>✔&sup1;</td>
<td>✔</td>
<td>✔</td>
<td>✔</td>
<td></td>
<td>&sup1;</td>
<td>&sup2;</td>
<td>API&sup2;</td>
<td>✔&sup3;</td>
</tr>
</tbody>
</table>
&sup1; Native player used (no support for `<progress>` or `<input type="range">`)
&sup1; Mobile Safari on the iPhone forces the native player for `<video>` so no useful customisation is possible. `<audio>` elements have volume controls disabled.
&sup2; IE10 has no native fullscreen support, fallback can be used (see options)
&sup2; Native player used (no support for `<progress>` or `<input type="range">`) but the API is supported (v1.0.28+)
&sup3; IE10 has no native fullscreen support, fallback can be used (see options)
The `enabled` option can be used to disable certain User Agents. For example, if you don't want to use Plyr for smartphones, you could use:
@ -345,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.
### 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
If you find anything weird with Plyr, please let us know using the GitHub issues tracker.
## 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
- [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/)
- [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/)
- [Hacker News](https://news.ycombinator.com/item?id=9136774)
- [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)
- [The Treehouse Show #131](https://teamtreehouse.com/library/episode-131-origami-react-responsive-hero-images)
## Used by
- [Selz.com](https://selz.com)
@ -375,4 +457,4 @@ Also these links helped created Plyr:
- [Styling the `<progress>` element - hongkiat.com](http://www.hongkiat.com/blog/html5-progress-bar/)
## Copyright and License
[The MIT license](license.md).
[The MIT license](license.md).

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