UNPKG

@haxtheweb/a11y-media-player

Version:

A feature rich, highly accessible video player

1,425 lines (1,319 loc) 107 kB
/** * Copyright 2019 The Pennsylvania State University * @license Apache-2.0, see License.md for full text. */ import { LitElement, html, css } from "lit"; import { DDD } from "@haxtheweb/d-d-d/d-d-d.js"; import { FullscreenBehaviors } from "@haxtheweb/fullscreen-behaviors/fullscreen-behaviors.js"; import "@haxtheweb/anchor-behaviors/anchor-behaviors.js"; import "@haxtheweb/responsive-utility/responsive-utility.js"; import { normalizeEventPath } from "@haxtheweb/utils/utils.js"; import "@haxtheweb/absolute-position-behavior/absolute-position-behavior.js"; import "@haxtheweb/simple-tooltip/simple-tooltip.js"; import "@haxtheweb/simple-search/simple-search.js"; import "@haxtheweb/simple-range-input/simple-range-input.js"; import "@haxtheweb/simple-fields/lib/simple-fields-field.js"; import "./lib/a11y-media-play-button.js"; import "./lib/a11y-media-state-manager.js"; import "./lib/a11y-media-button.js"; import "./lib/a11y-media-transcript-cue.js"; import "./lib/a11y-media-youtube.js"; /** * `a11y-media-player` * an accessible video player * ### Styling `<a11y-media-player>` provides the following basic custom properties for styling: #### Basic Styling Custom property | Description | Default ----------------|-------------|---------- `--a11y-media-color` | default text color | `--simple-colors-default-theme-grey-11` `--a11y-media-bg-color` | default background color | `--simple-colors-default-theme-grey-2` `--a11y-media-border-color` | default border color | `--simple-colors-default-theme-grey-3` `--a11y-media-hover-color` | text color when hovering | `--simple-colors-default-theme-grey-12` `--a11y-media-hover-bg-color` | background color when hovering | `--simple-colors-default-theme-grey-2` `--a11y-media-accent-color` | accent color | `--simple-colors-default-theme-accent-9` `--a11y-media-faded-accent-color` | accent color when faded | `--simple-colors-default-theme-accent-8` `--a11y-media-disabled-color` | color for disabled items | `--simple-colors-default-theme-grey-5` `--a11y-media-transcript-color` | default text color of transcript | `--simple-colors-default-theme-grey-7` `--a11y-media-transcript-bg-color` | default background color of transcript | `--simple-colors-default-theme-grey-1` `--a11y-media-transcript-accent-color` | default accent color of transcript | `--simple-colors-default-theme-accent-8` `--a11y-media-transcript-faded-accent-color` | accent color of transcript, faded | `--simple-colors-default-theme-accent-10` `--a11y-media-transcript-cue-color` | text color of transcript cue | `--simple-colors-fixed-theme-grey-12` `--a11y-media-transcript-cue-bg-color` | background color of transcript cue | `--simple-colors-fixed-theme-grey-1` `--a11y-media-transcript-active-cue-color` | text color of active transcript cue | `--simple-colors-fixed-theme-grey-12` `--a11y-media-transcript-active-cue-bg-color` | background color of active transcript cue | `--simple-colors-fixed-theme-accent-1` `--a11y-media-transcript-focused-cue-color` | text color of focused transcript cue | `--simple-colors-fixed-theme-grey-12` `--a11y-media-transcript-focused-cue-bg-color` | background color of focused transcript cue | `--simple-colors-fixed-theme-grey-2` `--a11y-media-transcript-match-color` | text color of matched term in transcript search | `--simple-colors-fixed-theme-grey-1` `--a11y-media-transcript-match-bg-color` | background color of matched term in transcript search | `--simple-colors-fixed-theme-accent-10` `--a11y-media-transcript-match-border-color` | border color of matched term in transcript search | `--simple-colors-fixed-theme-accent-12` #### Controls Custom property | Description | Default ----------------|-------------|---------- `--a11y-media-scrollbar-width` | default width of scrollbars | `5px` `--a11y-media-controls-font-family` | font-family of controls #### Buttons Custom property | Description | Default ----------------|-------------|---------- `--a11y-media-button-color` | button text color | `--a11y-media-color` `--a11y-media-button-bg-color` | button background color | `--a11y-media-bg-color` `--a11y-media-button-hover-color` | button text color when hovering | `--a11y-media-accent-color` `--a11y-media-button-hover-bg-color` | button background color when hovering | `--a11y-media-hover-bg-color` `--a11y-media-button-disabled-color` | button text color when disabled | `--a11y-media-disabled-color` `--a11y-media-button-toggle-color` | button text color when toggled | `--a11y-media-faded-accent-color` #### Sliders Custom property | Description | Default ----------------|-------------|---------- `--simple-range-input-active-color` | slider color when active | `--a11y-media-accent-color` `--simple-range-input-secondary-color` | slider color for buffering | `--a11y-media-faded-accent-color` `--simple-range-input-pin-color` | slider pin color | `--a11y-media-bg-color` `--simple-range-input-pin-start-color` | slider pin color in start position | `--a11y-media-bg-color` `--simple-range-input-pin-end-color` | slider pin color in end position | `--a11y-media-bg-color` `--simple-range-input-knob-color` | slider knob color | `--a11y-media-accent-color` `--simple-range-input-knob-start-color` | slider knob color in start position | `--a11y-media-accent-color` `--simple-range-input-knob-end-color` | slider knob color in end position | `--a11y-media-bg-accent-color` `--simple-range-input-knob-border-color` | slider knob border color | `--a11y-media-accent-color` `--simple-range-input-knob-start-border-color` | slider knob border color in start position | `--a11y-media-bg-color` `--simple-range-input-knob-end-border-color` | slider knob border color in end position | `--a11y-media-bg-color` #### Settings Menu Custom property | Description | Default ----------------|-------------|---------- `--a11y-media-settings-menu-color` | settings menu text color | `--a11y-media-color` `--a11y-media-settings-menu-bg-color` | settings menu background color | `--a11y-media-bg-color` `--a11y-media-settings-menu-hover-color` | settings menu text color when hovering | `--a11y-media-hover-color` `--a11y-media-settings-menu-hover-bg-color` | settings menu background color when hovering | `--a11y-media-hover-bg-color` #### Link Sharing Toast Custom property | Description | Default ----------------|-------------|---------- `--simple-toast-color` | toast text color | `--a11y-media-color` `--simple-toast-background-color` | toast background color | `--a11y-media-bg-color` * * @element a11y-media-player * @extends DDD * @demo ./demo/index.html video demo * @demo ./demo/audio.html audio demo * @demo ./demo/youtube.html YouTube demo */ class A11yMediaPlayer extends FullscreenBehaviors(DDD) { //styles function static get styles() { return [ super.styles, css` :host { display: block; overflow: hidden; width: calc(100% - 2px); font-family: var(--ddd-font-navigation); --a11y-media-controls-font-family: var(--ddd-font-navigation); --a11y-media-player-height: unset; --a11y-media-color: var( --simple-colors-default-theme-grey-11, #111111 ); --a11y-media-bg-color: var( --simple-colors-default-theme-grey-2, #eeeeee ); --a11y-media-border-color: var( --simple-colors-default-theme-grey-3, #dddddd ); --a11y-media-hover-color: var( --simple-colors-default-theme-grey-12, #000000 ); --a11y-media-hover-bg-color: var( --simple-colors-default-theme-grey-2, #eeeeee ); --a11y-media-accent-color: var( --simple-colors-default-theme-accent-9, #333333 ); --a11y-media-faded-accent-color: var( --simple-colors-default-theme-accent-8, #444444 ); --a11y-media-disabled-color: var( --simple-colors-default-theme-grey-5, #bbbbbb ); border: 1px solid var( --a11y-media-border-color, var(--simple-colors-default-theme-grey-3) ); --a11y-media-settings-menu-color: var(--a11y-media-color); --a11y-media-settings-menu-bg-color: var(--a11y-media-bg-color); --a11y-media-settings-menu-hover-color: var(--a11y-media-hover-color); --a11y-media-settings-menu-hover-bg-color: var( --a11y-media-hover-bg-color ); --simple-fields-accent-color: var(--a11y-media-accent-color); --simple-fields-background-color: var(--a11y-media-bg-color); --simple-fields-color: var(--a11y-media-color); --simple-fields-border-color: var(--a11y-media-border-color); --simple-fields-border-color-light: var( --a11y-media-border-color-light, var(--a11y-media-border-color) ); --a11y-media-button-color: var(--a11y-media-color); --a11y-media-button-bg-color: var(--a11y-media-bg-color); --a11y-media-button-hover-color: var(--a11y-media-accent-color); --a11y-media-button-hover-bg-color: var(--a11y-media-hover-bg-color); --a11y-media-button-disabled-color: var(--a11y-media-disabled-color); --a11y-media-button-toggle-color: var( --a11y-media-faded-accent-color ); --simple-range-input-bg: var(--a11y-media-accent-color); --simple-range-input-color: var(--a11y-media-color); --simple-range-input-track-height: 4px; --simple-range-input-pin-height: 10px; --simple-toast-color: var(--a11y-media-color); --simple-toast-background-color: var(--a11y-media-bg-color); --a11y-media-transcript-color: var( --simple-colors-default-theme-grey-7, #666666 ); --a11y-media-transcript-bg-color: var( --simple-colors-default-theme-grey-1, #ffffff ); --a11y-media-transcript-accent-color: var( --simple-colors-default-theme-accent-8, #444444 ); --a11y-media-transcript-faded-accent-color: var( --simple-colors-default-theme-accent-10, #222222 ); --a11y-media-transcript-cue-color: var( --simple-colors-fixed-theme-grey-12, #000000 ); --a11y-media-transcript-cue-bg-color: var( --simple-colors-fixed-theme-grey-1, #ffffff ); --a11y-media-transcript-active-cue-color: var( --simple-colors-fixed-theme-grey-12, #000000 ); --a11y-media-transcript-active-cue-bg-color: var( --simple-colors-fixed-theme-accent-1, #ffffff ); --a11y-media-transcript-focused-cue-color: var( --simple-colors-fixed-theme-grey-12, #000000 ); --a11y-media-transcript-focused-cue-bg-color: var( --simple-colors-fixed-theme-grey-2, #eeeeee ); --a11y-media-transcript-match-color: var( --simple-colors-fixed-theme-grey-1, #ffffff ); --a11y-media-transcript-match-bg-color: var( --simple-colors-fixed-theme-accent-10, #222222 ); --a11y-media-transcript-match-border-color: var( --simple-colors-fixed-theme-accent-12, #000000 ); } :host([dark]) { border: 1px solid var(--simple-colors-default-theme-grey-1, #000000); } :host([dark-transcript]) { --a11y-media-transcript-bg-color: var( --simple-colors-dark-theme-grey-1, #000000 ); --a11y-media-transcript-cue-color: var( --simple-colors-dark-theme-grey-12, #ffffff ); --a11y-media-transcript-cue-bg-color: var( --simple-colors-dark-theme-grey-1, #000000 ); --a11y-media-transcript-active-cue-color: var( --simple-colors-dark-theme-accent-10, #dddddd ); --a11y-media-transcript-active-cue-bg-color: var( --simple-colors-dark-theme-grey-1, #000000 ); --a11y-media-transcript-match-color: var( --simple-colors-dark-theme-grey-1, #000000 ); --a11y-media-transcript-match-bg-color: var( --simple-colors-dark-theme-accent-10, #dddddd ); --a11y-media-transcript-match-border-color: var( --simple-colors-dark-theme-accent-12, #ffffff ); --a11y-media-transcript-focused-cue-color: var( --simple-colors-dark-theme-grey-12, #ffffff ); --a11y-media-transcript-focused-cue-bg-color: var( --simple-colors-dark-theme-grey-2, #111111 ); } :host *::-webkit-scrollbar { width: var(--a11y-media-scrollbar-width, 5px); } :host([hidden]), *[hidden] { display: none !important; } :host([height]) { height: calc(var(--a11y-media-player-height) - 2px); max-height: calc(var(--a11y-media-player-height) - 2px); overflow: unset; } :host([height]) #player-section { max-height: var(--a11y-media-player-height); } :host([height]) #player-and-controls { max-height: calc(100% - 32px - 44px); } :host([height]) #player { height: calc(100% - 32px - 44px); padding-top: unset; } :host, #player-section { color: var(--a11y-media-hover-color); background-color: var(--a11y-media-bg-color); } :host > * { transition: all 0.5s; } :host, #player-section, #player, #transcript-section, #transcript-and-controls { display: flex; flex-flow: column; align-items: stretch; align-content: stretch; } #captionlink:link { text-decoration: none; } #player-and-controls, #player, #player > *, #cc-custom, #cc-text, #slider, #controls, #player-section, #transcript-section, #transcript-and-controls { width: 100%; } #transcript-and-controls > * { width: calc(100% - 1px); } :host > *, #player-and-controls, #player, #player > *, #cc-text { flex: 1 1 auto; } #controls, #searchbar { flex: 0 0 44px; } #player-and-controls { margin: 0 auto; display: flex; } #player { height: 400px; position: relative; background-size: cover; background-position: center; } #player > * { position: absolute; top: 0; left: 0; height: 100%; } #playbutton, #slider, #controls { z-index: 2; } #html5 { min-width: 100px; display: flex; align-items: stretch; } :host([audio-only]) #playbutton { opacity: 0; } #slider { flex: 0 0 32px; height: 32px; background-color: var(--a11y-media-bg-color); --simple-range-input-pin-height: 15px; } a11y-media-youtube { opacity: 1; transition: opacity 0.5s; } a11y-media-youtube.hidden { opacity: 0; } #cc-custom:not([hidden]) { font-size: 20px; transition: font-size 0.25s; display: flex; } #cc-text { align-self: flex-end; font-family: sans-serif; color: white; margin: 4px 10px; padding: 0.15em 4px; background-color: black; background-color: rgba(0, 0, 0, 0.8); transition: all 0.5s; } #player-and-controls[audio-no-thumb] #cc-text { align-self: center; color: var(--a11y-media-color); background-color: transparent; } #controls { display: block; width: 100%; max-width: 100%; height: 44px; max-height: 44px; position: relative; color: var(--a11y-media-color); background-color: var(--a11y-media-bg-color); --primary-text-color: var(--a11y-media-settings-menu-color); } #controls-left { position: absolute; left: 0; min-width: 200px; } #controls-right { position: absolute; right: 0; top: 0; } absolute-position-behavior { background-color: var(--a11y-media-settings-menu-bg-color); color: var(--a11y-media-settings-menu-color); border: 1px solid var( --a11y-media-border-color, var(--simple-colors-default-theme-grey-3) ); max-height: 200px; overflow-y: scroll; overflow-x: hidden; } absolute-position-behavior::-webkit-scrollbar-track { background-color: var(--a11y-media-settings-menu-bg-color); } absolute-position-behavior::-webkit-scrollbar-thumb { background-color: var(--a11y-media-settings-menu-color); } absolute-position-behavior .setting { min-height: 42px; padding: 2px 10px; display: flex; justify-content: space-between; align-items: center; } absolute-position-behavior simple-field-field { margin-top: 0 !important; margin-bottom: 0 !important; background-color: var(--a11y-media-settings-menu-bg-color); color: var(--a11y-media-settings-menu-color); } .setting-text { margin-right: 1em; font-family: var(--a11y-media-controls-font-family); } .setting-control { max-width: 110px; } .setting-slider { flex: 0 0 110px; margin-left: -15px; margin-right: -15px; } #loop { flex: 0 0 40px; } #loop-label { flex: 1 1 auto; } .play-status { border: none; position: relative; font-size: 85%; font-family: var(--a11y-media-controls-font-family); } .play-status.control-bar { padding: 8px 13px 8px; } :host([hide-play-status]) .play-status { display: none; } #volume-and-mute { display: inline-block; position: relative; } #volume { position: absolute; left: 30px; top: 0px; width: 0; height: 40px; overflow: hidden; transition: width 0.5s; z-index: 3; border-radius: 4px; background-color: var(--a11y-media-bg-color); } #volume:active, #volume:focus, #volume:hover, #volume.focus, #volume-and-mute:active #volume, #volume-and-mute:focus #volume, #volume-and-mute:hover #volume { overflow: visible; width: 100px; } :host([responsive-size="xs"]) #volume:active, :host([responsive-size="xs"]) #volume:focus, :host([responsive-size="xs"]) #volume:hover, :host([responsive-size="xs"]) #volume.focus, :host([responsive-size="xs"]) #volume-and-mute:active #volume, :host([responsive-size="xs"]) #volume-and-mute:focus #volume, :host([responsive-size="xs"]) #volume-and-mute:hover #volume, :host([width]) #volume:active, :host([width]) #volume:focus, :host([width]) #volume:hover, :host([width]) #volume.focus, :host([width]) #volume-and-mute:active #volume, :host([width]) #volume-and-mute:focus #volume, :host([width]) #volume-and-mute:hover #volume { top: 0px; } #print-thumbnail { width: 100%; margin: 0; display: block; border-top: 1px solid #aaaaaa; } .media-caption:not(:empty) { padding: var(--ddd-spacing-2) var(--ddd-spacing-4); font-size: var(--ddd-font-size-xs); font-weight: bold; } .media-type { font-style: italic; } #searchbar { display: flex; align-items: stretch; justify-content: space-between; height: 44px; max-height: 44px; min-height: 44px; width: 100%; color: var(--a11y-media-color); background-color: var(--a11y-media-transcript-bg-color); --simple-fields-color: var(--a11y-media-color); --a11y-media-button-bg-color: var(--a11y-media-transcript-bg-color); --a11y-media-button-hover-bg-color: var( --a11y-media-transcript-bg-color ); --simple-search-input-background-color: var( --a11y-media-transcript-bg-color ); --simple-search-input-text-color: var(--a11y-media-color); --simple-search-input-line-color: var(--a11y-media-accent-color); --simple-search-input-placeholder-color: var(--a11y-media-color); --simple-search-button-color: var(--a11y-media-accent-color); --simple-search-button-hover-color: var( --a11y-media-faded-accent-color ); --simple-search-button-bg-color: var( --a11y-media-transcript-bg-color ); --simple-search-button-border-color: var( --a11y-media-transcript-bg-color ); --simple-search-button-hover-border-color: var( --a11y-media-transcript-bg-color ); --simple-search-button-disabled-color: var( --a11y-media-disabled-color ); --simple-search-button-disabled-bg-color: var( --a11y-media-transcript-bg-color ); --simple-search-button-disabled-border-color: var( --a11y-media-border-color ); --simple-search-padding: 0 15px; } :host([dark]) #searchbar { background-color: var(--a11y-media-bg-color); --a11y-media-button-bg-color: var(--a11y-media-bg-color); --a11y-media-button-hover-bg-color: var(--a11y-media-bg-color); --simple-search-input-background-color: var(--a11y-media-bg-color); --simple-search-button-bg-color: var(--a11y-media-bg-color); --simple-search-button-border-color: var(--a11y-media-bg-color); --simple-search-button-hover-border-color: var(--a11y-media-bg-color); --simple-search-button-disabled-bg-color: var(--a11y-media-bg-color); } #searching { flex-grow: 2; } #autoscroll { padding-right: 8px; } #scrolling, #printing { display: flex; align-items: center; } #transcript-section { padding: 0 1px 0 0; } #transcript-and-controls { flex: 1 0 194px; } #transcript { flex: 1 0 150px; max-height: var(--a11y-media-transcript-max-height, unset); overflow-y: scroll; color: var(--a11y-media-transcript-cue-color); background-color: var(--a11y-media-transcript-cue-bg-color); border-left: 1px solid var(--a11y-media-transcript-bg-color); } #transcript::-webkit-scrollbar-track { background-color: var(--a11y-media-transcript-cue-bg-color); } #transcript::-webkit-scrollbar-thumb { background-color: var(--a11y-media-transcript-cue-color); } .transcript-from-track { display: table; width: calc(100% - 30px); padding: 0 15px 15px; color: var(--a11y-media-transcript-cue-color); background-color: var(--a11y-media-transcript-cue-bg-color); font-size: var(--a11y-media-transcript-cue-font-size, 14px); line-height: var(--a11y-media-transcript-cue-line-height, 28px); } .transcript-from-track[hideTimestamps] { display: block; } .sr-only { position: absolute; left: -9999px; font-size: 0; height: 0; width: 0; overflow: hidden; } absolute-position-behavior:not(:defined), simple-tooltip:not(:defined) { display: none; } ::slotted(iframe) { display: none; } @media screen { :host([full-flex]) { flex-flow: row; padding: 0; } :host([full-flex]) #player-section { max-width: 50%; flex: 1 0 auto; } :host([full-flex]) #transcript-section { min-width: 50%; flex: 0 1 auto; } :host([full-flex]) #transcript { position: absolute; top: 44px; left: 0; right: 0; bottom: 0; overflow-y: scroll; } #transcript-and-controls { position: relative; } :host([sticky-mode]) #player-section { position: fixed; top: 5px; right: 5px; width: 200px; max-width: 200px; z-index: 999999; border: 1px solid var(--a11y-media-bg-color); box-shadow: 1px 1px 20px 1px rgba(125, 125, 125); border-radius: 3.2px; } :host([fullscreen]) #player-section { width: 100%; height: 100vh; max-width: 100vw; position: absolute; position: sticky; left: 0; top: 0; z-index: 100000; transition: all 0.5s; } :host([dark][sticky-mode]) #player-section { border: 1px solid var(--a11y-media-bg-color); } :host([sticky][sticky-corner="top-left"]) #player-section { right: unset; left: 5px; } :host( :not([no-height]):not([stacked-layout]):not( [responsive-size="xs"] ):not([responsive-size="sm"]) ) #player-and-controls.totop { position: absolute; top: 0; left: 0; width: 200px !important; z-index: 9999; } :host([sticky][sticky-corner="bottom-left"]) #player-and-controls { top: unset; right: unset; bottom: 5px; } :host([sticky][sticky-corner="bottom-right"]) #player-and-controls { top: unset; bottom: 5px; } :host([sticky-mode]) .screen-only.media-caption, :host([responsive-size="xs"]) .screen-only.media-caption { display: none; } :host([sticky-mode]) #player-and-controls[audio-no-thumb] { max-height: 0px; overflow: hidden; } :host([sticky-mode]) .hide-sticky, :host([sticky-mode]) .hide-full-xs, :host([sticky-mode]) .hide-full-sm, :host([sticky-mode]) .hide-flex, :host([width]) .hide-full-xs, :host([width]) .hide-full-sm, :host([width]) .hide-full-flex, :host([responsive-size="xs"]) .hide-full-xs, :host([responsive-size="xs"]) .hide-full-sm, :host([responsive-size="xs"]) .hide-full-flex, :host([responsive-size="sm"]) .hide-full-sm, :host([responsive-size="sm"]) .hide-full-flex, :host([flex-layout]) .hide-flex { display: none; } :host([responsive-size="xl"]) #cc-custom { font-size: 16px; } :host([responsive-size="lg"]) #cc-custom, :host([flex-layout][responsive-size="xl"]) #cc-custom { font-size: 14px; } :host([responsive-size="md"]) #cc-custom, :host([flex-layout][responsive-size="lg"]) #cc-custom { font-size: 12px; } :host([responsive-size="xs"]) #cc-custom, :host([width]) #cc-custom, :host([flex-layout][responsive-size="md"]) #cc-custom, :host([flex-layout][responsive-size="sm"]) #cc-custom { font-size: 10px; } :host([sticky-mode]) #cc-custom, :host([flex-layout][width]) #cc-custom, :host([flex-layout][responsive-size="xs"]) #cc-custom { display: none; } .media-caption { color: var(--a11y-media-caption-color, var(--a11y-media-bg-color)); background-color: var(--a11y-media-accent-color); } #audio-only { text-align: center; font-style: italic; width: 100%; line-height: 160%; } #print-thumbnail, .print-only { width: 0; display: none; } } @media print { :host, :host([dark]) { outline: 1px solid #aaaaaa; background-color: #ffffff; } .screen-only, #searchbar, #print-thumbnail:not([src]), :host(:not([thumbnail-src])) #player { display: none; } .media-caption { background-color: #cccccc; color: #000000; font-size: 120%; } #transcript { padding: 0 15px 5px; color: #000; background-color: #ffffff; border-top: 1px solid #aaa; } } `, ]; } // render function render() { return html` <div class="sr-only" ?hidden="${!this.mediaCaption}"> ${this.mediaCaption} </div> <div id="player-section"> <div id="player-and-controls" .style="${this.mediaMaxWidth}" ?audio-no-thumb="${this.audioNoThumb}" > <div id="player" .style="${this.playerStyle}"> <a11y-media-play-button id="playbutton" action="${this.__playing ? "pause" : "play"}" label="${this._getLocal( this.localization, this.__playing ? "pause" : "play", "label", )}" @button-click="${this.togglePlay}" ?audio-only="${this.audioOnly}" ?disabled="${this.audioNoThumb}" youtube-id="${this.youtubeId}" > </a11y-media-play-button> <div id="html5"> <slot></slot> </div> ${this.videoId && this.__playerReady ? html` <a11y-media-youtube id="youtube-${this.id}" class="${this.__currentTime > 0.3 || this.__seeking ? `` : `hidden`}" lang="${this.mediaLang}" preload="${this.t ? "auto" : this.preload}" .t="${this.t}" video-id="${this.videoId}" playback-rate="${this.playbackRate}" @timeupdate="${this._handleTimeUpdate}" ?hidden=${!this.isYoutube} > </a11y-media-youtube> ` : ``} ${Object.keys(this.captionCues || []).length === 0 || !this.showCustomCaptions ? html`` : html` <div id="cc-custom" aria-live="polite" class="screen-only"> <div id="cc-text"> ${!this.captionCues ? `` : Object.keys(this.captionCues).map( (key) => html`${this.captionCues[key].text ? this.captionCues[key].text : ""}`, )} </div> </div> `} </div> </div> <div id="progresslabel" class="sr-only"> ${this._getLocal(this.localization, "seekSlider", "label")} </div> <simple-range-input id="slider" class="screen-only" aria-labelledby="progresslabel" min="0" .max="${this.duration}" step="1" @value-changed="${this._handleSliderChanged}" @immediate-value-changed="${this._handleSliderDragging}" .value="${this.__currentTime}" ?disabled="${this.disableSeek}" > </simple-range-input> <div id="controls" controls="innerplayer"> <div id="controls-left"> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" icon="${this._getLocal( this.localization, this.__playing ? "pause" : "play", "icon", )}" label="${this._getLocal( this.localization, this.__playing ? "pause" : "play", "label", )}" @click="${this.togglePlay}" ></a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" class="hide-flex hide-full-xs" icon="${this._getLocal(this.localization, "rewind", "icon")}" label="${this._getLocal(this.localization, "rewind", "label")}" ?disabled="${this.disableSeek || this.currentTime <= 0}" ?hidden="${this.disableSeek}" @click="${(e) => { this.rewind(); }}" ></a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" class="hide-flex hide-full-xs" icon="${this._getLocal(this.localization, "forward", "icon")}" label="${this._getLocal(this.localization, "forward", "label")}" ?disabled="${this.disableSeek || this.currentTime >= this.duration}" ?hidden="${this.disableSeek}" @click="${(e) => { this.forward(); }}" ></a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" class="hide-flex" icon="${this._getLocal(this.localization, "restart", "icon")}" label="${this._getLocal(this.localization, "restart", "label")}" ?disabled="${this.disableSeek}" ?hidden="${this.responsiveSize === "xs" || this.responsiveSize === "sm" || this.disableSeek}" @click="${this.restart}" ></a11y-media-button> <div id="volume-and-mute" @focus="${(e) => (this.__volumeSlider = true)}" @blur="${(e) => (this.__volumeSlider = false)}" > <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" id="mute" icon="${this._getLocal( this.localization, this.muted ? "unmute" : "mute", "icon", )}" label="${this._getLocal( this.localization, this.muted ? "unmute" : "mute", "label", )}" @click="${(e) => { this.toggleMute(); }}" ></a11y-media-button> <simple-range-input id="volume" accent-color="${this.accentColor}" ?dark="${this.dark}" aria-labelledby="volume-slider-label" label="${this._getLocal(this.localization, "volume", "label")}" min="0" max="100" pin step="10" value="${this.muted ? 0 : this.volume}" @value-changed="${this._handleVolumeChanged}" ?hidden="${this.responsiveSize === "xs"}" ></simple-range-input> </div> <span aria-live="polite" class="play-status control-bar hide-full-xs" > <span id="statbar">${this.status}</span> </span> </div> <div id="controls-right"> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" icon="${this._getLocal(this.localization, "captions", "icon")}" label="${this._getLocal(this.localization, "captions", "label")}" ?disabled="${!this.hasCaptions}" ?hidden="${!this.hasCaptions}" ?toggle="${this.captionsTrackKey > -1}" @click="${(e) => this.toggleCC()}" > </a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" class="hide-full-xs" controls="transcript" icon="${this._getLocal(this.localization, "transcript", "icon")}" label="${this._getLocal( this.localization, "transcript", "label", )}" ?disabled="${!this.hasCaptions || this.learningMode}" ?hidden="${!this.hasCaptions || this.standAlone || (this.height && this.responsiveSize.indexOf("s") > -1) || this.learningMode}" ?toggle="${this.transcriptTrackKey > -1}" @click="${(e) => this.toggleTranscript()}" > </a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" class="hide-full-sm" icon="${this._getLocal(this.localization, "copyLink", "icon")}" label="${this._getLocal(this.localization, "copyLink", "label")}" ?disabled="${!this.linkable || this.learningMode}" ?hidden="${!this.linkable || this.learningMode}" @click="${this._handleCopyLink}" ></a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" icon="${this._getLocal(this.localization, "fullscreen", "icon")}" label="${this._getLocal( this.localization, "fullscreen", "label", )}" ?hidden="${this.audioNoThumb || !this.fullscreenButton}" ?toggle="${this.fullscreen}" @click="${(e) => this.toggleFullscreen()}" > </a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" id="settings-button" class="hide-sticky" controls="settings" icon="${this._getLocal(this.localization, "settings", "icon")}" label="${this._getLocal(this.localization, "settings", "label")}" @click="${(e) => this.toggleSettings()}" ></a11y-media-button> ${this.isYoutube ? html` <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" class="hide-sticky" icon="mdi-social:youtube" label="Open on YouTube" ?hidden="${this.learningMode || this.hideYoutubeLink}" @click="${this.goToYoutube}" ></a11y-media-button>` : ``} </div> <absolute-position-behavior id="settings" auto fit-to-visible-bounds for="settings-button" offset="10" position-align="end" position="top" ?hidden="${!this.__settingsOpen}" > <div class="setting" ?hidden="${!this.hasCaptions}"> <div class="setting-text"> ${this._getLocal(this.localization, "captions", "label")} </div> <simple-fields-field id="cc_tracks" class="setting-control" value="${this.captionsTrackKey}" .options="${this.captionsPicker}" ?hidden="${!this.hasCaptions}" ?disabled="${!this.hasCaptions}" @value-changed="${this.selectCaptionByKeyEvent}" type="select" > </simple-fields-field> </div> <div class="setting" ?hidden="${!this.hasCaptions || this.learningMode}" > <div class="setting-text"> ${this._getLocal(this.localization, "transcript", "label")} </div> <simple-fields-field id="transcript_tracks" class="setting-control" .value="${this.transcriptTrackKey}" .options="${this.transcriptPicker}" ?hidden="${!this.hasCaptions || this.learningMode}" ?disabled="${!this.hasCaptions || this.learningMode}" @value-changed="${this.selectTranscriptByKeyEvent}" type="select" > </simple-fields-field> </div> <div class="setting" ?hidden="${!this.hasCaptions || this.learningMode}" > <div id="print-label" class="setting-text"> ${this._getLocal(this.localization, "print", "label")} </div> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" aria-labelledby="print-label" class="setting-control" icon="${this._getLocal(this.localization, "print", "icon")}" ?disabled="${this.noPrinting || this.learningMode}" ?hidden="${this.noPrinting || this.learningMode}" @click="${this.print}" > </a11y-media-button> </div> <div class="setting" ?hidden="${!this.hasCaptions || this.learningMode}" > <div id="download-label" class="setting-text"> ${this._getLocal(this.localization, "download", "label")} </div> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" aria-labelledby="download-label" class="setting-control" icon="${this._getLocal(this.localization, "download", "icon")}" ?disabled="${this.noPrinting || this.learningMode}" ?hidden="${this.noPrinting || this.learningMode}" @click="${this.download}" > </a11y-media-button> </div> <div class="setting"> <div id="loop-label" class="setting-text"> ${this._getLocal(this.localization, "loop", "label")} </div> <simple-fields-field type="checkbox" id="loop" class="setting-control" aria-labelledby="loop-label" @value-change="${this.toggleLoop}" ?value="${this.loop}" > </simple-fields-field> </div> <div class="setting"> <div id="speed-label" class="setting-text"> ${this._getLocal(this.localization, "speed", "label")} </div> <simple-range-input id="speed" aria-labelledby="speed-label" class="setting-slider setting-control" min="0.5" max="2.5" pin step="0.25" value="${this.playbackRate}" @value-changed="${this._handleSpeedChanged}" > </simple-range-input> </div> </absolute-position-behavior> </div> <div aria-hidden="true" class="screen-only media-caption" ?hidden="${!this.mediaCaption}" > ${this.mediaCaption} </div> <div class="print-only media-caption">${this.printCaption}</div> </div> ${this.poster ? html`<img id="print-thumbnail" aria-hidden="true" .src="${this.poster}" />` : ``} <div id="transcript-section" ?hidden="${this.standAlone || !this.hasCaptions}" > <div id="transcript-and-controls" ?hidden="${this.hideTranscript}"> <div id="searchbar"> <div id="searching"> <simple-search id="simplesearch" controls="transcript" next-button-icon="${this._getLocal( this.localization, "nextResult", "icon", )}" next-button-label="${this._getLocal( this.localization, "nextResult", "label", )}" prev-button-icon="${this._getLocal( this.localization, "prevResult", "icon", )}" prev-button-label="${this._getLocal( this.localization, "prevResult", "label", )}" search-input-icon="${this._getLocal( this.localization, "search", "icon", )}" search-input-label="${this._getLocal( this.localization, "search", "label", )}" selector=".searchable" ?disabled="${this.disableSearch}" ?hidden="${this.disableSearch}" > </simple-search> </div> <div id="scrolling"> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" id="scroll" controls="transcript" icon="${this._getLocal( this.localization, "autoScroll", "icon", )}" label="${this._getLocal( this.localization, "autoScroll", "label", )}" ?toggle="${!this.disableScroll}" @click="${(e) => (this.disableScroll = !this.disableScroll)}" > </a11y-media-button> </div> <div id="printing" ?hidden="${this.disablePrintButton}" ?disabled="${this.disablePrintButton}" > <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" id="download" controls="transcript" icon="${this._getLocal(this.localization, "download", "icon")}" label="${this._getLocal( this.localization, "download", "label", )}" @click="${this.download}" > </a11y-media-button> <a11y-media-button accent-color="${this.accentColor}" ?dark="${this.dark}" id="print" controls="transcript" icon="${this._getLocal(this.localization, "print", "icon")}" label="${this._getLocal(this.localization, "print", "label")}" @click="${this.print}" > </a11y-media-button> </div> </div> <div id="transcript" aria-live="polite"> <a id="transcript-desc" class="sr-only" href="#bottom"> ${this._getLocal(this.localization, "transcript", "skip")} </a> ${this.transcriptCues.length > 0 ? html` <div class="transcript-from-track"> ${this.transcriptCues.map((cue, index) => { return html` <a11y-media-transcript-cue controls="html5" end="