diff --git a/src/components/subtitlesync/subtitlesync.js b/src/components/subtitlesync/subtitlesync.js
index ba8984486b..57ae63cb8c 100644
--- a/src/components/subtitlesync/subtitlesync.js
+++ b/src/components/subtitlesync/subtitlesync.js
@@ -46,15 +46,8 @@ function init(instance) {
if (inputOffset) {
inputOffset = inputOffset[0];
inputOffset = parseFloat(inputOffset);
- inputOffset = Math.min(30, Math.max(-30, inputOffset));
- // replace current text by considered offset
- this.textContent = inputOffset + 's';
- // set new offset
- playbackManager.setSubtitleOffset(inputOffset, player);
- // synchronize with slider value
- subtitleSyncSlider.updateOffset(
- getSliderValueFromOffset(inputOffset));
+ subtitleSyncSlider.updateOffset(inputOffset);
} else {
this.textContent = (playbackManager.getPlayerSubtitleOffset(player) || 0) + 's';
}
@@ -79,23 +72,26 @@ function init(instance) {
}
};
+ function updateSubtitleOffset() {
+ const value = parseFloat(subtitleSyncSlider.value);
+ // set new offset
+ playbackManager.setSubtitleOffset(value, player);
+ // synchronize with textField value
+ subtitleSyncTextField.updateOffset(value);
+ }
+
subtitleSyncSlider.updateOffset = function (sliderValue) {
// default value is 0s = 0ms
this.value = sliderValue === undefined ? 0 : sliderValue;
+
+ updateSubtitleOffset();
};
- subtitleSyncSlider.addEventListener('change', function () {
- // set new offset
- playbackManager.setSubtitleOffset(getOffsetFromSliderValue(this.value), player);
- // synchronize with textField value
- subtitleSyncTextField.updateOffset(
- getOffsetFromSliderValue(this.value));
- });
+ subtitleSyncSlider.addEventListener('change', () => updateSubtitleOffset());
- subtitleSyncSlider.getBubbleHtml = function (value) {
- const newOffset = getOffsetFromPercentage(value);
+ subtitleSyncSlider.getBubbleHtml = function (_, value) {
return '
'
- + (newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's'
+ + (value > 0 ? '+' : '') + parseFloat(value) + 's'
+ '
';
};
@@ -107,25 +103,6 @@ function init(instance) {
instance.element = parent;
}
-function getOffsetFromPercentage(value) {
- // convert percentage to fraction
- let offset = (value - 50) / 50;
- // multiply by offset min/max range value (-x to +x) :
- offset *= 30;
- return offset.toFixed(1);
-}
-
-function getOffsetFromSliderValue(value) {
- // convert slider value to offset
- const offset = value / 10;
- return offset.toFixed(1);
-}
-
-function getSliderValueFromOffset(value) {
- const sliderValue = value * 10;
- return Math.min(300, Math.max(-300, sliderValue.toFixed(1)));
-}
-
class SubtitleSync {
constructor(currentPlayer) {
player = currentPlayer;
diff --git a/src/components/subtitlesync/subtitlesync.template.html b/src/components/subtitlesync/subtitlesync.template.html
index a055d24fcb..eb36d58260 100644
--- a/src/components/subtitlesync/subtitlesync.template.html
+++ b/src/components/subtitlesync/subtitlesync.template.html
@@ -3,7 +3,7 @@
0s
-
+
diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js
index 5e44fb03c6..cf804849d1 100644
--- a/src/elements/emby-slider/emby-slider.js
+++ b/src/elements/emby-slider/emby-slider.js
@@ -6,6 +6,7 @@ import './emby-slider.scss';
import 'webcomponents.js/webcomponents-lite';
import '../emby-input/emby-input';
import globalize from '../../scripts/globalize';
+import { decimalCount } from '../../utils/number';
const EmbySliderPrototype = Object.create(HTMLInputElement.prototype);
@@ -75,13 +76,23 @@ function mapClientToFraction(range, clientX) {
function mapFractionToValue(range, fraction) {
let value = (range.max - range.min) * fraction;
+ let decimals = null;
+
// Snap to step
if (range.step !== 'any') {
const step = normalizeSliderStep(range);
+ decimals = decimalCount(step);
value = Math.round(value / step) * step;
}
- value += parseFloat(range.min);
+ const min = parseFloat(range.min);
+
+ value += min;
+
+ if (decimals != null) {
+ decimals = Math.max(decimals, decimalCount(min));
+ value = parseFloat(value.toFixed(decimals));
+ }
return Math.min(Math.max(value, range.min), range.max);
}
@@ -135,12 +146,12 @@ function updateValues(isValueSet) {
});
}
-function updateBubble(range, value, bubble) {
+function updateBubble(range, percent, value, bubble) {
requestAnimationFrame(function () {
const bubbleTrackRect = range.sliderBubbleTrack.getBoundingClientRect();
const bubbleRect = bubble.getBoundingClientRect();
- let bubblePos = bubbleTrackRect.width * value / 100;
+ let bubblePos = bubbleTrackRect.width * percent / 100;
if (globalize.getIsElementRTL(range)) {
bubblePos = bubbleTrackRect.width - bubblePos;
}
@@ -148,18 +159,20 @@ function updateBubble(range, value, bubble) {
bubble.style.left = bubblePos + 'px';
+ let html;
+
if (range.getBubbleHtml) {
- value = range.getBubbleHtml(value);
+ html = range.getBubbleHtml(percent, value);
} else {
if (range.getBubbleText) {
- value = range.getBubbleText(value);
+ html = range.getBubbleText(percent, value);
} else {
- value = mapFractionToValue(range, value / 100).toLocaleString();
+ html = value.toLocaleString();
}
- value = '' + value + '
';
+ html = '' + html + '
';
}
- bubble.innerHTML = value;
+ bubble.innerHTML = html;
});
}
@@ -295,8 +308,8 @@ EmbySliderPrototype.attachedCallback = function () {
updateValues.call(this);
}
- const bubbleValue = mapValueToFraction(this, this.value) * 100;
- updateBubble(this, bubbleValue, sliderBubble);
+ const percent = mapValueToFraction(this, this.value) * 100;
+ updateBubble(this, percent, parseFloat(this.value), sliderBubble);
if (hasHideBubbleClass) {
sliderBubble.classList.remove('hide');
@@ -322,9 +335,11 @@ EmbySliderPrototype.attachedCallback = function () {
/* eslint-disable-next-line compat/compat */
dom.addEventListener(this, (window.PointerEvent ? 'pointermove' : 'mousemove'), function (e) {
if (!this.dragging) {
- const bubbleValue = mapClientToFraction(this, e.clientX) * 100;
+ const fraction = mapClientToFraction(this, e.clientX);
+ const percent = fraction * 100;
+ const value = mapFractionToValue(this, fraction);
- updateBubble(this, bubbleValue, sliderBubble);
+ updateBubble(this, percent, value, sliderBubble);
if (hasHideBubbleClass) {
sliderBubble.classList.remove('hide');
diff --git a/src/utils/number.ts b/src/utils/number.ts
index 16797d7d51..553280c1fe 100644
--- a/src/utils/number.ts
+++ b/src/utils/number.ts
@@ -32,3 +32,16 @@ export function toPercent(value: number | null | undefined, locale: string): str
return `${Math.round(value * 100)}%`;
}
+
+/**
+ * Gets decimal count of a Number.
+ * @param {number} value Number.
+ * @returns {number} Decimal count of a Number.
+ */
+export function decimalCount(value: number): number {
+ if (Number.isInteger(value)) return 0;
+
+ const arr = value.toString().split('.');
+
+ return arr[1].length;
+}