aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/js/plyr.js64
-rw-r--r--src/less/plyr.less9
-rw-r--r--src/sass/plyr.scss243
-rwxr-xr-x[-rw-r--r--]src/sprite/icon-restart.svg14
4 files changed, 190 insertions, 140 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js
index fac7d555..1953f864 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -835,6 +835,44 @@
}
}
+ // Trap focus inside container
+ function _focusTrap() {
+ var tabbables = _getElements('input:not([disabled]), button:not([disabled])'),
+ first = tabbables[0],
+ last = tabbables[tabbables.length - 1];
+
+ function _checkFocus(event) {
+ // If it is TAB
+ if (event.which === 9 && plyr.isFullscreen) {
+ // Move focus to first element that can be tabbed if Shift isn't used
+ if (event.target === last && !event.shiftKey) {
+ event.preventDefault();
+ first.focus();
+ }
+ // Move focus to last element that can be tabbed if Shift is used
+ else if (event.target === first && event.shiftKey) {
+ event.preventDefault();
+ last.focus();
+ }
+ }
+ }
+
+ // Bind the handler
+ _on(plyr.container, 'keydown', _checkFocus);
+ }
+
+ // Add elements to HTML5 media (source, tracks, etc)
+ function _insertChildElements(type, attributes) {
+ if (typeof attributes === 'string') {
+ _insertElement(type, plyr.media, { src: attributes });
+ }
+ else if (attributes.constructor === Array) {
+ for (var i = attributes.length - 1; i >= 0; i--) {
+ _insertElement(type, plyr.media, attributes[i]);
+ }
+ }
+ }
+
// Insert controls
function _injectControls() {
// Make a copy of the html
@@ -1481,6 +1519,9 @@
// Toggle state
_toggleState(plyr.buttons.fullscreen, false);
+ // Setup focus trap
+ _focusTrap();
+
// Set control hide class hook
if (config.fullscreen.hideControls) {
_toggleClass(plyr.container, config.classes.fullscreen.hideControls, true);
@@ -1642,6 +1683,17 @@
// Set class hook
_toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen);
+ // Trap focus
+ if(plyr.isFullscreen) {
+ plyr.container.setAttribute('tabindex', '-1');
+ }
+ else {
+ plyr.container.removeAttribute('tabindex');
+ }
+
+ // Trap focus
+ _focusTrap(plyr.isFullscreen);
+
// Set button state
_toggleState(plyr.buttons.fullscreen, plyr.isFullscreen);
@@ -1940,18 +1992,6 @@
_updateProgress(event);
}
- // Add elements to HTML5 media (source, tracks, etc)
- function _insertChildElements(type, attributes) {
- if (typeof attributes === 'string') {
- _insertElement(type, plyr.media, { src: attributes });
- }
- else if (attributes.constructor === Array) {
- for (var i = attributes.length - 1; i >= 0; i--) {
- _insertElement(type, plyr.media, attributes[i]);
- }
- }
- }
-
// Add common function to retrieve media source
function _source(source) {
// If not null or undefined, parse it
diff --git a/src/less/plyr.less b/src/less/plyr.less
index affa7cef..891b6f9d 100644
--- a/src/less/plyr.less
+++ b/src/less/plyr.less
@@ -111,7 +111,7 @@
background: @volume-thumb-bg;
border: 0;
border-radius: 100%;
- transition: background .3s ease, transform .2s ease;
+ transition: background .3s ease;
cursor: ew-resize;
}
.volume-track() {
@@ -243,7 +243,7 @@
background: @controls-bg;
line-height: 1;
text-align: center;
- box-shadow: 0 1px 1px rgba(red(@gray-dark), green(@gray-dark), blue(@gray-dark), .2);
+ box-shadow: 0 1px 1px fade(@gray-dark, 20%);
// Layout
&--right {
@@ -283,7 +283,7 @@
}
// Hover and tab focus
- &.tab-focus,
+ &.tab-focus:focus,
&:hover {
background: @control-bg-hover;
color: @control-color-hover;
@@ -309,7 +309,6 @@
color: @control-color;
font-weight: 600;
font-size: @font-size-small;
- .font-smoothing();
}
// Media duration hidden on small screens
@@ -388,7 +387,7 @@
}
// Common range styles
- input[type='range'].tab-focus {
+ input[type='range'].tab-focus:focus {
.tab-focus();
}
diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss
index 7cefca3a..8bf481db 100644
--- a/src/sass/plyr.scss
+++ b/src/sass/plyr.scss
@@ -32,14 +32,16 @@ $control-color-hover: null !default;
// Contrast
@if lightness($controls-bg) >= 65% {
- $control-color: $gray-light;
-} @else {
- $control-color: $gray-lighter;
+ $control-color: $gray-light;
+}
+@else {
+ $control-color: $gray-lighter;
}
@if lightness($control-bg-hover) >= 65% {
- $control-color-hover: $gray;
-} @else {
- $control-color-hover: #fff;
+ $control-color-hover: $gray;
+}
+@else {
+ $control-color-hover: #fff;
}
// Tooltips
@@ -48,7 +50,7 @@ $tooltip-border-color: transparentize(@gray-dark, .1) !default;
$tooltip-border-width: 1px;
$tooltip-shadow: 0 0 5px $tooltip-border-color, 0 0 0 $tooltip-border-width $tooltip-border-color;
$tooltip-color: $control-color !default;
-$tooltip-padding: $control-spacing !default;
+$tooltip-padding: $control-spacing !default;
$tooltip-arrow-size: 6px !default;
$tooltip-radius: 3px !default;
@@ -80,77 +82,61 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
// Font smoothing
@mixin font-smoothing($mode: on)
{
- @if ($mode == 'on') {
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: antialiased;
- }
- @else if ($mode == 'off') {
- -moz-osx-font-smoothing: auto;
- -webkit-font-smoothing: subpixel-antialiased;
- }
+ @if ($mode == 'on') {
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ }
+ @else if ($mode == 'off') {
+ -moz-osx-font-smoothing: auto;
+ -webkit-font-smoothing: subpixel-antialiased;
+ }
}
// Contain floats: nicolasgallagher.com/micro-clearfix-hack/
@mixin clearfix()
{
zoom: 1;
- &:before,
+ &:before,
&:after { content: ''; display: table; }
&:after { clear: both; }
}
// Tab focus styles
-@mixin tab-focus()
-{
- outline: thin dotted #000;
- outline-offset: 0;
+@mixin tab-focus() {
+ outline: thin dotted transparentize($gray-dark, .8);
+ outline-offset: 3px;
}
// <input type="range"> styling
-@mixin volume-thumb()
-{
+@mixin volume-thumb() {
height: $volume-thumb-height;
width: $volume-thumb-width;
background: $volume-thumb-bg;
border: 0;
- border-radius: ($volume-thumb-height / 2);
+ border-radius: 100%;
transition: background .3s ease;
cursor: ew-resize;
}
-@mixin volume-track()
-{
+@mixin volume-track() {
height: $volume-track-height;
background: $volume-track-bg;
border: 0;
border-radius: ($volume-track-height / 2);
}
-@mixin seek-thumb()
-{
+@mixin seek-thumb() {
background: transparent;
border: 0;
- width: ($control-spacing * 2);
+ width: ($control-spacing * 4);
height: $control-spacing;
+ transform: translateX(-50%);
}
-@mixin seek-track()
-{
+@mixin seek-track() {
background: none;
border: 0;
}
-// Screen reader only
-// -------------------------------
-.sr-only {
- position: absolute !important;
- clip: rect(1px, 1px, 1px, 1px);
- padding: 0 !important;
- border: 0 !important;
- height: 1px !important;
- width: 1px !important;
- overflow: hidden;
-}
-
// Styles
// -------------------------------
-// Base
+// Base
.plyr {
position: relative;
max-width: 100%;
@@ -161,12 +147,28 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
&,
*,
*::after,
- *::before {
- box-sizing: border-box;
+ *::before {
+ box-sizing: border-box;
+ }
+
+ // Fix 300ms delay
+ a, button, input, label {
+ touch-action: manipulation;
+ }
+
+ // Screen reader only
+ &__sr-only {
+ position: absolute !important;
+ clip: rect(1px, 1px, 1px, 1px);
+ padding: 0 !important;
+ border: 0 !important;
+ height: 1px !important;
+ width: 1px !important;
+ overflow: hidden;
}
// For video
- &-video-wrapper {
+ &__video-wrapper {
position: relative;
}
video,
@@ -177,12 +179,12 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
}
// For embeds
- &-video-embed {
+ &__video-embed {
padding-bottom: 56.25%; /* 16:9 */
height: 0;
overflow: hidden;
background: #000;
-
+
iframe {
position: absolute;
top: 0;
@@ -201,7 +203,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
}
// Captions
- &-captions {
+ &__captions {
display: none;
position: absolute;
bottom: 0;
@@ -226,15 +228,15 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
font-size: $font-size-captions-medium;
}
}
- &.captions-active &-captions {
+ &--captions-active &__captions {
display: block;
}
- &.fullscreen-active &-captions {
+ &--fullscreen-active &__captions {
font-size: $font-size-captions-large;
}
// Playback controls
- &-controls {
+ &__controls {
@include clearfix();
@include font-smoothing();
position: relative;
@@ -242,23 +244,23 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
background: $controls-bg;
line-height: 1;
text-align: center;
- box-shadow: 0 1px 1px rgba(red($gray-dark), green($gray-dark), blue($gray-dark), .2);
+ box-shadow: 0 1px 1px transparentize($gray-dark, .2);
// Layout
- &-right {
+ &--right {
display: block;
margin: $control-spacing auto 0;
}
@media (min-width: $bp-control-split) {
- &-left {
+ &--left {
float: left;
}
- &-right {
+ &--right {
float: right;
margin-top: 0;
}
}
-
+
// Buttons
button {
display: inline-block;
@@ -272,7 +274,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
cursor: pointer;
color: $control-color;
transition: background .3s ease, color .3s ease, opacity .3s ease;
-
+
svg {
width: 18px;
height: 18px;
@@ -280,9 +282,9 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
fill: currentColor;
transition: fill .3s ease;
}
-
+
// Hover and tab focus
- &.tab-focus,
+ &.tab-focus:hover,
&:hover {
background: $control-bg-hover;
color: $control-color-hover;
@@ -292,27 +294,26 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
outline: 0;
}
}
-
+
// Hide toggle icons by default
- .icon-exit-fullscreen,
- .icon-muted,
- .icon-captions-on {
+ .icon--exit-fullscreen,
+ .icon--muted,
+ .icon--captions-on {
display: none;
}
-
+
// Time display
- .plyr-time {
+ .plyr__time {
display: inline-block;
vertical-align: middle;
margin-left: $control-spacing;
color: $control-color;
font-weight: 600;
font-size: $font-size-small;
- @include font-smoothing();
}
// Media duration hidden on small screens
- .plyr-time + .plyr-time {
+ .plyr__time + .plyr__time {
display: none;
@media (min-width: $bp-control-split) {
@@ -328,7 +329,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
}
// Tooltips
- &-tooltip {
+ &__tooltip {
position: absolute;
z-index: 2;
bottom: 100%;
@@ -367,8 +368,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
border-top: $border-arrow-size solid $tooltip-border-color;
border-left: $border-arrow-size solid transparent;
z-index: 1;
- }
- // The background triangle
+ }
+ // The background triangle
&::before {
bottom: -$tooltip-arrow-size;
border-right: $tooltip-arrow-size solid transparent;
@@ -377,15 +378,20 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
z-index: 2;
}
}
- button:hover .plyr-tooltip,
- button:focus .plyr-tooltip {
+ button:hover .plyr__tooltip,
+ button.tab-focus:focus .plyr__tooltip {
opacity: 1;
transform: translate(-50%, 0) scale(1);
}
- button:hover .plyr-tooltip {
+ button:hover .plyr__tooltip {
z-index: 3;
}
+ // Common range styles
+ input[type='range'].tab-focus:focus {
+ .tab-focus();
+ }
+
// Playback progress
// <progress> element
&-progress {
@@ -397,9 +403,9 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
height: $control-spacing;
background: $progress-bg;
- &-buffer[value],
- &-played[value],
- &-seek[type='range'] {
+ &--buffer[value],
+ &--played[value],
+ &--seek[type='range'] {
position: absolute;
left: 0;
top: 0;
@@ -414,8 +420,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
border: none;
background: transparent;
}
- &-buffer[value],
- &-played[value] {
+ &--buffer[value],
+ &--played[value] {
&::-webkit-progress-bar {
background: transparent;
}
@@ -428,18 +434,18 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
background: currentColor;
}
}
- &-played[value] {
+ &--played[value] {
z-index: 2;
color: $progress-playing-bg;
}
- &-buffer[value] {
+ &--buffer[value] {
color: $progress-buffered-bg;
}
// Seek control
// <input[type='range']> element
// Specificity is for bootstrap compatibility
- &-seek[type='range'] {
+ &--seek[type='range'] {
z-index: 4;
cursor: pointer;
outline: 0;
@@ -461,7 +467,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
-moz-appearance: none;
@include seek-thumb();
}
-
+
// Microsoft
&::-ms-track {
color: transparent;
@@ -485,47 +491,47 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
}
// Loading state
- &.loading .plyr-progress-buffer {
+ &--loading .plyr__progress--buffer {
animation: progress 1s linear infinite;
background-size: $progress-loading-size $progress-loading-size;
background-repeat: repeat-x;
background-color: $progress-buffered-bg;
background-image: linear-gradient(
- -45deg,
- $progress-loading-bg 25%,
- transparent 25%,
- transparent 50%,
- $progress-loading-bg 50%,
+ -45deg,
+ $progress-loading-bg 25%,
+ transparent 25%,
+ transparent 50%,
+ $progress-loading-bg 50%,
$progress-loading-bg 75%,
- transparent 75%,
+ transparent 75%,
transparent);
color: transparent;
}
// States
- &-controls [data-plyr='pause'],
- &.playing .plyr-controls [data-plyr='play'] {
+ &__controls [data-plyr='pause'],
+ &--playing .plyr__controls [data-plyr='play'] {
display: none;
}
- &.playing .plyr-controls [data-plyr='pause'] {
+ &--playing .plyr__controls [data-plyr='pause'] {
display: inline-block;
}
// 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;
-moz-appearance: none;
width: 100px;
margin: 0 $control-spacing 0 0;
- padding: 0;
+ padding: 0;
cursor: pointer;
background: transparent;
border: none;
-
+
// Webkit
&::-webkit-slider-runnable-track {
@include volume-track();
@@ -543,7 +549,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
&::-moz-range-thumb {
@include volume-thumb();
}
-
+
// Microsoft
&::-ms-track {
height: $volume-track-height;
@@ -578,30 +584,30 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
// Hide sound controls on iOS
// It's not supported to change volume using JavaScript:
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
- &.ios &-volume,
- &.ios [data-plyr='mute'],
- &-audio.ios &-controls-right {
+ &--is-ios &__volume,
+ &--is-ios [data-plyr='mute'],
+ &--is-ios.plyr--audio &__controls--right {
display: none;
}
// Center buttons so it looks less odd
- &-audio.ios &-controls-left {
+ &--is-ios.plyr--audio &__controls--left {
float: none;
}
// Audio specific styles
// Position the progress within the container
- &-audio .plyr-controls {
+ &--audio .plyr__controls {
padding-top: ($control-spacing * 2);
}
- &-audio .plyr-progress {
+ &--audio .plyr__progress {
bottom: auto;
top: 0;
background: $off-white;
}
// Full screen mode
- &-fullscreen,
- &.fullscreen-active {
+ &--fullscreen,
+ &--fullscreen-active {
position: fixed;
top: 0;
left: 0;
@@ -615,11 +621,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
video {
height: 100%;
}
- .plyr-video-wrapper {
+ .plyr__video-wrapper {
height: 100%;
width: 100%;
}
- .plyr-controls {
+ .plyr__controls {
position: absolute;
bottom: 0;
left: 0;
@@ -627,23 +633,24 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
}
// Hide controls when playing in full screen
- &.fullscreen-hide-controls.playing {
- .plyr-controls {
+ &--fullscreen--hide-controls&--fullscreen-active&--playing {
+ .plyr__controls {
transform: translateY(100%) translateY($control-spacing / 2);
transition: transform .3s .2s ease;
}
- &.plyr-hover .plyr-controls {
+ &.plyr--hover .plyr__controls {
transform: translateY(0);
}
- .plyr-captions {
+ .plyr__captions {
bottom: ($control-spacing / 2);
transition: bottom .3s .2s ease;
}
}
// Captions
- .plyr-captions,
- &.fullscreen-hide-controls.playing.plyr-hover .plyr-captions {
+ &--fullscreen .plyr__captions,
+ &--fullscreen-active .plyr__captions,
+ &--fullscreen--hide-controls&--fullscreen-active&--playing&--hover &__captions {
top: auto;
bottom: 90px;
@@ -654,9 +661,9 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
}
// Change icons on state change
- &.fullscreen-active .icon-exit-fullscreen,
- &.muted .plyr-controls .icon-muted,
- &.captions-active .plyr-controls .icon-captions-on {
+ &--fullscreen-active .icon--exit-fullscreen,
+ &--muted .plyr__controls .icon--muted,
+ &--captions-active .plyr__controls .icon--captions-on {
display: block;
& + svg {
@@ -669,8 +676,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger
[data-plyr='fullscreen'] {
display: none;
}
- &.captions-enabled [data-plyr='captions'],
- &.fullscreen-enabled [data-plyr='fullscreen'] {
+ &--captions-enabled [data-plyr='captions'],
+ &--fullscreen-enabled [data-plyr='fullscreen'] {
display: inline-block;
}
}
diff --git a/src/sprite/icon-restart.svg b/src/sprite/icon-restart.svg
index 1e393763..6cf89d8d 100644..100755
--- a/src/sprite/icon-restart.svg
+++ b/src/sprite/icon-restart.svg
@@ -1,5 +1,9 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <title>Restart</title>
- <path d="M17,2 C16.448,2 16,2.448 16,3 L16,7.318 L7,2 C6.448,2 6,2.448 6,3 L6,4.954 L1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L6,13.045 L6,15 C6,15.552 6.448,16 7,16 L16,10.682 L16,15 C16,15.552 16.448,16 17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L17,2 Z M6,10.722 L2,13.086 L2,4.914 L6,7.278 L6,10.722 L6,10.722 Z M8,13.086 L8,4.914 L14.915,9 L8,13.086 L8,13.086 Z" transform="translate(9.000000, 9.000000) scale(-1, 1) translate(-9.000000, -9.000000) "></path>
-</svg> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
+<path d="M7.7,1.2l0.7,6.4l2.1-2.1c1.9,1.9,1.9,5.1,0,7C9.6,13.5,8.3,14,7,14c-1.3,0-2.6-0.5-3.5-1.5
+ c-1.9-1.9-1.9-5.1,0-7c0.6-0.6,1.4-1.1,2.3-1.3L5.2,2.3C4,2.6,2.9,3.2,2,4.1c-2.7,2.7-2.7,7.1,0,9.9c1.3,1.3,3.1,2,4.9,2
+ c1.9,0,3.6-0.7,4.9-2c2.7-2.7,2.7-7.1,0-9.9l2.2-2.2L7.7,1.2z"/>
+</svg>