Compare commits

...

6 Commits

Author SHA1 Message Date
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
19 changed files with 1572 additions and 1488 deletions

View File

@ -1,5 +1,9 @@
# Changelog # Changelog
## v1.0.26
- Fixes for SASS (cheers @brunowego)
- Indentation reset to 4 spaces
## v1.0.25 ## v1.0.25
- Fixes for iOS volume controls (hidden) - Fixes for iOS volume controls (hidden)
- Classnames for left/right controls changed - Classnames for left/right controls changed

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

View File

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

View File

@ -8,10 +8,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Styles --> <!-- Styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.25/plyr.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.0.27/plyr.css">
<!-- Docs styles --> <!-- Docs styles -->
<link rel="stylesheet" href="//cdn.plyr.io/1.0.25/docs.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.0.27/docs.css">
</head> </head>
<body> <body>
<header> <header>
@ -67,13 +67,13 @@
<!-- 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.25/sprite.svg"); (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.27/sprite.svg");
</script> </script>
<!-- Plyr core script --> <!-- Plyr core script -->
<script src="//cdn.plyr.io/1.0.25/plyr.js"></script> <script src="//cdn.plyr.io/1.0.27/plyr.js"></script>
<!-- Docs script --> <!-- Docs script -->
<script src="//cdn.plyr.io/1.0.25/docs.js"></script> <script src="//cdn.plyr.io/1.0.27/docs.js"></script>
</body> </body>
</html> </html>

View File

