diff --git a/demo/src/js/demo.js b/demo/src/js/demo.js index 1e71c0c5..b501bbb2 100644 --- a/demo/src/js/demo.js +++ b/demo/src/js/demo.js @@ -81,15 +81,15 @@ import toggleClass from './toggle-class'; points: [ { time: 10, - tip: 'first marker', + label: 'first marker', }, { time: 40, - tip: 'second marker', + label: 'second marker', }, { time: 120, - tipHTML: 'third marker', + label: 'third marker', }, ], }, diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index 6d3d7712..620c008c 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -350,6 +350,7 @@ const defaults = { hover: 'plyr--hover', tooltip: 'plyr__tooltip', cues: 'plyr__cues', + marker: 'plyr__progress__marker', hidden: 'plyr__sr-only', hideControls: 'plyr--hide-controls', isIos: 'plyr--is-ios', @@ -391,10 +392,6 @@ const defaults = { scrubbingContainer: 'plyr__preview-scrubbing', scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown', }, - markers: { - points: 'plyr__marker__points', - tip: 'plyr__marker__tip', - }, }, // Embed attributes @@ -453,7 +450,7 @@ const defaults = { album: '', artwork: [], }, - + // Markers markers: { enabled: false, diff --git a/src/js/controls.js b/src/js/controls.js index 38cd5568..008e7656 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -484,7 +484,7 @@ const controls = { menuItem.appendChild(flex); - // Replicate radio button behaviour + // Replicate radio button behavior Object.defineProperty(menuItem, 'checked', { enumerable: true, get() { @@ -698,8 +698,9 @@ const controls = { return; } + const tipElement = this.elements.display.seekTooltip; const visible = `${this.config.classNames.tooltip}--visible`; - const toggle = (show) => toggleClass(this.elements.display.seekTooltip, visible, show); + const toggle = (show) => toggleClass(tipElement, visible, show); // Hide on touch if (this.touch) { @@ -713,8 +714,8 @@ const controls = { if (is.event(event)) { percent = (100 / clientRect.width) * (event.pageX - clientRect.left); - } else if (hasClass(this.elements.display.seekTooltip, visible)) { - percent = parseFloat(this.elements.display.seekTooltip.style.left, 10); + } else if (hasClass(tipElement, visible)) { + percent = parseFloat(tipElement.style.left, 10); } else { return; } @@ -726,11 +727,21 @@ const controls = { percent = 100; } + const time = (this.duration / 100) * percent; + // Display the time a click would seek to - controls.updateTimeDisplay.call(this, this.elements.display.seekTooltip, (this.duration / 100) * percent); + tipElement.innerText = controls.formatTime(time); + + // Get marker point for time + const point = this.config.markers?.points?.find(({ time: t }) => t === Math.round(time)); + + // Append the point label to the tooltip + if (point) { + tipElement.insertAdjacentHTML('afterbegin', `${point.label}
`); + } // Set position - this.elements.display.seekTooltip.style.left = `${percent}%`; + tipElement.style.left = `${percent}%`; // Show/hide the tooltip // If the event is a moues in/out and percentage is inside bounds @@ -1761,70 +1772,81 @@ const controls = { artwork: this.config.mediaMetadata.artwork, }); } - // eslint-disable-next-line no-empty - } catch (e) {} - }, - - // Add markers + } catch (_) { + // Do nothing + } + }, + + // Add markers setMarkers() { - if (this.duration > 0 && !this.elements.markers) { - const { points } = this.config.markers; - const markersContainerFragment = document.createDocumentFragment(); - const markersPointsFragment = document.createDocumentFragment(); - const markerTipElement = createElement( + if (!this.duration || this.elements.markers) return; + + // Get valid points + const points = this.config.markers?.points?.filter(({ time }) => time > 0 && time < this.duration); + if (!points?.length) return; + + const containerFragment = document.createDocumentFragment(); + const pointsFragment = document.createDocumentFragment(); + let tipElement = null; + const tipVisible = `${this.config.classNames.tooltip}--visible`; + const toggleTip = (show) => toggleClass(tipElement, tipVisible, show); + + // Inject markers to progress container + points.forEach((point) => { + const markerElement = createElement( 'span', { - class: this.config.classNames.markers.tip, + class: this.config.classNames.marker, }, '', ); - points.forEach((point) => { - if (point < 0 || point > this.duration) { - return; - } + const left = `${(point.time / this.duration) * 100}%`; - const markerPointElement = createElement( - 'span', - { - class: this.config.classNames.markers.points, - }, - '', - ); - - const left = `${(point.time / this.duration) * 100}%`; - const tipVisible = `${this.config.classNames.markers.tip}--visible`; - const toggle = (show) => toggleClass(markerTipElement, tipVisible, show); - - markerPointElement.addEventListener('mouseenter', () => { - markerTipElement.style.left = left; - if (point.tipHTML) { - markerTipElement.innerHTML = point.tipHTML; - } else { - markerTipElement.innerText = point.tip; - } - toggle(true); - }); - markerPointElement.addEventListener('mouseleave', () => { - toggle(false); - }); - markerPointElement.addEventListener('click', () => { - this.currentTime = point.time; + if (tipElement) { + // Show on hover + markerElement.addEventListener('mouseenter', () => { + if (point.label) return; + tipElement.style.left = left; + tipElement.innerHTML = point.label; + toggleTip(true); }); - markerPointElement.style.left = left; - markersPointsFragment.appendChild(markerPointElement); + // Hide on leave + markerElement.addEventListener('mouseleave', () => { + toggleTip(false); + }); + } + + markerElement.addEventListener('click', () => { + this.currentTime = point.time; }); - markersContainerFragment.appendChild(markersPointsFragment); - markersContainerFragment.appendChild(markerTipElement); + markerElement.style.left = left; + pointsFragment.appendChild(markerElement); + }); - this.elements.markers = { - points: markersPointsFragment, - tip: markerTipElement, - }; - this.elements.progress.appendChild(markersContainerFragment); + containerFragment.appendChild(pointsFragment); + + // Inject a tooltip if needed + if (!this.config.tooltips.seek) { + tipElement = createElement( + 'span', + { + class: this.config.classNames.tooltip, + }, + '', + ); + + containerFragment.appendChild(tipElement); } + + this.elements.markers = { + points: pointsFragment, + tip: tipElement, + }; + + this.elements.progress.appendChild(containerFragment); }, }; diff --git a/src/js/plugins/preview-thumbnails.js b/src/js/plugins/preview-thumbnails.js index 80e8cd4a..efc678f7 100644 --- a/src/js/plugins/preview-thumbnails.js +++ b/src/js/plugins/preview-thumbnails.js @@ -241,6 +241,15 @@ class PreviewThumbnails { // Set time text inside image container this.elements.thumb.time.innerText = formatTime(this.seekTime); + + // Get marker point for time + const point = this.player.config.markers?.points?.find(({ time: t }) => t === Math.round(this.seekTime)); + + // Append the point label to the tooltip + if (point) { + // this.elements.thumb.time.innerText.concat('\n'); + this.elements.thumb.time.insertAdjacentHTML('afterbegin', `${point.label}
`); + } } // Download and show image @@ -326,7 +335,7 @@ class PreviewThumbnails { this.elements.thumb.time = createElement('span', {}, '00:00'); timeContainer.appendChild(this.elements.thumb.time); - this.elements.thumb.container.appendChild(timeContainer); + this.elements.thumb.imageContainer.appendChild(timeContainer); // Inject the whole thumb if (is.element(this.player.elements.progress)) { diff --git a/src/sass/components/markers.scss b/src/sass/components/markers.scss deleted file mode 100644 index 8030036c..00000000 --- a/src/sass/components/markers.scss +++ /dev/null @@ -1,57 +0,0 @@ -// -------------------------------------------------------------- -// Markers -// -------------------------------------------------------------- -.plyr__marker__points { - width: $plyr-range-track-height; - height: $plyr-range-track-height; - border-radius: $plyr-range-track-height; - background-color: #fff; - position: absolute; - top: 50%; - margin-top: calc((#{$plyr-range-track-height} / 2) * -1); - margin-left: calc((#{$plyr-range-track-height} / 2) * -1); - z-index: 3; -} - -.plyr__marker__tip { - background: $plyr-markers-background; - border-radius: $plyr-markers-radius; - bottom: 100%; - box-shadow: $plyr-markers-shadow; - color: $plyr-markers-color; - font-size: $plyr-font-size-small; - font-weight: $plyr-font-weight-regular; - left: 50%; - line-height: 1.3; - margin-bottom: calc(#{$plyr-markers-padding} * 2); - opacity: 0; - padding: $plyr-markers-padding calc(#{$plyr-markers-padding} * 1.5); - pointer-events: none; - position: absolute; - transform: translate(-50%, 10px) scale(0.8); - transform-origin: 50% 100%; - transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease; - white-space: nowrap; - z-index: 2; - - // The background triangle - &::before { - border-left: $plyr-markers-arrow-size solid transparent; - border-right: $plyr-markers-arrow-size solid transparent; - border-top: $plyr-markers-arrow-size solid $plyr-markers-background; - bottom: calc(#{$plyr-markers-arrow-size} * -1); - content: ''; - height: 0; - left: 50%; - position: absolute; - transform: translateX(-50%); - width: 0; - z-index: 2; - } -} - -.plyr__marker__tip--visible { - opacity: 1; - transform: translate(-50%, 0) scale(1); - z-index: 3; -} \ No newline at end of file diff --git a/src/sass/components/progress.scss b/src/sass/components/progress.scss index be5bc126..61bd3011 100644 --- a/src/sass/components/progress.scss +++ b/src/sass/components/progress.scss @@ -24,8 +24,10 @@ $plyr-progress-offset: $plyr-range-thumb-height; // Seek tooltip to show time .plyr__tooltip { - font-size: $plyr-font-size-time; left: 0; + max-width: 120px; + overflow-wrap: break-word; + white-space: normal; } } @@ -92,3 +94,15 @@ $plyr-progress-offset: $plyr-range-thumb-height; .plyr--audio.plyr--loading .plyr__progress__buffer { background-color: $plyr-audio-progress-buffered-background; } + +// Markers +.plyr__progress__marker { + background-color: $plyr-progress-marker-background; + border-radius: 1px; + height: $plyr-range-track-height; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + width: $plyr-progress-marker-width; + z-index: 3; +} diff --git a/src/sass/plugins/preview-thumbnails/index.scss b/src/sass/plugins/preview-thumbnails/index.scss index 7a9eb991..da9e10b1 100644 --- a/src/sass/plugins/preview-thumbnails/index.scss +++ b/src/sass/plugins/preview-thumbnails/index.scss @@ -6,12 +6,12 @@ .plyr__preview-thumb { background-color: $plyr-preview-background; - border-radius: 3px; + border-radius: $plyr-preview-radius; bottom: 100%; box-shadow: $plyr-preview-shadow; margin-bottom: calc(#{$plyr-preview-padding} * 2); opacity: 0; - padding: $plyr-preview-radius; + padding: 3px; pointer-events: none; position: absolute; transform: translate(0, 10px) scale(0.8); @@ -59,19 +59,20 @@ // Seek time text &__time-container { - bottom: $plyr-preview-time-bottom-offset; + background: $plyr-preview-time-container-background; + border-bottom-left-radius: calc(#{$plyr-preview-radius} - 1px); + border-bottom-right-radius: calc(#{$plyr-preview-radius} - 1px); + bottom: 0; left: 0; + line-height: 1.1; + padding: $plyr-preview-time-container-padding; position: absolute; right: 0; - white-space: nowrap; z-index: 3; span { - background-color: $plyr-preview-time-background; - border-radius: calc(#{$plyr-preview-radius} - 1px); color: $plyr-preview-time-color; font-size: $plyr-preview-time-font-size; - padding: $plyr-preview-time-padding; } } } diff --git a/src/sass/plugins/preview-thumbnails/settings.scss b/src/sass/plugins/preview-thumbnails/settings.scss index 155d6019..7b3c67ef 100644 --- a/src/sass/plugins/preview-thumbnails/settings.scss +++ b/src/sass/plugins/preview-thumbnails/settings.scss @@ -4,12 +4,14 @@ $plyr-preview-padding: $plyr-tooltip-padding !default; $plyr-preview-background: $plyr-tooltip-background !default; -$plyr-preview-radius: $plyr-tooltip-radius !default; +$plyr-preview-radius: 6px !default; $plyr-preview-shadow: $plyr-tooltip-shadow !default; $plyr-preview-arrow-size: $plyr-tooltip-arrow-size !default; $plyr-preview-image-background: $plyr-color-gray-200 !default; -$plyr-preview-time-font-size: $plyr-font-size-time !default; -$plyr-preview-time-padding: 3px 6px !default; -$plyr-preview-time-background: rgba(0, 0, 0, 0.55); +$plyr-preview-time-container-background: var( + --plyr-video-controls-background, + linear-gradient(rgba(#000, 0), rgba(#000, 0.75)) +) !default; +$plyr-preview-time-container-padding: 20px 6px 6px !default; $plyr-preview-time-color: #fff; -$plyr-preview-time-bottom-offset: 6px; +$plyr-preview-time-font-size: $plyr-font-size-time !default; diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss index 6299df74..39dc49d6 100644 --- a/src/sass/plyr.scss +++ b/src/sass/plyr.scss @@ -20,7 +20,6 @@ $css-vars-use-native: true; @import 'settings/progress'; @import 'settings/sliders'; @import 'settings/tooltips'; -@import 'settings/markers'; @import 'lib/animation'; @import 'lib/functions'; @import 'lib/mixins'; @@ -36,7 +35,6 @@ $css-vars-use-native: true; @import 'components/tooltips'; @import 'components/progress'; @import 'components/volume'; -@import 'components/markers'; @import 'types/audio'; @import 'types/video'; @import 'states/fullscreen'; diff --git a/src/sass/settings/markers.scss b/src/sass/settings/markers.scss deleted file mode 100644 index 4b69df96..00000000 --- a/src/sass/settings/markers.scss +++ /dev/null @@ -1,11 +0,0 @@ -// ========================================================================== -// Markers -// ========================================================================== - -$plyr-markers-background: var(--plyr-markers-background, rgba(#fff, 0.9)) !default; -$plyr-markers-color: var(--plyr-markers-color, $plyr-color-gray-700) !default; -$plyr-markers-padding: calc(#{$plyr-control-spacing} / 2); -$plyr-markers-padding: var(--plyr-markers-padding, $plyr-markers-padding) !default; -$plyr-markers-arrow-size: var(--plyr-markers-arrow-size, 4px) !default; -$plyr-markers-radius: var(--plyr-markers-radius, 3px) !default; -$plyr-markers-shadow: var(--plyr-markers-shadow, 0 1px 2px rgba(0, 0, 0, 0.15)) !default; diff --git a/src/sass/settings/progress.scss b/src/sass/settings/progress.scss index 4e5105f0..36edb613 100644 --- a/src/sass/settings/progress.scss +++ b/src/sass/settings/progress.scss @@ -6,6 +6,10 @@ $plyr-progress-loading-size: var(--plyr-progress-loading-size, 25px) !default; $plyr-progress-loading-background: var(--plyr-progress-loading-background, rgba($plyr-color-gray-900, 0.6)) !default; +// Markers +$plyr-progress-marker-background: var(--plyr-progress-marker-background, #fff) !default; +$plyr-progress-marker-width: var(--plyr-progress-marker-width, 3px) !default; + // Buffered $plyr-video-progress-buffered-background: var(--plyr-video-progress-buffered-background, rgba(#fff, 0.25)) !default; $plyr-audio-progress-buffered-background: var(