diff --git a/packages/live-ui/index.ts b/packages/live-ui/index.ts index b3cb722..66c236b 100644 --- a/packages/live-ui/index.ts +++ b/packages/live-ui/index.ts @@ -127,12 +127,12 @@ export default class LiveUiMiddle extends HTMLElement{ const start = document.createElement("button") start.classList.add("fp-live-start") start.textContent = player.i18n("core.watch_beginning", "Watch from beginning") - this.setAttribute("aria-label", player.i18n("core.watch_live_start", "Watch from beginning")) + start.setAttribute("aria-label", player.i18n("core.watch_live_start", "Watch from beginning")) const live = document.createElement("button") live.classList.add("fp-live-edge") live.textContent = player.i18n("core.watch_live", "Watch live") - this.setAttribute("aria-label", player.i18n("core.watch_live", "Watch live")) + live.setAttribute("aria-label", player.i18n("core.watch_live", "Watch live")) ;[start, live].forEach((button)=> { button.onclick = (e) => { diff --git a/packages/vertical-volume-bar/index.css b/packages/vertical-volume-bar/index.css index 81aab5e..7e46a37 100644 --- a/packages/vertical-volume-bar/index.css +++ b/packages/vertical-volume-bar/index.css @@ -2,18 +2,24 @@ position: relative; } -.fp-volume-control-vertical .fp-volume-vertical { +.fp-volume-control-vertical .fp-volume-wrapper { position: absolute; cursor: pointer; - opacity: 0; - padding: 0.5em; - left: -0.4em; - bottom: 1.3em; + display: flex; + visibility: hidden; + bottom: 1em; height: 10em; + left: -0.8em; + justify-content: center; + align-items: center; + flex-direction: column; + z-index: 1; } -.fp-volume-control-vertical .fp-volume-vertical:focus { - opacity: 1; +.fp-volume-control-vertical .fp-volume-vertical { + flex: 1; + margin-bottom: 1em; + padding: 0 1em; } .fp-volume-control-vertical .fp-volume-container { @@ -29,7 +35,7 @@ } .fp-volume-control-vertical .fp-dragger { - left: -0.29em; + left: -0.24em; } .fp-volume-control-vertical .fp-volume-mute-unmute { @@ -39,7 +45,3 @@ .fp-volume-control-vertical .fp-volume-mute-unmute:after { padding-bottom: 0.7em; } - -.fp-volume-control-vertical .fp-volume-mute-unmute:focus + .fp-volume-vertical { - opacity: 1; -} diff --git a/packages/vertical-volume-bar/index.ts b/packages/vertical-volume-bar/index.ts index 5c9c003..0fff23c 100644 --- a/packages/vertical-volume-bar/index.ts +++ b/packages/vertical-volume-bar/index.ts @@ -1,85 +1,95 @@ -import { install } from "../../shared/install" -import { type Player } from "@flowplayer/player" +import {install} from "../../shared/install" +import {type Player} from "@flowplayer/player" import "./index.css" import {CLICK, VOLUME_CHANGE} from "@flowplayer/player/core/events" import support from "../utils" -import { SliderStates, makeSlider } from "./slider" +import {SliderStates, makeSlider} from "./slider" export default class VerticalVolume extends HTMLElement { - constructor(player: Player) { - super() - this.classList.add("fp-volume-control-vertical") - - const volume_icon = player.createComponents(flowplayer.defaultElements.VOLUME_ICON)[0] - volume_icon.addEventListener(CLICK, _ => player.toggleMute()) - this.append(volume_icon) - - if (support().ios || support().android) return - - const volumeBar = this.createVolumeBar(player) - makeSlider(volumeBar, {onseek: this.onVolumeBarSeek.bind(this, player)}) - this.append(volumeBar) - - player.on(VOLUME_CHANGE, () => { - const muted = (player.volume == 0) || player.muted - if (muted) this.adjustVolumeSlider(player, 0, volumeBar) - - const ui_opt = player.opt("ui") - if (!this.classList.contains(SliderStates.GRABBING) && !(muted && typeof ui_opt === "number" && (4 & ui_opt) > 0)) { + constructor(player: Player) { + super() + this.classList.add("fp-volume-control-vertical") + + const volume_icon = player.createComponents(flowplayer.defaultElements.VOLUME_ICON)[0] + volume_icon.addEventListener(CLICK, _ => player.toggleMute()) + this.append(volume_icon) + + if (support().ios || support().android) return + + const volumeBar = this.createVolumeBar(player) + this.append(volumeBar) + + volume_icon.addEventListener("pointerenter", _ => volumeBar.style.visibility = "visible") + this.addEventListener("pointerleave", _ => volumeBar.style.visibility = "hidden") + this.addEventListener("focusin", ()=> volumeBar.style.visibility = "visible") + this.addEventListener("focusout", ()=> { + setTimeout(()=> { + if (document.activeElement !== volumeBar) volumeBar.style.visibility = "hidden" + }, 0) + }) + } + + createVolumeBar(player: Player) { + const volumeWrapper = document.createElement("div") + volumeWrapper.classList.add("fp-volume-wrapper") + volumeWrapper.setAttribute("tabindex", "0") + volumeWrapper.setAttribute("role", "slider") + volumeWrapper.setAttribute("aria-valuemin", "0") + volumeWrapper.setAttribute("aria-valuemax", "1") + volumeWrapper.setAttribute("aria-label", player.i18n("core.volume", "volume")) + player.on(VOLUME_CHANGE, this.onVolumeChange.bind(this, player, volumeWrapper)) + + const volumeBar = document.createElement("div") + volumeBar.setAttribute("aria-hidden", "true") + volumeBar.classList.add("fp-volume-vertical") + makeSlider(volumeBar, {onseek: this.onVolumeBarSeek.bind(this, player)}) + + const container = document.createElement("div") + container.classList.add("fp-volume-container") + + const volume = document.createElement("div") + volume.classList.add("fp-volume-progress", "fp-color", "use-drag-handle") + + const dragger = document.createElement("div") + dragger.classList.add("fp-dragger", "fp-color") + + volume.append(dragger) + volumeBar.append(container) + container.append(volume) + volumeWrapper.append(volumeBar) + + return volumeWrapper + } + + onVolumeBarSeek(player: Player, volumeBar: HTMLElement, amount: number) { + player._storage.setItem("volume", (player.volume = amount / 100).toString()) this.adjustVolumeSlider(player, player.volume, volumeBar) - } - }) - - volume_icon.addEventListener("pointerenter", _ => volumeBar.style.opacity = "1") - this.addEventListener("pointerleave", _ => volumeBar.style.opacity = "0") - } - - createVolumeBar(player: Player) { - const volumeBar = document.createElement("div") - volumeBar.classList.add("fp-volume-vertical") - volumeBar.setAttribute("tabindex", "0") - volumeBar.setAttribute("role", "slider") - volumeBar.setAttribute("aria-valuemin", "0") - volumeBar.setAttribute("aria-valuemax", "1") - volumeBar.setAttribute("aria-label", player.i18n("core.volume", "volume")) - - const container = document.createElement("div") - container.setAttribute("aria-hidden", "true") - container.classList.add("fp-volume-container") - - const volume = document.createElement("div") - volume.classList.add("fp-volume-progress", "fp-color", "use-drag-handle") - - const dragger = document.createElement("div") - dragger.classList.add("fp-dragger", "fp-color") - - - volume.append(dragger) - volumeBar.append(container) - container.append(volume) - - return volumeBar - } - - onVolumeBarSeek(player: Player, volumeBar: HTMLElement, amount: number) { - player._storage.setItem("volume", (player.volume = amount / 100).toString()) - this.adjustVolumeSlider(player, player.volume, volumeBar) - - if (amount < 0) return - player.muted = false - player._storage.removeItem("mute") - } - - adjustVolumeSlider(player: Player, amount: number, volume_bar: HTMLElement) { - volume_bar.setAttribute("aria-valuenow", amount.toString()) - volume_bar.setAttribute("aria-valuetext", Math.round(amount * 100) + "%") - const progress = this.querySelector(".fp-volume-progress") as HTMLDivElement - if(!progress) return - progress.style.height = player.muted ? "0" : Math.round(amount * 100) + "%" - } + if (amount < 0) return + player.muted = false + player._storage.removeItem("mute") + } + + adjustVolumeSlider(player: Player, amount: number, volume_bar: HTMLElement) { + volume_bar.setAttribute("aria-valuenow", amount.toString()) + volume_bar.setAttribute("aria-valuetext", Math.round(amount * 100) + "%") + + const progress = this.querySelector(".fp-volume-progress") as HTMLDivElement + if (!progress) return + progress.style.height = player.muted ? "0" : Math.round(amount * 100) + "%" + } + + onVolumeChange(player: Player, volumeBar: HTMLElement) { + const muted = player.volume == 0 || player.muted + if (muted) this.adjustVolumeSlider(player, 0, volumeBar) + + const ui_opt = player.opt("ui") + if (!this.classList.contains(SliderStates.GRABBING) && !(muted && typeof ui_opt === "number" && (4 & ui_opt) > 0)) { + this.adjustVolumeSlider(player, player.volume, volumeBar) + } + } } install("flowplayer-volume-control", "vertical-volume-bar", VerticalVolume)