YouTube, Captions and Control improvements
- Controls improvements (Fixes #103) - YouTube bug fixes (Fixes #105) - Internationalization support (Fixes #101) - Captions legibility improvements
This commit is contained in:
145
src/js/plyr.js
145
src/js/plyr.js
@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr
|
||||
// plyr.js v1.2.6
|
||||
// plyr.js v1.3.0
|
||||
// https://github.com/selz/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
@ -83,7 +83,21 @@
|
||||
key: "plyr_volume"
|
||||
},
|
||||
controls: ["restart", "rewind", "play", "fast-forward", "current-time", "duration", "mute", "volume", "captions", "fullscreen"],
|
||||
onSetup: function() {}
|
||||
i18n: {
|
||||
restart: "Restart",
|
||||
rewind: "Rewind {seektime} secs",
|
||||
play: "Play",
|
||||
pause: "Pause",
|
||||
forward: "Forward {seektime} secs",
|
||||
played: "played",
|
||||
buffered: "buffered",
|
||||
currentTime: "Current time",
|
||||
duration: "Duration",
|
||||
volume: "Volume",
|
||||
toggleMute: "Toggle Mute",
|
||||
toggleCaptions: "Toggle Captions",
|
||||
toggleFullscreen: "Toggle Fullscreen"
|
||||
}
|
||||
};
|
||||
|
||||
// Build the default HTML
|
||||
@ -95,10 +109,10 @@
|
||||
"<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",
|
||||
"<span>0</span>% " + config.i18n.played,
|
||||
"</progress>",
|
||||
"<progress class='player-progress-buffer' max='100' value='0'>",
|
||||
"<span>0</span>% buffered",
|
||||
"<span>0</span>% " + config.i18n.buffered,
|
||||
"</progress>",
|
||||
"</div>",
|
||||
"<span class='player-controls-left'>"];
|
||||
@ -108,7 +122,7 @@
|
||||
html.push(
|
||||
"<button type='button' data-player='restart'>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-restart'></use></svg>",
|
||||
"<span class='sr-only'>Restart</span>",
|
||||
"<span class='sr-only'>" + config.i18n.restart + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
@ -118,7 +132,7 @@
|
||||
html.push(
|
||||
"<button type='button' data-player='rewind'>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-rewind'></use></svg>",
|
||||
"<span class='sr-only'>Rewind {seektime} secs</span>",
|
||||
"<span class='sr-only'>" + config.i18n.rewind + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
@ -128,11 +142,11 @@
|
||||
html.push(
|
||||
"<button type='button' data-player='play'>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-play'></use></svg>",
|
||||
"<span class='sr-only'>Play</span>",
|
||||
"<span class='sr-only'>" + config.i18n.play + "</span>",
|
||||
"</button>",
|
||||
"<button type='button' data-player='pause'>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-pause'></use></svg>",
|
||||
"<span class='sr-only'>Pause</span>",
|
||||
"<span class='sr-only'>" + config.i18n.pause + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
@ -142,7 +156,7 @@
|
||||
html.push(
|
||||
"<button type='button' data-player='fast-forward'>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-fast-forward'></use></svg>",
|
||||
"<span class='sr-only'>Forward {seektime} secs</span>",
|
||||
"<span class='sr-only'>" + config.i18n.forward + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
@ -151,7 +165,7 @@
|
||||
if(_inArray(config.controls, "current-time")) {
|
||||
html.push(
|
||||
"<span class='player-time'>",
|
||||
"<span class='sr-only'>Current time</span>",
|
||||
"<span class='sr-only'>" + config.i18n.currentTime + "</span>",
|
||||
"<span class='player-current-time'>00:00</span>",
|
||||
"</span>"
|
||||
);
|
||||
@ -161,7 +175,7 @@
|
||||
if(_inArray(config.controls, "duration")) {
|
||||
html.push(
|
||||
"<span class='player-time'>",
|
||||
"<span class='sr-only'>Duration</span>",
|
||||
"<span class='sr-only'>" + config.i18n.duration + "</span>",
|
||||
"<span class='player-duration'>00:00</span>",
|
||||
"</span>"
|
||||
);
|
||||
@ -176,19 +190,18 @@
|
||||
// Toggle mute button
|
||||
if(_inArray(config.controls, "mute")) {
|
||||
html.push(
|
||||
"<input class='inverted sr-only' id='mute{id}' type='checkbox' data-player='mute'>",
|
||||
"<label id='mute{id}' for='mute{id}'>",
|
||||
"<button type='button' data-player='mute'>",
|
||||
"<svg class='icon-muted'><use xlink:href='#" + config.iconPrefix + "-muted'></use></svg>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-volume'></use></svg>",
|
||||
"<span class='sr-only'>Toggle Mute</span>",
|
||||
"</label>"
|
||||
"<span class='sr-only'>" + config.i18n.toggleMute + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
|
||||
// Volume range control
|
||||
if(_inArray(config.controls, "volume")) {
|
||||
html.push(
|
||||
"<label for='volume{id}' class='sr-only'>Volume</label>",
|
||||
"<label for='volume{id}' class='sr-only'>" + config.i18n.volume + "</label>",
|
||||
"<input id='volume{id}' class='player-volume' type='range' min='0' max='10' value='5' data-player='volume'>"
|
||||
);
|
||||
}
|
||||
@ -196,12 +209,11 @@
|
||||
// Toggle captions button
|
||||
if(_inArray(config.controls, "captions")) {
|
||||
html.push(
|
||||
"<input class='sr-only' id='captions{id}' type='checkbox' data-player='captions'>",
|
||||
"<label for='captions{id}'>",
|
||||
"<button type='button' data-player='captions'>",
|
||||
"<svg class='icon-captions-on'><use xlink:href='#" + config.iconPrefix + "-captions-on'></use></svg>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-captions-off'></use></svg>",
|
||||
"<span class='sr-only'>Toggle Captions</span>",
|
||||
"</label>"
|
||||
"<span class='sr-only'>" + config.i18n.toggleCaptions + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
|
||||
@ -211,7 +223,7 @@
|
||||
"<button type='button' data-player='fullscreen'>",
|
||||
"<svg class='icon-exit-fullscreen'><use xlink:href='#" + config.iconPrefix + "-exit-fullscreen'></use></svg>",
|
||||
"<svg><use xlink:href='#" + config.iconPrefix + "-enter-fullscreen'></use></svg>",
|
||||
"<span class='sr-only'>Toggle Fullscreen</span>",
|
||||
"<span class='sr-only'>" + config.i18n.toggleFullscreen + "</span>",
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
@ -478,18 +490,15 @@
|
||||
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;
|
||||
|
||||
// Trigger change event
|
||||
_triggerEvent(event.target, "change");
|
||||
// Toggle aria-pressed state on a toggle button
|
||||
function _toggleState(target, state) {
|
||||
// Get state
|
||||
state = (typeof state === "boolean" ? state : !target.getAttribute("aria-pressed"));
|
||||
|
||||
// Set the attribute on target
|
||||
target.setAttribute("aria-pressed", state);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Get percentage
|
||||
@ -637,7 +646,7 @@
|
||||
player.currentCaption = player.captions[player.subcount][1];
|
||||
|
||||
// Render the caption
|
||||
player.captionsContainer.innerHTML = player.currentCaption;
|
||||
player.captionsContainer.innerHTML = player.currentCaption.trim();
|
||||
}
|
||||
else {
|
||||
// Clear the caption
|
||||
@ -656,7 +665,7 @@
|
||||
|
||||
if (config.captions.defaultActive) {
|
||||
_toggleClass(player.container, config.classes.captions.active, true);
|
||||
player.buttons.captions.checked = true;
|
||||
_toggleState(player.buttons.captions, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,15 +804,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Setup aria attributes
|
||||
function _setupAria() {
|
||||
// Setup aria attribute for play
|
||||
function _setupPlayAria() {
|
||||
// If there's no play button, bail
|
||||
if(!player.buttons.play) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the current text
|
||||
var label = player.buttons.play.innerText || "Play";
|
||||
var label = player.buttons.play.innerText || config.i18n.play;
|
||||
|
||||
// If there's a media title set, use that for the label
|
||||
if (typeof(config.title) !== "undefined" && config.title.length) {
|
||||
@ -913,10 +922,10 @@
|
||||
cc_lang_pref: "en",
|
||||
wmode: "transparent",
|
||||
modestbranding: 1,
|
||||
disablekb: 1
|
||||
disablekb: 1
|
||||
},
|
||||
events: {
|
||||
'onReady': function(event) {
|
||||
"onReady": function(event) {
|
||||
// Get the instance
|
||||
var instance = event.target;
|
||||
|
||||
@ -925,7 +934,7 @@
|
||||
player.media.pause = function() { instance.pauseVideo(); };
|
||||
player.media.stop = function() { instance.stopVideo(); };
|
||||
player.media.duration = instance.getDuration();
|
||||
player.media.paused = (instance.getPlayerState() == 2);
|
||||
player.media.paused = true;
|
||||
player.media.currentTime = instance.getCurrentTime();
|
||||
player.media.muted = instance.isMuted();
|
||||
|
||||
@ -961,7 +970,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
'onStateChange': function(event) {
|
||||
"onStateChange": function(event) {
|
||||
// Get the instance
|
||||
var instance = event.target;
|
||||
|
||||
@ -1010,10 +1019,10 @@
|
||||
function _setupCaptions() {
|
||||
if(player.type === "video") {
|
||||
// Inject the container
|
||||
player.videoContainer.insertAdjacentHTML("afterbegin", "<div class='" + config.selectors.captions.replace(".", "") + "'></div>");
|
||||
player.videoContainer.insertAdjacentHTML("afterbegin", "<div class='" + config.selectors.captions.replace(".", "") + "' aria-live='assertive'><span></span></div>");
|
||||
|
||||
// Cache selector
|
||||
player.captionsContainer = _getElement(config.selectors.captions);
|
||||
player.captionsContainer = _getElement(config.selectors.captions).querySelector("span");
|
||||
|
||||
// Determine if HTML5 textTracks is supported
|
||||
player.usingTextTracks = false;
|
||||
@ -1088,7 +1097,7 @@
|
||||
|
||||
// Display a cue, if there is one
|
||||
if (this.activeCues[0] && this.activeCues[0].hasOwnProperty("text")) {
|
||||
player.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML());
|
||||
player.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1170,6 +1179,9 @@
|
||||
_log("Fullscreen not supported and fallback disabled.");
|
||||
}
|
||||
|
||||
// Toggle state
|
||||
_toggleState(player.buttons.fullscreen, false);
|
||||
|
||||
// Set control hide class hook
|
||||
if(config.fullscreen.hideControls) {
|
||||
_toggleClass(player.container, config.classes.fullscreen.hideControls, true);
|
||||
@ -1224,7 +1236,8 @@
|
||||
// Seek to time
|
||||
// The input parameter can be an event or a number
|
||||
function _seek(input) {
|
||||
var targetTime = 0;
|
||||
var targetTime = 0,
|
||||
paused = player.media.paused;
|
||||
|
||||
// Explicit position
|
||||
if (typeof input === "number") {
|
||||
@ -1256,6 +1269,10 @@
|
||||
if(player.type == "youtube") {
|
||||
player.embed.seekTo(targetTime);
|
||||
|
||||
if(paused) {
|
||||
_pause();
|
||||
}
|
||||
|
||||
// Trigger timeupdate
|
||||
_triggerEvent(player.media, "timeupdate");
|
||||
}
|
||||
@ -1313,6 +1330,9 @@
|
||||
|
||||
// Set class hook
|
||||
_toggleClass(player.container, config.classes.fullscreen.active, player.isFullscreen);
|
||||
|
||||
// Set button state
|
||||
_toggleState(player.buttons.fullscreen, player.isFullscreen);
|
||||
|
||||
// Toggle controls visibility based on mouse movement and location
|
||||
var hoverTimer, isMouseOver = false;
|
||||
@ -1399,10 +1419,13 @@
|
||||
// Mute
|
||||
function _toggleMute(muted) {
|
||||
// If the method is called without parameter, toggle based on current value
|
||||
if(typeof muted === "undefined") {
|
||||
if(typeof muted !== "boolean") {
|
||||
muted = !player.media.muted;
|
||||
}
|
||||
|
||||
// Set button state
|
||||
_toggleState(player.buttons.mute, muted);
|
||||
|
||||
// Set mute on the player
|
||||
player.media.muted = muted;
|
||||
|
||||
@ -1435,7 +1458,7 @@
|
||||
|
||||
// Update checkbox for mute state
|
||||
if(player.supported.full && player.buttons.mute) {
|
||||
player.buttons.mute.checked = (volume === 0);
|
||||
_toggleState(player.buttons.mute, (volume === 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1447,11 +1470,14 @@
|
||||
}
|
||||
|
||||
// If the method is called without parameter, toggle based on current value
|
||||
if(typeof show === "undefined") {
|
||||
if(typeof show !== "boolean") {
|
||||
show = (player.container.className.indexOf(config.classes.captions.active) === -1);
|
||||
player.buttons.captions.checked = show;
|
||||
}
|
||||
|
||||
// Toggle state
|
||||
_toggleState(player.buttons.captions, show);
|
||||
|
||||
// Add class hook
|
||||
_toggleClass(player.container, config.classes.captions.active, show);
|
||||
}
|
||||
|
||||
@ -1731,9 +1757,7 @@
|
||||
});
|
||||
|
||||
// Mute
|
||||
_on(player.buttons.mute, "change", function() {
|
||||
_toggleMute(this.checked);
|
||||
});
|
||||
_on(player.buttons.mute, "click", _toggleMute);
|
||||
|
||||
// Fullscreen
|
||||
_on(player.buttons.fullscreen, "click", _toggleFullscreen);
|
||||
@ -1753,9 +1777,7 @@
|
||||
_on(player.media, "loadedmetadata", _displayDuration);
|
||||
|
||||
// Captions
|
||||
_on(player.buttons.captions, "change", function() {
|
||||
_toggleCaptions(this.checked);
|
||||
});
|
||||
_on(player.buttons.captions, "click", _toggleCaptions);
|
||||
|
||||
// Handle the media finishing
|
||||
_on(player.media, "ended", function() {
|
||||
@ -1780,9 +1802,6 @@
|
||||
// Loading
|
||||
_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() {
|
||||
@ -1900,7 +1919,7 @@
|
||||
}
|
||||
|
||||
// Set up aria-label for Play button with the title option
|
||||
_setupAria();
|
||||
_setupPlayAria();
|
||||
}
|
||||
|
||||
// Successful setup
|
||||
@ -2026,7 +2045,9 @@
|
||||
element.plyr = (Object.keys(instance).length ? instance : false);
|
||||
|
||||
// Callback
|
||||
config.onSetup.apply(element.plyr);
|
||||
if(typeof config.onSetup === "function") {
|
||||
config.onSetup.apply(element.plyr);
|
||||
}
|
||||
}
|
||||
|
||||
// Add to return array even if it's already setup
|
||||
@ -2036,4 +2057,4 @@
|
||||
return players;
|
||||
}
|
||||
|
||||
}(this.plyr = this.plyr || {}));
|
||||
}(this.plyr = this.plyr || {}));
|
@ -17,7 +17,11 @@
|
||||
// Font sizes
|
||||
@font-size-small: 14px;
|
||||
@font-size-base: 16px;
|
||||
@font-size-large: ceil((@font-size-base * 1.5));
|
||||
|
||||
// Captions
|
||||
@font-size-captions-base: ceil(@font-size-base * 1.25);
|
||||
@font-size-captions-medium: ceil(@font-size-base * 1.5);
|
||||
@font-size-captions-large: (@font-size-base * 2);
|
||||
|
||||
// Controls
|
||||
@control-spacing: 10px;
|
||||
@ -189,26 +193,31 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
min-height: 2.5em;
|
||||
padding: (@control-spacing * 2) (@control-spacing * 2) (@control-spacing * 3);
|
||||
color: #fff;
|
||||
font-size: @font-size-base;
|
||||
font-weight: 600;
|
||||
text-shadow:
|
||||
-1px -1px 0 @gray,
|
||||
1px -1px 0 @gray,
|
||||
-1px 1px 0 @gray,
|
||||
1px 1px 0 @gray;
|
||||
font-size: @font-size-captions-base;
|
||||
text-align: center;
|
||||
.font-smoothing();
|
||||
|
||||
span {
|
||||
border-radius: 2px;
|
||||
padding: 3px 10px;
|
||||
background: rgba(0,0,0, .9);
|
||||
}
|
||||
span:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: @bp-captions-large) {
|
||||
font-size: @font-size-large;
|
||||
font-size: @font-size-captions-medium;
|
||||
}
|
||||
}
|
||||
&.captions-active &-captions {
|
||||
display: block;
|
||||
}
|
||||
&.fullscreen-active &-captions {
|
||||
font-size: @font-size-captions-large;
|
||||
}
|
||||
|
||||
// Player controls
|
||||
&-controls {
|
||||
@ -236,17 +245,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
input + label,
|
||||
// Buttons
|
||||
button {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 0 2px;
|
||||
padding: (@control-spacing / 2) @control-spacing;
|
||||
|
||||
transition: background .3s ease, color .3s ease, opacity .3s ease;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
|
||||
color: @control-color;
|
||||
transition: background .3s ease, color .3s ease, opacity .3s ease;
|
||||
|
||||
svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@ -254,41 +266,27 @@
|
||||
fill: currentColor;
|
||||
transition: fill .3s ease;
|
||||
}
|
||||
}
|
||||
input + label,
|
||||
.inverted:checked + label {
|
||||
opacity: .5;
|
||||
}
|
||||
button,
|
||||
.inverted + label,
|
||||
input:checked + label {
|
||||
color: @control-color;
|
||||
opacity: 1;
|
||||
}
|
||||
button {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Specificity for overriding .inverted
|
||||
button:focus,
|
||||
button:hover,
|
||||
[type="checkbox"]:focus + label,
|
||||
[type="checkbox"] + label:hover {
|
||||
background: @control-bg-hover;
|
||||
color: @control-color-hover;
|
||||
opacity: 1;
|
||||
}
|
||||
button:focus,
|
||||
input:focus + label {
|
||||
outline: 0;
|
||||
// Hover and tab focus
|
||||
&.tab-focus,
|
||||
&:hover {
|
||||
background: @control-bg-hover;
|
||||
color: @control-color-hover;
|
||||
}
|
||||
// Default focus
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide toggle icons by default
|
||||
.icon-exit-fullscreen,
|
||||
.icon-muted,
|
||||
.icon-captions-on {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Player time
|
||||
.player-time {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
@ -309,7 +307,7 @@
|
||||
|
||||
// Add a slash in before
|
||||
&::before {
|
||||
content: "\2044";
|
||||
content: '\2044';
|
||||
margin-right: @control-spacing;
|
||||
}
|
||||
}
|
||||
@ -338,7 +336,7 @@
|
||||
|
||||
// Arrow
|
||||
&::after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 100%;
|
||||
@ -352,14 +350,11 @@
|
||||
border-width: 0 1px 1px 0;
|
||||
}
|
||||
}
|
||||
label:hover .player-tooltip,
|
||||
input.tab-focus:focus + label .player-tooltip,
|
||||
button:hover .player-tooltip,
|
||||
button.tab-focus:focus .player-tooltip {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, 0) scale(1);
|
||||
}
|
||||
label:hover .player-tooltip,
|
||||
button:hover .player-tooltip {
|
||||
z-index: 3;
|
||||
}
|
||||
@ -377,7 +372,7 @@
|
||||
|
||||
&-buffer[value],
|
||||
&-played[value],
|
||||
&-seek[type=range] {
|
||||
&-seek[type='range'] {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@ -417,7 +412,7 @@
|
||||
// Seek control
|
||||
// <input[type='range']> element
|
||||
// Specificity is for bootstrap compatibility
|
||||
&-seek[type=range] {
|
||||
&-seek[type='range'] {
|
||||
z-index: 4;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
@ -492,7 +487,7 @@
|
||||
// Volume control
|
||||
// <input[type='range']> element
|
||||
// Specificity is for bootstrap compatibility
|
||||
&-volume[type="range"] {
|
||||
&-volume[type='range'] {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
-webkit-appearance: none;
|
||||
@ -558,7 +553,6 @@
|
||||
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
|
||||
&.ios &-volume,
|
||||
&.ios [data-player='mute'],
|
||||
&.ios [data-player='mute'] + label,
|
||||
&-audio.ios &-controls-right {
|
||||
display: none;
|
||||
}
|
||||
@ -645,15 +639,11 @@
|
||||
|
||||
// Some options are hidden by default
|
||||
[data-player='captions'],
|
||||
[data-player='captions'] + label,
|
||||
[data-player='fullscreen'],
|
||||
[data-player='fullscreen'] + label {
|
||||
[data-player='fullscreen'] {
|
||||
display: none;
|
||||
}
|
||||
&.captions-enabled [data-player='captions'],
|
||||
&.captions-enabled [data-player='captions'] + label,
|
||||
&.fullscreen-enabled [data-player='fullscreen'],
|
||||
&.fullscreen-enabled [data-player='fullscreen'] + label {
|
||||
&.fullscreen-enabled [data-player='fullscreen'] {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
@ -17,7 +17,11 @@ $off-white: #D6DADD !default;
|
||||
// Font sizes
|
||||
$font-size-small: 14px !default;
|
||||
$font-size-base: 16px !default;
|
||||
$font-size-large: ceil(($font-size-base * 1.5)) !default;
|
||||
|
||||
// Captions
|
||||
$font-size-captions-base: ceil(@font-size-base * 1.25) !default;
|
||||
$font-size-captions-medium: ceil(@font-size-base * 1.5) !default;
|
||||
$font-size-captions-large: (@font-size-base * 2) !default;
|
||||
|
||||
// Controls
|
||||
$control-spacing: 10px !default;
|
||||
@ -89,7 +93,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
{
|
||||
zoom: 1;
|
||||
&:before,
|
||||
&:after { content: ""; display: table; }
|
||||
&:after { content: ''; display: table; }
|
||||
&:after { clear: both; }
|
||||
}
|
||||
// Tab focus styles
|
||||
@ -192,26 +196,31 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
min-height: 2.5em;
|
||||
padding: ($control-spacing * 2) ($control-spacing * 2) ($control-spacing * 3);
|
||||
color: #fff;
|
||||
font-size: $font-size-base;
|
||||
font-weight: 600;
|
||||
text-shadow:
|
||||
-1px -1px 0 $gray,
|
||||
1px -1px 0 $gray,
|
||||
-1px 1px 0 $gray,
|
||||
1px 1px 0 $gray;
|
||||
font-size: $font-size-captions-base;
|
||||
text-align: center;
|
||||
@include font-smoothing();
|
||||
|
||||
@media (min-width: $bp-captions-large) {
|
||||
font-size: $font-size-large;
|
||||
span {
|
||||
border-radius: 2px;
|
||||
padding: 3px 10px;
|
||||
background: rgba(0,0,0, .9);
|
||||
}
|
||||
span:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: @bp-captions-large) {
|
||||
font-size: $font-size-captions-medium;
|
||||
}
|
||||
}
|
||||
&.captions-active &-captions {
|
||||
display: block;
|
||||
}
|
||||
&.fullscreen-active &-captions {
|
||||
font-size: $font-size-captions-large;
|
||||
}
|
||||
|
||||
// Player controls
|
||||
&-controls {
|
||||
@ -239,17 +248,20 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
}
|
||||
}
|
||||
|
||||
input + label,
|
||||
// Buttons
|
||||
button {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 0 2px;
|
||||
padding: ($control-spacing / 2) $control-spacing;
|
||||
|
||||
transition: background .3s ease, color .3s ease, opacity .3s ease;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
|
||||
color: $control-color;
|
||||
transition: background .3s ease, color .3s ease, opacity .3s ease;
|
||||
|
||||
svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@ -257,41 +269,27 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
fill: currentColor;
|
||||
transition: fill .3s ease;
|
||||
}
|
||||
}
|
||||
input + label,
|
||||
.inverted:checked + label {
|
||||
opacity: .5;
|
||||
}
|
||||
button,
|
||||
.inverted + label,
|
||||
input:checked + label {
|
||||
color: $control-color;
|
||||
opacity: 1;
|
||||
}
|
||||
button {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
|
||||
// Hover and tab focus
|
||||
&.tab-focus,
|
||||
&:hover {
|
||||
background: $control-bg-hover;
|
||||
color: $control-color-hover;
|
||||
}
|
||||
// Default focus
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Specificity for overriding .inverted
|
||||
button:focus,
|
||||
button:hover,
|
||||
[type="checkbox"]:focus + label,
|
||||
[type="checkbox"] + label:hover {
|
||||
background: $control-bg-hover;
|
||||
color: $control-color-hover;
|
||||
opacity: 1;
|
||||
}
|
||||
button:focus,
|
||||
input:focus + label {
|
||||
outline: 0;
|
||||
}
|
||||
// Hide toggle icons by default
|
||||
.icon-exit-fullscreen,
|
||||
.icon-muted,
|
||||
.icon-captions-on {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Time display
|
||||
.player-time {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
@ -312,7 +310,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
|
||||
// Add a slash in before
|
||||
&::before {
|
||||
content: "\2044";
|
||||
content: '\2044';
|
||||
margin-right: $control-spacing;
|
||||
}
|
||||
}
|
||||
@ -339,7 +337,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
transition: transform .2s .1s ease, opacity .2s .1s ease;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
@ -353,14 +351,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
border-color: $controls-bg transparent transparent;
|
||||
}
|
||||
}
|
||||
label:hover .player-tooltip,
|
||||
input:focus + label .player-tooltip,
|
||||
button:hover .player-tooltip,
|
||||
button:focus .player-tooltip {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, 0) scale(1);
|
||||
}
|
||||
label:hover .player-tooltip,
|
||||
button:hover .player-tooltip {
|
||||
z-index: 3;
|
||||
}
|
||||
@ -378,7 +373,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
|
||||
&-buffer[value],
|
||||
&-played[value],
|
||||
&-seek[type=range] {
|
||||
&-seek[type='range'] {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@ -418,7 +413,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
// Seek control
|
||||
// <input[type='range']> element
|
||||
// Specificity is for bootstrap compatibility
|
||||
&-seek[type=range] {
|
||||
&-seek[type='range'] {
|
||||
z-index: 4;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
@ -493,7 +488,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
// Volume control
|
||||
// <input[type='range']> element
|
||||
// Specificity is for bootstrap compatibility
|
||||
&-volume[type=range] {
|
||||
&-volume[type='range'] {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
-webkit-appearance: none;
|
||||
@ -559,7 +554,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
|
||||
&.ios &-volume,
|
||||
&.ios [data-player='mute'],
|
||||
&.ios [data-player='mute'] + label,
|
||||
&-audio.ios &-controls-right {
|
||||
display: none;
|
||||
}
|
||||
@ -646,15 +640,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
|
||||
|
||||
// Some options are hidden by default
|
||||
[data-player='captions'],
|
||||
[data-player='captions'] + label,
|
||||
[data-player='fullscreen'],
|
||||
[data-player='fullscreen'] + label {
|
||||
[data-player='fullscreen'] {
|
||||
display: none;
|
||||
}
|
||||
&.captions-enabled [data-player='captions'],
|
||||
&.captions-enabled [data-player='captions'] + label,
|
||||
&.fullscreen-enabled [data-player='fullscreen'],
|
||||
&.fullscreen-enabled [data-player='fullscreen'] + label {
|
||||
&.fullscreen-enabled [data-player='fullscreen'] {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user