unique_bubble_graph.yaml aktualisiert

This commit is contained in:
2026-06-11 10:23:11 +00:00
parent c78fa144a4
commit cd4aacf6fd

View File

@@ -1,6 +1,6 @@
unique_bubble_graph:
name: Unique Bubble Multi History Background Graph
version: 2.8.6
version: 2.8.7
creator: Torsten
supported:
- button
@@ -120,6 +120,26 @@ unique_bubble_graph:
pointer-events: none;
}
.bubble-history-point-markers {
position: absolute !important;
inset: 0 !important;
z-index: 8 !important;
display: none;
pointer-events: none;
}
.bubble-history-point-marker {
position: absolute !important;
width: 9px;
height: 9px;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow:
0 0 0 2px rgba(20, 20, 20, 0.55),
0 0 8px rgba(255, 255, 255, 0.65);
pointer-events: none;
}
.bubble-button-card-container,
.bubble-button-card,
.bubble-name-container,
@@ -175,6 +195,9 @@ unique_bubble_graph:
const extendToNow = cfg.extend_to_now !== false;
const extendThresholdMinutes = Number(cfg.extend_threshold_minutes ?? 2);
const tooltipIndicator = ["points", "line", "both", "none"].includes(cfg.tooltip_indicator)
? cfg.tooltip_indicator
: "points";
const sameScale = cfg.same_scale === true;
const numberOrNull = (value) => {
@@ -360,6 +383,7 @@ unique_bubble_graph:
let bg = host.querySelector(".bubble-history-background");
let tooltip = host.querySelector(".bubble-history-tooltip");
let marker = host.querySelector(".bubble-history-marker");
let pointLayer = host.querySelector(".bubble-history-point-markers");
let loader = host.querySelector(".bubble-history-loader");
if (!bg) {
@@ -381,6 +405,12 @@ unique_bubble_graph:
host.appendChild(marker);
}
if (!pointLayer) {
pointLayer = document.createElement("div");
pointLayer.className = "bubble-history-point-markers";
host.appendChild(pointLayer);
}
if (!loader) {
loader = document.createElement("div");
loader.className = "bubble-history-loader";
@@ -537,7 +567,10 @@ unique_bubble_graph:
host.__bubbleHistoryTooltip = tooltip;
host.__bubbleHistoryMarker = marker;
host.__bubbleHistoryPointLayer = pointLayer;
host.__bubbleHistoryTooltipTop = tooltipTop;
host.__bubbleHistoryTooltipIndicator = tooltipIndicator;
host.__bubbleHistoryPaddingY = paddingY;
if (host.__bubbleHistoryTooltipAttached) return;
@@ -551,8 +584,9 @@ unique_bubble_graph:
const tooltipElement = host.__bubbleHistoryTooltip;
const markerElement = host.__bubbleHistoryMarker;
const pointLayerElement = host.__bubbleHistoryPointLayer;
if (!tooltipElement || !markerElement) return;
if (!tooltipElement || !markerElement || !pointLayerElement) return;
const rect = host.getBoundingClientRect();
const xRatio = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));
@@ -568,11 +602,15 @@ unique_bubble_graph:
: Math.max(...usableSeries.map((series) => series.points[series.points.length - 1].t));
const targetTime = globalMinTime + xRatio * (globalMaxTime - globalMinTime);
const timeRange = globalMaxTime - globalMinTime || 1;
const indicatorMode = host.__bubbleHistoryTooltipIndicator || "points";
const rows = usableSeries.map((series) => {
const nearest = findNearestPoint(series.points, targetTime);
if (!nearest) return "";
const nearestBySeries = usableSeries.map((series) => ({
series,
nearest: findNearestPoint(series.points, targetTime)
})).filter((entry) => entry.nearest);
const rows = nearestBySeries.map(({ series, nearest }) => {
return `
<div class="bubble-history-tooltip-row">
<span class="bubble-history-tooltip-dot" style="background:${series.color};"></span>
@@ -581,31 +619,68 @@ unique_bubble_graph:
`;
}).join("");
const firstNearest = findNearestPoint(usableSeries[0].points, targetTime);
const firstNearest = nearestBySeries[0]?.nearest;
const tooltipTime = firstNearest ? firstNearest.t : targetTime;
const x = ((targetTime - globalMinTime) / (globalMaxTime - globalMinTime || 1)) * rect.width;
const x = ((targetTime - globalMinTime) / timeRange) * rect.width;
const safeX = Math.min(rect.width - 60, Math.max(60, x));
const pointMarkers = nearestBySeries.map(({ series, nearest }) => {
const minValue = Number.isFinite(series.__minValue) ? series.__minValue : 0;
const maxValue = Number.isFinite(series.__maxValue) ? series.__maxValue : 1;
const valueRange = maxValue - minValue || 1;
const pointX = ((nearest.t - globalMinTime) / timeRange) * rect.width;
const pointYView =
100 -
host.__bubbleHistoryPaddingY -
((nearest.v - minValue) / valueRange) *
(100 - host.__bubbleHistoryPaddingY * 2);
const pointY = (pointYView / 100) * rect.height;
return `
<span
class="bubble-history-point-marker"
style="left:${pointX}px;top:${pointY}px;background:${series.color};"
></span>
`;
}).join("");
tooltipElement.innerHTML = `
${rows}
<div style="opacity:0.75;margin-top:3px;">${formatTime(tooltipTime)}</div>
`;
tooltipElement.style.display = "block";
markerElement.style.display = "block";
tooltipElement.style.left = `${safeX}px`;
tooltipElement.style.top = `${host.__bubbleHistoryTooltipTop}px`;
if (indicatorMode === "line" || indicatorMode === "both") {
markerElement.style.display = "block";
markerElement.style.left = `${x}px`;
} else {
markerElement.style.display = "none";
}
if (indicatorMode === "points" || indicatorMode === "both") {
pointLayerElement.innerHTML = pointMarkers;
pointLayerElement.style.display = "block";
} else {
pointLayerElement.innerHTML = "";
pointLayerElement.style.display = "none";
}
};
host.onmouseleave = () => {
const tooltipElement = host.__bubbleHistoryTooltip;
const markerElement = host.__bubbleHistoryMarker;
const pointLayerElement = host.__bubbleHistoryPointLayer;
if (tooltipElement) tooltipElement.style.display = "none";
if (markerElement) markerElement.style.display = "none";
if (pointLayerElement) {
pointLayerElement.style.display = "none";
pointLayerElement.innerHTML = "";
}
};
};
@@ -645,25 +720,39 @@ unique_bubble_graph:
const globalMaxTime = Math.max(...usableSeries.map((series) => series.points[series.points.length - 1].t));
const sameScaleRange = sameScale ? getSameScaleRange(usableSeries) : null;
const buildPath = (series) => {
let minValue;
let maxValue;
const getValueRange = (series) => {
if (sameScaleRange) {
minValue = sameScaleRange.minValue;
maxValue = sameScaleRange.maxValue;
} else {
return {
minValue: sameScaleRange.minValue,
maxValue: sameScaleRange.maxValue
};
}
const rawMinValue = Math.min(...series.points.map((point) => point.v));
const rawMaxValue = Math.max(...series.points.map((point) => point.v));
const rawRange = rawMaxValue - rawMinValue;
const safeRange = rawRange || Math.max(Math.abs(rawMaxValue), 1);
const valuePadding = safeRange * (valuePaddingPercent / 100);
minValue = rawMinValue - valuePadding;
maxValue = rawMaxValue + valuePadding;
}
return {
minValue: rawMinValue - valuePadding,
maxValue: rawMaxValue + valuePadding
};
};
const renderSeries = usableSeries.map((series) => {
const range = getValueRange(series);
return {
...series,
__minValue: range.minValue,
__maxValue: range.maxValue
};
});
const buildPath = (series) => {
const minValue = series.__minValue;
const maxValue = series.__maxValue;
const timeRange = globalMaxTime - globalMinTime || 1;
const valueRange = maxValue - minValue || 1;
@@ -685,7 +774,7 @@ unique_bubble_graph:
.join(" ");
};
const paths = usableSeries.map((series, index) => {
const paths = renderSeries.map((series, index) => {
const linePath = buildPath(series);
const areaPath = `${linePath} L ${width} ${height} L 0 ${height} Z`;
@@ -714,7 +803,7 @@ unique_bubble_graph:
</svg>
`;
host.__bubbleHistorySeries = usableSeries;
host.__bubbleHistorySeries = renderSeries;
host.__bubbleHistoryMinTime = globalMinTime;
host.__bubbleHistoryMaxTime = globalMaxTime;
attachTooltipOnce();
@@ -1197,6 +1286,19 @@ unique_bubble_graph:
label: Tooltip anzeigen
selector:
boolean: null
- name: tooltip_indicator
label: Tooltip Markierung
selector:
select:
options:
- label: Punkte auf dem Graphen
value: points
- label: Vertikale Linie
value: line
- label: Punkte und Linie
value: both
- label: Keine Markierung
value: none
- name: tooltip_top
label: Tooltip Position oben
selector: