Tag-Ansicht: Zeitfenster-Doppelschieberegler (00-24 Uhr, stuendlich) ueber der Tabelle
Default = Auto (erste bis letzte Aktivitaet, auf volle Stunden). Zwei Fader zum Zusammenschieben (z.B. aktuelle Stunde). Balken werden aufs Fenster gekappt (overflow). "Ganzer Zeitraum"-Reset zurueck auf Auto. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+81
-5
@@ -2096,6 +2096,56 @@ function _renderGenericCompareBody(rows, simId) {
|
||||
return html;
|
||||
}
|
||||
|
||||
// Zeitfenster-Filter für die Tag-Ansicht (Stunden 0–24; null = Auto = erste bis
|
||||
// letzte Aktivität). Wird vom Doppel-Schieberegler über der Tabelle gesetzt.
|
||||
var _liveWin = { from: null, to: null };
|
||||
function _pad2(n){ return ('0'+n).slice(-2); }
|
||||
// Stunde/Minute in Wiener Zeit aus ms-Epoch.
|
||||
function _vHM(ms){
|
||||
var s = new Date(ms).toLocaleString('en-GB', {timeZone:'Europe/Vienna', hour:'2-digit', minute:'2-digit', hour12:false});
|
||||
var p = s.split(':'); return { h: parseInt(p[0],10)||0, m: parseInt(p[1],10)||0 };
|
||||
}
|
||||
function _tsInjectCss(){
|
||||
if (document.getElementById('ts-css')) return;
|
||||
var s = document.createElement('style'); s.id = 'ts-css';
|
||||
s.textContent =
|
||||
'.ts-wrap{margin:.2rem 0 .7rem}'
|
||||
+'.ts-head{font-size:.74rem;color:#5a5a5a;margin-bottom:.5rem;display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}'
|
||||
+'.ts-head b{color:#1f4b37;font-variant-numeric:tabular-nums}'
|
||||
+'.ts-reset{font-size:.66rem;padding:.2rem .5rem;border:1px solid rgba(0,0,0,.15);border-radius:6px;background:#fff;color:#4a7c8a;cursor:pointer;font-weight:600}'
|
||||
+'.ts-reset:hover{background:#f0f8fa}'
|
||||
+'.ts-slider{position:relative;height:34px;margin:0 10px}'
|
||||
+'.ts-track{position:absolute;left:0;right:0;top:15px;height:5px;border-radius:3px;background:#e3e0d5}'
|
||||
+'.ts-range{position:absolute;top:15px;height:5px;border-radius:3px;background:#4a7c8a}'
|
||||
+'.ts-slider input[type=range]{position:absolute;left:0;width:100%;top:0;height:34px;margin:0;background:none;pointer-events:none;-webkit-appearance:none;appearance:none}'
|
||||
+'.ts-slider input[type=range]::-webkit-slider-thumb{pointer-events:auto;-webkit-appearance:none;appearance:none;width:22px;height:22px;border-radius:50%;background:#4a7c8a;border:3px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.35);cursor:pointer;margin-top:0}'
|
||||
+'.ts-slider input[type=range]::-moz-range-thumb{pointer-events:auto;width:20px;height:20px;border-radius:50%;background:#4a7c8a;border:3px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.35);cursor:pointer}'
|
||||
+'.ts-slider input[type=range]::-webkit-slider-runnable-track{background:none;height:34px}'
|
||||
+'.ts-ticks{position:relative;height:12px;margin:0 10px}'
|
||||
+'.ts-ticks span{position:absolute;top:0;transform:translateX(-50%);font-size:.54rem;color:#a8a8a8}';
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
// Schieberegler-Interaktion (global, für inline-Handler).
|
||||
function _tsClamp(){
|
||||
var fe=document.getElementById('tsFrom'), te=document.getElementById('tsTo');
|
||||
if(!fe||!te) return null;
|
||||
var f=+fe.value, t=+te.value;
|
||||
if(f>=t){ if(f>=24){f=23;} t=Math.min(24,f+1); if(+te.value<t) te.value=t; if(+fe.value>f) fe.value=f; }
|
||||
return {f:f,t:t};
|
||||
}
|
||||
function _tsVisual(){
|
||||
var v=_tsClamp(); if(!v) return;
|
||||
var r=document.getElementById('tsRange'); if(r){ r.style.left=(v.f/24*100)+'%'; r.style.width=((v.t-v.f)/24*100)+'%'; }
|
||||
var l=document.getElementById('tsLbl'); if(l) l.textContent=_pad2(v.f)+':00 – '+_pad2(v.t)+':00';
|
||||
}
|
||||
function _tsCommit(){
|
||||
var v=_tsClamp(); if(!v) return;
|
||||
_liveWin.from=v.f; _liveWin.to=v.t;
|
||||
renderLiveSummary();
|
||||
}
|
||||
function _tsReset(){ _liveWin.from=null; _liveWin.to=null; renderLiveSummary(); }
|
||||
window._tsVisual=_tsVisual; window._tsCommit=_tsCommit; window._tsReset=_tsReset;
|
||||
|
||||
async function renderLiveSummary() {
|
||||
console.log('[live-summary] renderLiveSummary() aufgerufen, date='+_liveDate);
|
||||
var host = document.getElementById('tab-live');
|
||||
@@ -2183,10 +2233,17 @@ async function renderLiveSummary() {
|
||||
});
|
||||
var dayBase = new Date(_liveDate+'T00:00:00').getTime();
|
||||
if (!isFinite(minMs)) { minMs = dayBase + 8*3600*1000; maxMs = dayBase + 14*3600*1000; }
|
||||
var PAD_MS = 4*60*1000; // knappes Polster vorne/hinten
|
||||
var winStart = minMs - PAD_MS;
|
||||
var winEnd = maxMs + PAD_MS;
|
||||
if (winEnd - winStart < 30*60*1000) winEnd = winStart + 30*60*1000; // min. 30-min-Fenster
|
||||
// Auto-Grenzen (volle Stunden, Wiener Zeit): erste bis letzte Aktivität.
|
||||
var _lo=_vHM(minMs), _hi=_vHM(maxMs);
|
||||
var autoFromH = Math.max(0, _lo.h);
|
||||
var autoToH = Math.min(24, _hi.h + ((_hi.m>0)?1:0));
|
||||
if (autoToH <= autoFromH) autoToH = Math.min(24, autoFromH+1);
|
||||
// Effektives Fenster: Schieberegler-Auswahl (falls gesetzt) ODER Auto.
|
||||
var fromH = (_liveWin.from!=null) ? _liveWin.from : autoFromH;
|
||||
var toH = (_liveWin.to !=null) ? _liveWin.to : autoToH;
|
||||
if (toH <= fromH) toH = Math.min(24, fromH+1);
|
||||
var winStart = dayBase + fromH*3600*1000;
|
||||
var winEnd = dayBase + toH*3600*1000;
|
||||
var winSpanMs = winEnd - winStart;
|
||||
function _msToPct(ms) { return ((ms - winStart) / winSpanMs) * 100; }
|
||||
function _fmtHM(ms) {
|
||||
@@ -2199,6 +2256,25 @@ async function renderLiveSummary() {
|
||||
+ _fmtHM(winStart) + '–' + _fmtHM(winEnd)
|
||||
+ ' · Klick auf Balken öffnet Details.</p>';
|
||||
|
||||
// Zeitfenster-Schieberegler (00–24 Uhr, stündlich; zwei Fader). Default = Auto
|
||||
// (erste bis letzte Aktivität). onchange committet + rendert neu, oninput nur Visual.
|
||||
_tsInjectCss();
|
||||
var _isAuto = (_liveWin.from==null && _liveWin.to==null);
|
||||
var _ticks=''; for (var _h=0;_h<=24;_h+=3){ _ticks += '<span style="left:'+(_h/24*100)+'%">'+_pad2(_h)+'</span>'; }
|
||||
html += '<div class="ts-wrap">'
|
||||
+ '<div class="ts-head">🕒 Zeitraum <b id="tsLbl">'+_pad2(fromH)+':00 – '+_pad2(toH)+':00</b>'
|
||||
+ (_isAuto ? '<span style="color:#8a8a8a;font-size:.66rem">Auto: erste – letzte Aktivität</span>'
|
||||
: '<button class="ts-reset" onclick="_tsReset()">↺ ganzer Zeitraum</button>')
|
||||
+ '</div>'
|
||||
+ '<div class="ts-slider">'
|
||||
+ '<div class="ts-track"></div>'
|
||||
+ '<div class="ts-range" id="tsRange" style="left:'+(fromH/24*100)+'%;width:'+((toH-fromH)/24*100)+'%"></div>'
|
||||
+ '<input type="range" id="tsFrom" min="0" max="24" step="1" value="'+fromH+'" aria-label="Von" oninput="_tsVisual()" onchange="_tsCommit()">'
|
||||
+ '<input type="range" id="tsTo" min="0" max="24" step="1" value="'+toH+'" aria-label="Bis" oninput="_tsVisual()" onchange="_tsCommit()">'
|
||||
+ '</div>'
|
||||
+ '<div class="ts-ticks">'+_ticks+'</div>'
|
||||
+ '</div>';
|
||||
|
||||
// Marker an sauberen Uhrzeiten INNERHALB des Fensters — Schrittweite passt sich
|
||||
// der Spanne an (kurze Stunde = 15-min-Takt, langer Tag = Stunden-Takt), damit
|
||||
// die Achse weder leer noch überladen wirkt. Erster Marker = erste saubere Zeit
|
||||
@@ -2238,7 +2314,7 @@ async function renderLiveSummary() {
|
||||
html += '<div style="height:28px;background:repeating-linear-gradient(45deg,rgba(0,0,0,.02) 0 6px,transparent 6px 12px);border-radius:4px;display:flex;align-items:center;padding:0 .6rem;font-size:.66rem;color:#aaa;font-style:italic">nicht gespielt</div>';
|
||||
return;
|
||||
}
|
||||
html += '<div style="position:relative;height:28px;background:#fafaf6;border-radius:4px">';
|
||||
html += '<div style="position:relative;height:28px;background:#fafaf6;border-radius:4px;overflow:hidden">';
|
||||
// Stunden-Hilfslinien im Hintergrund
|
||||
scaleMarks.forEach(function(mk){
|
||||
if (!mk.isHour) return;
|
||||
|
||||
Reference in New Issue
Block a user