@ -22,7 +22,8 @@ var fs = require("fs"),
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 = {
@ -223,6 +224,10 @@ gulp.task("cdn", function () {
// Upload to CDN // Upload to CDN
gulp.src(paths.upload) gulp.src(paths.upload)
.pipe(size({
showFiles: true,
gzip: true
}))
.pipe(rename(function (path) { .pipe(rename(function (path) {
path.dirname = path.dirname.replace(".", version); path.dirname = path.dirname.replace(".", version);
})) }))
@ -234,6 +239,11 @@ gulp.task("cdn", function () {
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 readme.md
gulp.src([root + "/readme.md"])
.pipe(replace(cdnpath, aws.cdn.bucket + "/" + version))
.pipe(gulp.dest(root));
// Replace versioned files in *.html // Replace versioned files in *.html
gulp.src([paths.docs.root + "*.html"]) gulp.src([paths.docs.root + "*.html"])
.pipe(replace(cdnpath, aws.cdn.bucket + "/" + version)) .pipe(replace(cdnpath, aws.cdn.bucket + "/" + version))

View File

@ -1,6 +1,6 @@
{ {
"name": "plyr", "name": "plyr",
"version": "1.0.25", "version": "1.0.27",
"description": "A simple HTML5 media player using custom controls", "description": "A simple HTML5 media player using custom controls",
"homepage": "http://plyr.io", "homepage": "http://plyr.io",
"main": "gulpfile.js", "main": "gulpfile.js",
@ -18,6 +18,7 @@
"gulp-replace": "^0.5.3", "gulp-replace": "^0.5.3",
"gulp-s3": "^0.3.0", "gulp-s3": "^0.3.0",
"gulp-sass": "^1.3.3", "gulp-sass": "^1.3.3",
"gulp-size": "^1.2.1",
"gulp-svgmin": "^1.0.0", "gulp-svgmin": "^1.0.0",
"gulp-svgstore": "^5.0.0", "gulp-svgstore": "^5.0.0",
"gulp-uglify": "~0.3.1", "gulp-uglify": "~0.3.1",

View File

@ -38,7 +38,7 @@ If you have any cool ideas or features, please let me know by [creating an issue
Check `docs/index.html` and `docs/dist/docs.js` for an example setup. Check `docs/index.html` and `docs/dist/docs.js` for an example setup.
**Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.0.25/plyr.js` to `https://cdn.plyr.io/1.0.25/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.0.27/plyr.js` to `https://cdn.plyr.io/1.0.27/plyr.js`
### Bower ### Bower
If bower is your thang, you can grab Plyr using: If bower is your thang, you can grab Plyr using:
@ -51,11 +51,11 @@ More info on setting up dependencies can be found in the [Bower Docs](http://bow
If you want to use our CDN, you can use the following. HTTPS (SSL) is supported. If you want to use our CDN, you can use the following. HTTPS (SSL) is supported.
```html ```html
<link rel="stylesheet" href="//cdn.plyr.io/1.0.25/plyr.css"> <link rel="stylesheet" href="//cdn.plyr.io/1.0.27/plyr.css">
<script src="//cdn.plyr.io/1.0.25/plyr.js"></script> <script src="//cdn.plyr.io/1.0.27/plyr.js"></script>
``` ```
You can also access the `sprite.svg` file at `//cdn.plyr.io/1.0.25/sprite.svg`. You can also access the `sprite.svg` file at `//cdn.plyr.io/1.0.27/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.

View File

@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr // Plyr
// plyr.js v1.0.25 // plyr.js v1.0.27
// https://github.com/selz/plyr // https://github.com/selz/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
@ -317,6 +317,17 @@
function _toggleHandler(element, events, callback, toggle) { function _toggleHandler(element, events, callback, toggle) {
events = events.split(" "); events = events.split(" ");
// If a nodelist is passed, call itself on each node
if(element instanceof NodeList) {
for (var x = 0; x < element.length; x++) {
if (element[x] instanceof Node) {
_toggleHandler(element[x], arguments[1], arguments[2], arguments[3]);
}
}
return;
}
// If a single node is passed, bind the event listener
for (var i = 0; i < events.length; i++) { for (var i = 0; i < events.length; i++) {
element[toggle ? "addEventListener" : "removeEventListener"](events[i], callback, false); element[toggle ? "addEventListener" : "removeEventListener"](events[i], callback, false);
} }
@ -332,6 +343,35 @@
_toggleHandler(element, events, callback, false); _toggleHandler(element, events, callback, false);
} }
// Trigger event
function _triggerEvent(element, event) {
// Create faux event
var fauxEvent = document.createEvent("MouseEvents");
// Set the event type
fauxEvent.initEvent(event, true, true);
// Dispatch the event
element.dispatchEvent(fauxEvent);
}
// Toggle checkbox
function _toggleCheckbox(event) {
// Only listen for return key
if(event.keyCode && event.keyCode != 13) {
return true;
}
// Toggle the checkbox
event.target.checked = !event.target.checked;
// Set the attribute for CSS hooks
event.target[event.target.checked ? "setAttribute" : "removeAttribute"]("checked", "");
// Trigger change event
_triggerEvent(event.target, "change");
}
// Get percentage // Get percentage
function _getPercentage(current, max) { function _getPercentage(current, max) {
if(current === 0 || max === 0 || isNaN(current) || isNaN(max)) { if(current === 0 || max === 0 || isNaN(current) || isNaN(max)) {
@ -496,7 +536,7 @@
if (config.captions.defaultActive) { if (config.captions.defaultActive) {
_toggleClass(player.container, config.classes.captions.active, true); _toggleClass(player.container, config.classes.captions.active, true);
player.buttons.captions.setAttribute("checked", "checked"); player.buttons.captions.setAttribute("checked", "");
} }
} }
@ -590,9 +630,12 @@
player.buttons.restart = _getElement(config.selectors.buttons.restart); player.buttons.restart = _getElement(config.selectors.buttons.restart);
player.buttons.rewind = _getElement(config.selectors.buttons.rewind); player.buttons.rewind = _getElement(config.selectors.buttons.rewind);
player.buttons.forward = _getElement(config.selectors.buttons.forward); player.buttons.forward = _getElement(config.selectors.buttons.forward);
player.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen);
// Inputs
player.buttons.mute = _getElement(config.selectors.buttons.mute); player.buttons.mute = _getElement(config.selectors.buttons.mute);
player.buttons.captions = _getElement(config.selectors.buttons.captions); player.buttons.captions = _getElement(config.selectors.buttons.captions);
player.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen); player.checkboxes = _getElements("[type='checkbox']");
// Progress // Progress
player.progress = {}; player.progress = {};
@ -899,7 +942,11 @@
} }
// Set the current time // Set the current time
// Try/catch incase the media isn't set and we're calling seek() from source() and IE moans
try {
player.media.currentTime = targetTime.toFixed(1); player.media.currentTime = targetTime.toFixed(1);
}
catch(e) {}
// Logging // Logging
_log("Seeking to " + player.media.currentTime + " seconds"); _log("Seeking to " + player.media.currentTime + " seconds");
@ -1225,22 +1272,6 @@
// Handle user exiting fullscreen by escaping etc // Handle user exiting fullscreen by escaping etc
_on(document, fullscreen.fullScreenEventName, _toggleFullscreen); _on(document, fullscreen.fullScreenEventName, _toggleFullscreen);
// Click video
if(player.type === "video" && config.click) {
_on(player.videoContainer, "click", function() {
if(player.media.paused) {
_play();
}
else if(player.media.ended) {
_seek();
_play();
}
else {
_pause();
}
});
}
// Time change on media // Time change on media
_on(player.media, "timeupdate seeking", _timeUpdate); _on(player.media, "timeupdate seeking", _timeUpdate);
@ -1251,15 +1282,18 @@
_on(player.buttons.seek, "change input", _seek); _on(player.buttons.seek, "change input", _seek);
// Captions // Captions
_on(player.buttons.captions, "click", function() { _on(player.buttons.captions, "change", function() {
_toggleCaptions(this.checked); _toggleCaptions(this.checked);
}); });
// Clear captions at end of video // Handle the media finishing
_on(player.media, "ended", function() { _on(player.media, "ended", function() {
// Clear
if(player.type === "video") { if(player.type === "video") {
player.captionsContainer.innerHTML = ""; player.captionsContainer.innerHTML = "";
} }
// Reset UI
_checkPlaying(); _checkPlaying();
}); });
@ -1277,6 +1311,25 @@
// Loading // Loading
_on(player.media, "waiting canplay seeked", _checkLoading); _on(player.media, "waiting canplay seeked", _checkLoading);
// Toggle checkboxes on return key (as they look like buttons)
_on(player.checkboxes, "keyup", _toggleCheckbox);
// Click video
if(player.type === "video" && config.click) {
_on(player.videoContainer, "click", function() {
if(player.media.paused) {
_play();
}
else if(player.media.ended) {
_seek();
_play();
}
else {
_pause();
}
});
}
} }
function _init() { function _init() {
@ -1324,9 +1377,14 @@
// Listeners // Listeners
_listeners(); _listeners();
// Successful setup
return true;
} }
_init(); if(!_init()) {
return {};
}
return { return {
media: player.media, media: player.media,
@ -1357,7 +1415,8 @@
} }
// Get the players // Get the players
var elements = document.querySelectorAll(config.selectors.container), players = []; var elements = document.querySelectorAll(config.selectors.container),
players = [];
// Create a player instance for each element // Create a player instance for each element
for (var i = elements.length - 1; i >= 0; i--) { for (var i = elements.length - 1; i >= 0; i--) {
@ -1373,7 +1432,11 @@
// Setup a player instance and add to the element // Setup a player instance and add to the element
if(typeof element.plyr === "undefined") { if(typeof element.plyr === "undefined") {
element.plyr = new Plyr(element); // Create new instance
var instance = new Plyr(element);
// Set plyr to false if setup failed
element.plyr = (Object.keys(instance).length ? instance : false);
} }
// Add to return array // Add to return array

View File

@ -524,13 +524,13 @@
z-index: 10000000; z-index: 10000000;
background: #000; background: #000;
video {
height: 100%;
}
.player-video-wrapper { .player-video-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;
video {
height: 100%;
}
.player-captions { .player-captions {
top: auto; top: auto;
bottom: 90px; bottom: 90px;

View File

@ -37,7 +37,7 @@ $progress-buffered-bg: $gray;
$progress-loading-size: 40px; $progress-loading-size: 40px;
$progress-loading-bg: rgba(0,0,0, .15); $progress-loading-bg: rgba(0,0,0, .15);
// Range // Volume
$volume-track-height: 6px; $volume-track-height: 6px;
$volume-track-bg: $gray; $volume-track-bg: $gray;
$volume-thumb-height: ($volume-track-height * 2); $volume-thumb-height: ($volume-track-height * 2);
@ -79,7 +79,7 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
// Animation // Animation
// --------------------------------------- // ---------------------------------------
@keyframes progress { @keyframes progress {
to { background-position: @progress-loading-size 0; } to { background-position: $progress-loading-size 0; }
} }
// <input type="range"> styling // <input type="range"> styling
@ -101,29 +101,31 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
border: 0; border: 0;
border-radius: ($volume-track-height / 2); border-radius: ($volume-track-height / 2);
} }
@mixin seek-thumb() { @mixin seek-thumb()
{
background: transparent; background: transparent;
border: 0; border: 0;
width: ($control-spacing * 2); width: ($control-spacing * 2);
height: $control-spacing; height: $control-spacing;
} }
@mixin seek-track() { @mixin seek-track()
{
background: none; background: none;
border: 0; border: 0;
} }
// Font smoothing // Font smoothing
// --------------------------------------- // ---------------------------------------
@mixin font-smoothing($mode: on) when ($mode = on) @mixin font-smoothing($mode: on)
{ {
@if $mode == 'on' {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} } @else if $mode == 'off' {
@mixin 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;
} }
}
// Styles // Styles
// ------------------------------- // -------------------------------
@ -191,7 +193,7 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
text-align: center; text-align: center;
// Layout // Layout
&-sound { &-right {
display: block; display: block;
margin: $control-spacing auto 0; margin: $control-spacing auto 0;
} }
@ -238,16 +240,19 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
background: transparent; background: transparent;
overflow: hidden; overflow: hidden;
} }
input:focus + label,
button:focus { // Specificity for overriding .inverted
@include tab-focus(); button:focus,
color: $control-color-focus;
}
button:hover, button:hover,
input + label:hover { [type="checkbox"]:focus + label,
[type="checkbox"] + label:hover {
background: $control-bg-hover; background: $control-bg-hover;
color: $control-color-hover; color: $control-color-hover;
} }
button:focus,
input:focus + label {
outline: 0;
}
.icon-exit-fullscreen, .icon-exit-fullscreen,
.icon-muted, .icon-muted,
.icon-captions-on { .icon-captions-on {
@ -330,8 +335,9 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
left: 0; left: 0;
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: $control-spacing;
margin: 0; margin: 0;
padding: 0;
vertical-align: top; vertical-align: top;
-webkit-appearance: none; -webkit-appearance: none;
@ -339,7 +345,6 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
border: none; border: none;
background: transparent; background: transparent;
} }
&-buffer[value], &-buffer[value],
&-played[value] { &-played[value] {
&::-webkit-progress-bar { &::-webkit-progress-bar {
@ -366,7 +371,7 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
// <input[type='range']> element // <input[type='range']> element
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
&-seek[type=range] { &-seek[type=range] {
z-index: 3; z-index: 4;
cursor: pointer; cursor: pointer;
outline: 0; outline: 0;
@ -441,6 +446,7 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
// <input[type='range']> element // <input[type='range']> element
// Specificity is for bootstrap compatibility // Specificity is for bootstrap compatibility
&-volume[type=range] { &-volume[type=range] {
display: inline-block;
vertical-align: middle; vertical-align: middle;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
@ -452,20 +458,20 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
// Webkit // Webkit
&::-webkit-slider-runnable-track { &::-webkit-slider-runnable-track {
@include range-track(); @include volume-track();
} }
&::-webkit-slider-thumb { &::-webkit-slider-thumb {
-webkit-appearance: none; -webkit-appearance: none;
margin-top: -(($volume-thumb-height - $volume-track-height) / 2); margin-top: -(($volume-thumb-height - $volume-track-height) / 2);
@include range-thumb(); @include volume-thumb();
} }
// Mozilla // Mozilla
&::-moz-range-track { &::-moz-range-track {
@include range-track(); @include volume-track();
} }
&::-moz-range-thumb { &::-moz-range-thumb {
@include range-thumb(); @include volume-thumb();
} }
// Microsoft // Microsoft
@ -478,10 +484,10 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
} }
&::-ms-fill-lower, &::-ms-fill-lower,
&::-ms-fill-upper { &::-ms-fill-upper {
@include range-track(); @include volume-track();
} }
&::-ms-thumb { &::-ms-thumb {
@include range-thumb(); @include volume-thumb();
} }
&:focus { &:focus {
@ -526,13 +532,13 @@ $bp-captions-large: 768px; // When captions jump to the larger font size
z-index: 10000000; z-index: 10000000;
background: #000; background: #000;
video {
height: 100%;
}
.player-video-wrapper { .player-video-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;
video {
height: 100%;
}
.player-captions { .player-captions {
top: auto; top: auto;
bottom: 90px; bottom: 90px;