Compare commits

...

9 Commits

Author SHA1 Message Date
e9cdbfb8da Safari fix (fixes #96), YouTube tweaks, docs 2015-07-25 19:51:32 +10:00
df64fdac9e Tab focus and caption position fixes (fixes #61, fixes #92) 2015-07-25 18:30:47 +10:00
4dbbbd04cc Merge pull request #99 from ChristianPV/patch-1
Update bower.json - fix sass file name
2015-07-25 10:59:56 +10:00
c9c3ee9014 Update bower.json - fix sass file name
I installed this package with bower and encountered an error while checking for existence of main bower files. I changed the filename to the correct one. Please take a look. Thanks!
2015-07-24 11:51:16 -03:00
67191c2a75 Merge branch 'master' of github.com:selz/plyr 2015-07-22 11:36:35 +10:00
8ba4522b3e Docs 2015-07-22 11:36:24 +10:00
52eaf62b58 Update readme.md 2015-07-21 12:30:41 +10:00
8d43f412ac Docs CSS 2015-07-21 10:48:31 +10:00
e9ea90f527 Update readme.md 2015-07-21 10:38:48 +10:00
19 changed files with 428 additions and 100 deletions

View File

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

View File

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

View File

@ -1,7 +1,19 @@
# Changelog # Changelog
## v1.2.3
- Fix for YouTube on iPhone or unsupported browsers (fallback to YouTube native)
- Docs tidy up
- Fullscreen for Safari fix (Fixes #96)
## v1.2.2
- Fix for :focus keyboard vs mouse (Fixes #61)
- Fix for caption positioning in full screen (Fixes #92)
## v1.2.1
- Tooltip bug fix
## v1.2.0 ## v1.2.0
- Added YouTube support. - Added YouTube support
## v1.1.13 ## v1.1.13
- Added icon prefix option for when using default controls - Added icon prefix option for when using default controls

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

2
docs/dist/docs.css vendored

File diff suppressed because one or more lines are too long

2
docs/dist/docs.js vendored

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -101,7 +101,8 @@ nav {
} }
} }
.btn-primary { .btn-primary {
background: linear-gradient(@link-color, darken(@link-color, 3%)); background-image: linear-gradient(@link-color, darken(@link-color, 3%));
background-color: @link-color;
border-color: darken(@link-color, 10%); border-color: darken(@link-color, 10%);
box-shadow: 0 1px 1px rgba(0,0,0, .15); box-shadow: 0 1px 1px rgba(0,0,0, .15);
text-shadow: 0 1px 1px rgba(0,0,0, .1); text-shadow: 0 1px 1px rgba(0,0,0, .1);

View File

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

View File

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

View File

@ -10,7 +10,7 @@ We wanted a lightweight, accessible and customisable media player that just supp
## Features ## Features
- **Accessible** - full support for captions and screen readers. - **Accessible** - full support for captions and screen readers.
- **Lightweight** - just 6.4KB minified and gzipped. - **Lightweight** - just 7.5KB minified and gzipped.
- **[Customisable](#html)** - make the player look how you want with the markup you want. - **[Customisable](#html)** - make the player look how you want with the markup you want.
- **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks. - **Semantic** - uses the *right* elements. `<input type="range">` for volume and `<progress>` for progress and well, `<button>`s for buttons. There's no `<span>` or `<a href="#">` button hacks.
- **Responsive** - as you'd expect these days. - **Responsive** - as you'd expect these days.
@ -39,7 +39,7 @@ If you have any cool ideas or features, please let me know by [creating an issue
Check `docs/index.html` and `docs/dist/docs.js` for an example setup. Check `docs/index.html` and `docs/dist/docs.js` for an example setup.
**Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.2.1/plyr.js` to `https://cdn.plyr.io/1.2.1/plyr.js` **Heads up**, the example `index.html` file needs to be served from a webserver (such as Apache, Nginx, IIS or similar) unless you change the file sources to include http or https. e.g. change `//cdn.plyr.io/1.2.3/plyr.js` to `https://cdn.plyr.io/1.2.3/plyr.js`
### Bower ### Bower
If bower is your thang, you can grab Plyr using: If bower is your thang, you can grab Plyr using:
@ -59,11 +59,11 @@ More info is on [npm](https://www.npmjs.com/package/ember-cli-plyr) and [GitHub]
If you want to use our CDN, you can use the following: If you want to use our CDN, you can use the following:
```html ```html
<link rel="stylesheet" href="https://cdn.plyr.io/1.2.1/plyr.css"> <link rel="stylesheet" href="https://cdn.plyr.io/1.2.3/plyr.css">
<script src="https://cdn.plyr.io/1.2.1/plyr.js"></script> <script src="https://cdn.plyr.io/1.2.3/plyr.js"></script>
``` ```
You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.2.1/sprite.svg`. You can also access the `sprite.svg` file at `https://cdn.plyr.io/1.2.3/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.
@ -360,6 +360,9 @@ Here's a list of the methods supported:
<strong>array</strong><br> <strong>array</strong><br>
<code>.source([{ src: "/path/to/video.webm", type: "video/webm", ...more attributes... }, { src: "/path/to/video.mp4", type: "video/mp4", ...more attributes... }])`</code><br> <code>.source([{ src: "/path/to/video.webm", type: "video/webm", ...more attributes... }, { src: "/path/to/video.mp4", type: "video/mp4", ...more attributes... }])`</code><br>
This will inject a child `source` element for every element in the array with the specified attributes. `src` is the only required attribute although adding `type` is recommended as it helps the browser decide which file to download and play. This will inject a child `source` element for every element in the array with the specified attributes. `src` is the only required attribute although adding `type` is recommended as it helps the browser decide which file to download and play.
<br><br>
<strong>YouTube</strong><br>
Currently this API method only accepts a YouTube ID when used with a YouTube player. I will add URL support soon, along with being able to swap between types (e.g. YouTube to Audio or Video and vice versa.)
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr // Plyr
// plyr.js v1.2.1 // plyr.js v1.2.3
// https://github.com/selz/plyr // https://github.com/selz/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
@ -59,7 +59,7 @@
loading: "loading", loading: "loading",
tooltip: "player-tooltip", tooltip: "player-tooltip",
hidden: "sr-only", hidden: "sr-only",
hover: "hover", hover: "player-hover",
captions: { captions: {
enabled: "captions-enabled", enabled: "captions-enabled",
active: "captions-active" active: "captions-active"
@ -529,12 +529,12 @@
}, },
browserPrefixes = "webkit moz o ms khtml".split(" "); browserPrefixes = "webkit moz o ms khtml".split(" ");
// check for native support // Check for native support
if (typeof document.cancelFullScreen != "undefined") { if (typeof document.cancelFullScreen != "undefined") {
fullscreen.supportsFullScreen = true; fullscreen.supportsFullScreen = true;
} }
else { else {
// check for fullscreen support by vendor prefix // Check for fullscreen support by vendor prefix
for (var i = 0, il = browserPrefixes.length; i < il; i++ ) { for (var i = 0, il = browserPrefixes.length; i < il; i++ ) {
fullscreen.prefix = browserPrefixes[i]; fullscreen.prefix = browserPrefixes[i];
@ -551,12 +551,6 @@
} }
} }
// Safari doesn't support the ALLOW_KEYBOARD_INPUT flag (for security) so set it to not supported
// https://bugs.webkit.org/show_bug.cgi?id=121496
if(fullscreen.prefix === "webkit" && !!navigator.userAgent.match(/Version\/[\d\.]+.*Safari/)) {
fullscreen.supportsFullScreen = false;
}
// Update methods to do something useful // Update methods to do something useful
if (fullscreen.supportsFullScreen) { if (fullscreen.supportsFullScreen) {
// Yet again Microsoft awesomeness, // Yet again Microsoft awesomeness,
@ -578,7 +572,7 @@
} }
}; };
fullscreen.requestFullScreen = function(element) { fullscreen.requestFullScreen = function(element) {
return (this.prefix === "") ? element.requestFullScreen() : element[this.prefix + (this.prefix == "ms" ? "RequestFullscreen" : "RequestFullScreen")](this.prefix === "webkit" ? element.ALLOW_KEYBOARD_INPUT : null); return (this.prefix === "") ? element.requestFullScreen() : element[this.prefix + (this.prefix == "ms" ? "RequestFullscreen" : "RequestFullScreen")]();
}; };
fullscreen.cancelFullScreen = function() { fullscreen.cancelFullScreen = function() {
return (this.prefix === "") ? document.cancelFullScreen() : document[this.prefix + (this.prefix == "ms" ? "ExitFullscreen" : "CancelFullScreen")](); return (this.prefix === "") ? document.cancelFullScreen() : document[this.prefix + (this.prefix == "ms" ? "ExitFullscreen" : "CancelFullScreen")]();
@ -852,12 +846,12 @@
// Cache the container // Cache the container
player.videoContainer = wrapper; player.videoContainer = wrapper;
} }
}
// YouTube // YouTube
if(player.type == "youtube") { if(player.type == "youtube") {
_setupYouTube(player.media.getAttribute("data-video-id")); _setupYouTube(player.media.getAttribute("data-video-id"));
} }
}
// Autoplay // Autoplay
if(player.media.getAttribute("autoplay") !== null) { if(player.media.getAttribute("autoplay") !== null) {
@ -910,7 +904,7 @@
videoId: id, videoId: id,
playerVars: { playerVars: {
autoplay: 0, autoplay: 0,
controls: 0, controls: (player.supported.full ? 0 : 1),
vq: "hd720", vq: "hd720",
rel: 0, rel: 0,
showinfo: 0, showinfo: 0,
@ -953,6 +947,7 @@
} }
}, 200); }, 200);
if(player.supported.full) {
// Only setup controls once // Only setup controls once
if(!player.container.querySelectorAll(config.selectors.controls).length) { if(!player.container.querySelectorAll(config.selectors.controls).length) {
_setupInterface(); _setupInterface();
@ -962,6 +957,7 @@
if(config.displayDuration) { if(config.displayDuration) {
_displayDuration(); _displayDuration();
} }
}
}, },
onStateChange: function(event) { onStateChange: function(event) {
// Get the instance // Get the instance
@ -1322,7 +1318,7 @@
// Show the player controls // Show the player controls
function _showControls() { function _showControls() {
// Set shown class // Set shown class
_toggleClass(player.controls, config.classes.hover, true); _toggleClass(player.container, config.classes.hover, true);
// Clear timer every movement // Clear timer every movement
window.clearTimeout(hoverTimer); window.clearTimeout(hoverTimer);
@ -1330,7 +1326,7 @@
// If the mouse is not over the controls, set a timeout to hide them // If the mouse is not over the controls, set a timeout to hide them
if(!isMouseOver) { if(!isMouseOver) {
hoverTimer = window.setTimeout(function() { hoverTimer = window.setTimeout(function() {
_toggleClass(player.controls, config.classes.hover, false); _toggleClass(player.container, config.classes.hover, false);
}, 2000); }, 2000);
} }
} }
@ -1675,6 +1671,34 @@
// IE doesn't support input event, so we fallback to change // IE doesn't support input event, so we fallback to change
var inputEvent = (player.browser.name == "IE" ? "change" : "input"); var inputEvent = (player.browser.name == "IE" ? "change" : "input");
// Detect tab focus
function checkFocus() {
var focused = document.activeElement;
if (!focused || focused == document.body) {
focused = null;
}
else if (document.querySelector){
focused = document.querySelector(":focus");
}
for (var button in player.buttons) {
var element = player.buttons[button];
_toggleClass(element, "tab-focus", (element === focused));
}
}
_on(window, "keyup", function(event) {
var code = (event.keyCode ? event.keyCode : event.which);
if(code == 9) { checkFocus(); }
});
for (var button in player.buttons) {
var element = player.buttons[button];
_on(element, "blur", function() {
_toggleClass(element, "tab-focus", false);
});
}
// Play // Play
_on(player.buttons.play, "click", function() { _on(player.buttons.play, "click", function() {
_play(); _play();
@ -1956,7 +1980,7 @@
case "youtube": case "youtube":
basic = true; basic = true;
full = !oldIE; full = (!oldIE && !iPhone);
break; break;
default: default:

View File

@ -316,6 +316,8 @@
// Tooltips // Tooltips
&-tooltip { &-tooltip {
@border-base: darken(@tooltip-bg, 8%);
visibility: hidden; visibility: hidden;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
@ -325,6 +327,7 @@
opacity: 0; opacity: 0;
background: @tooltip-bg; background: @tooltip-bg;
border: 1px solid @border-base;
border-radius: @tooltip-radius; border-radius: @tooltip-radius;
color: @tooltip-color; color: @tooltip-color;
font-size: @font-size-small; font-size: @font-size-small;
@ -335,25 +338,28 @@
transform-origin: 50% 100%; transform-origin: 50% 100%;
transition: transform .2s .1s ease, opacity .2s .1s ease; transition: transform .2s .1s ease, opacity .2s .1s ease;
// Arrow
&::after { &::after {
content: ""; content: "";
display: block;
position: absolute; position: absolute;
z-index: 1;
top: 100%;
left: 50%; left: 50%;
bottom: -@tooltip-arrow-size; display: block;
margin-left: -@tooltip-arrow-size; width: 10px;
width: 0; height: 10px;
height: 0; background: @tooltip-bg;
transition: inherit; transform: translate(-50%, -50%) rotate(45deg) translateY(2px);
border-style: solid;
border-width: @tooltip-arrow-size @tooltip-arrow-size 0 @tooltip-arrow-size; @arrow-border-color: darken(@border-base, 5%);
border-color: @controls-bg transparent transparent; border: 1px solid rgba(red(@arrow-border-color), green(@arrow-border-color), blue(@arrow-border-color), .8);
border-width: 0 1px 1px 0;
} }
} }
label:hover .player-tooltip, label:hover .player-tooltip,
input:focus + label .player-tooltip, input.tab-focus:focus + label .player-tooltip,
button:hover .player-tooltip, button:hover .player-tooltip,
button:focus .player-tooltip { button.tab-focus:focus .player-tooltip {
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
transform: translate(-50%, 0) scale(1); transform: translate(-50%, 0) scale(1);
@ -596,15 +602,6 @@
.player-video-wrapper { .player-video-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;
.player-captions {
top: auto;
bottom: 90px;
@media (min-width: @bp-control-split) {
bottom: 60px;
}
}
} }
.player-controls { .player-controls {
position: absolute; position: absolute;
@ -614,13 +611,29 @@
} }
// Hide controls when playing in full screen // Hide controls when playing in full screen
&.fullscreen-hide-controls.playing .player-controls { &.fullscreen-hide-controls.playing {
.player-controls {
transform: translateY(100%) translateY(@control-spacing / 2); transform: translateY(100%) translateY(@control-spacing / 2);
transition: transform .3s .2s ease; transition: transform .3s .2s ease;
}
&.hover { &.player-hover .player-controls {
transform: translateY(0); transform: translateY(0);
} }
.player-captions {
bottom: (@control-spacing / 2);
transition: bottom .3s .2s ease;
}
}
// Captions
.player-captions,
&.fullscreen-hide-controls.playing.player-hover .player-captions {
top: auto;
bottom: 90px;
@media (min-width: @bp-control-split) {
bottom: 60px;
}
} }
} }

View File

@ -314,6 +314,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
// Tooltips // Tooltips
&-tooltip { &-tooltip {
$border-base: darken($tooltip-bg, 8%);
visibility: hidden; visibility: hidden;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
@ -323,6 +325,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
opacity: 0; opacity: 0;
background: $tooltip-bg; background: $tooltip-bg;
border: 1px solid $border-base;
border-radius: $tooltip-radius; border-radius: $tooltip-radius;
color: $tooltip-color; color: $tooltip-color;
font-size: $font-size-small; font-size: $font-size-small;
@ -333,25 +336,28 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
transform-origin: 50% 100%; transform-origin: 50% 100%;
transition: transform .2s .1s ease, opacity .2s .1s ease; transition: transform .2s .1s ease, opacity .2s .1s ease;
// Arrow
&::after { &::after {
content: ""; content: "";
display: block;
position: absolute; position: absolute;
z-index: 1;
top: 100%;
left: 50%; left: 50%;
bottom: -$tooltip-arrow-size; display: block;
margin-left: -$tooltip-arrow-size; width: 10px;
width: 0; height: 10px;
height: 0; background: $tooltip-bg;
transition: inherit; transform: translate(-50%, -50%) rotate(45deg) translateY(2px);
border-style: solid;
border-width: $tooltip-arrow-size $tooltip-arrow-size 0 $tooltip-arrow-size; $arrow-border-color: darken($border-base, 5%);
border-color: $controls-bg transparent transparent; border: 1px solid rgba(red($arrow-border-color), green($arrow-border-color), blue($arrow-border-color), .8);
border-width: 0 1px 1px 0;
} }
} }
label:hover .player-tooltip, label:hover .player-tooltip,
input:focus + label .player-tooltip, input.tab-focus:focus + label .player-tooltip,
button:hover .player-tooltip, button:hover .player-tooltip,
button:focus .player-tooltip { button.tab-focus:focus .player-tooltip {
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
transform: translate(-50%, 0) scale(1); transform: translate(-50%, 0) scale(1);
@ -594,15 +600,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
.player-video-wrapper { .player-video-wrapper {
height: 100%; height: 100%;
width: 100%; width: 100%;
.player-captions {
top: auto;
bottom: 90px;
@media (min-width: $bp-control-split) {
bottom: 60px;
}
}
} }
.player-controls { .player-controls {
position: absolute; position: absolute;
@ -612,13 +609,29 @@ $bp-captions-large: 768px !default; // When captions jump to the larger fo
} }
// Hide controls when playing in full screen // Hide controls when playing in full screen
&.fullscreen-hide-controls.playing .player-controls { &.fullscreen-hide-controls.playing {
.player-controls {
transform: translateY(100%) translateY($control-spacing / 2); transform: translateY(100%) translateY($control-spacing / 2);
transition: transform .3s .2s ease; transition: transform .3s .2s ease;
}
&.hover { &.player-hover .player-controls {
transform: translateY(0); transform: translateY(0);
} }
.player-captions {
bottom: (@control-spacing / 2);
transition: bottom .3s .2s ease;
}
}
// Captions
.player-captions,
&.fullscreen-hide-controls.playing.player-hover .player-captions {
top: auto;
bottom: 90px;
@media (min-width: $bp-control-split) {
bottom: 60px;
}
} }
} }