tools:ur-timer
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
| Beide Seiten, vorherige ÜberarbeitungVorherige ÜberarbeitungNächste Überarbeitung | Vorherige Überarbeitung | ||
| tools:ur-timer [12/03/2026 08:57] – Eric Weber | tools:ur-timer [18/03/2026 19:44] (aktuell) – Eric Weber | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| < | < | ||
| - | |||
| - | <html lang=" | ||
| - | < | ||
| - | <meta charset=" | ||
| - | <meta name=" | ||
| - | < | ||
| <link href=" | <link href=" | ||
| < | < | ||
| Zeile 75: | Zeile 69: | ||
| SETUP SCREEN | SETUP SCREEN | ||
| ═══════════════════════════════════════════════════ */ | ═══════════════════════════════════════════════════ */ | ||
| - | #ut-setup { padding: 20px 40px; gap: 0; } | + | #ut-setup { padding: 20px 24px; gap: 0; box-sizing: border-box; } |
| .ut-hdr { text-align: center; margin-bottom: | .ut-hdr { text-align: center; margin-bottom: | ||
| .ut-hdr h1 { | .ut-hdr h1 { | ||
| font-family: | font-family: | ||
| - | font-size: clamp(24px, 3.8vw, 46px); | + | font-size: clamp(22px, 5%, 46px); |
| letter-spacing: | letter-spacing: | ||
| background: linear-gradient(135deg, | background: linear-gradient(135deg, | ||
| Zeile 99: | Zeile 93: | ||
| grid-template-columns: | grid-template-columns: | ||
| gap: 12px; | gap: 12px; | ||
| - | width: | + | width: |
| + | max-width: | ||
| margin-bottom: | margin-bottom: | ||
| + | box-sizing: border-box; | ||
| } | } | ||
| Zeile 234: | Zeile 230: | ||
| display: flex; | display: flex; | ||
| gap: 10px; | gap: 10px; | ||
| - | width: | + | width: |
| + | max-width: | ||
| align-items: | align-items: | ||
| + | box-sizing: border-box; | ||
| } | } | ||
| .ut-start-btn { | .ut-start-btn { | ||
| Zeile 241: | Zeile 239: | ||
| padding: 15px 40px; | padding: 15px 40px; | ||
| border-radius: | border-radius: | ||
| - | border: none; | + | border: none !important; |
| - | background: linear-gradient(160deg, | + | background: linear-gradient(160deg, |
| - | color: #fff; | + | color: #fff !important; |
| font-family: | font-family: | ||
| font-size: 18px; | font-size: 18px; | ||
| letter-spacing: | letter-spacing: | ||
| cursor: pointer; | cursor: pointer; | ||
| - | transition: | + | transition: |
| box-shadow: 0 2px 0 #166534, 0 5px 18px rgba(22, | box-shadow: 0 2px 0 #166534, 0 5px 18px rgba(22, | ||
| text-shadow: | text-shadow: | ||
| Zeile 254: | Zeile 252: | ||
| .ut-start-btn: | .ut-start-btn: | ||
| transform: translateY(-1px); | transform: translateY(-1px); | ||
| + | background: linear-gradient(160deg, | ||
| + | color: #fff !important; | ||
| box-shadow: 0 3px 0 #166534, 0 8px 26px rgba(22, | box-shadow: 0 3px 0 #166534, 0 8px 26px rgba(22, | ||
| } | } | ||
| Zeile 302: | Zeile 302: | ||
| display: none; | display: none; | ||
| text-align: center; | text-align: center; | ||
| - | width: | + | width: |
| + | max-width: | ||
| } | } | ||
| .ut-wait-note.show { display: block; } | .ut-wait-note.show { display: block; } | ||
| Zeile 322: | Zeile 323: | ||
| position: relative; | position: relative; | ||
| width: 100%; | width: 100%; | ||
| + | /* dvh = dynamic viewport height, berücksichtigt iOS Browser-Chrome */ | ||
| height: 100vh; | height: 100vh; | ||
| - | min-height: | + | height: 100dvh; |
| + | min-height: | ||
| + | overflow: hidden; | ||
| + | flex-direction: | ||
| } | } | ||
| Zeile 352: | Zeile 357: | ||
| width: 7ch; | width: 7ch; | ||
| flex-shrink: | flex-shrink: | ||
| + | white-space: | ||
| + | display: flex !important; | ||
| + | flex-direction: | ||
| + | align-items: | ||
| } | } | ||
| .ut-topinfo { | .ut-topinfo { | ||
| Zeile 393: | Zeile 402: | ||
| /* Jede Ziffer in einer eigenen Box — absolute Pixelbreite */ | /* Jede Ziffer in einer eigenen Box — absolute Pixelbreite */ | ||
| .utd { | .utd { | ||
| - | display: inline-block; | + | display: inline-block |
| width: 0.62em; | width: 0.62em; | ||
| text-align: center; | text-align: center; | ||
| Zeile 401: | Zeile 410: | ||
| /* Ziffern für Prozentwert */ | /* Ziffern für Prozentwert */ | ||
| .utdd { | .utdd { | ||
| - | display: inline-block; | + | display: inline-block |
| width: 0.62em; | width: 0.62em; | ||
| text-align: center; | text-align: center; | ||
| Zeile 409: | Zeile 418: | ||
| /* Prozentzeichen — feste Breite */ | /* Prozentzeichen — feste Breite */ | ||
| .utdpc { | .utdpc { | ||
| - | display: inline-block; | + | display: inline-block |
| width: 0.7em; | width: 0.7em; | ||
| text-align: center; | text-align: center; | ||
| Zeile 424: | Zeile 433: | ||
| .ut-chip.gc .utv { color: #16a34a; } | .ut-chip.gc .utv { color: #16a34a; } | ||
| + | |||
| + | .ut-fsbtn { | ||
| + | position: absolute; | ||
| + | top: 10px; | ||
| + | right: 10px; | ||
| + | z-index: 100; | ||
| + | width: 34px; | ||
| + | height: 34px; | ||
| + | border-radius: | ||
| + | border: 1.5px solid rgba(0, | ||
| + | background: rgba(255, | ||
| + | color: #6b7280 !important; | ||
| + | font-size: 17px; | ||
| + | line-height: | ||
| + | cursor: pointer; | ||
| + | display: flex !important; | ||
| + | align-items: | ||
| + | justify-content: | ||
| + | transition: background 0.15s, color 0.15s, border-color 0.15s; | ||
| + | padding: 0; | ||
| + | box-shadow: 0 1px 6px rgba(0, | ||
| + | } | ||
| + | .ut-fsbtn: | ||
| + | background: #fff !important; | ||
| + | color: #16a34a !important; | ||
| + | border-color: | ||
| + | } | ||
| + | .ut-fsbtn.ut-fs-on { | ||
| + | color: #dc2626 !important; | ||
| + | border-color: | ||
| + | background: #fee2e2 !important; | ||
| + | } | ||
| + | .ut-fsbtn.ut-fs-on: | ||
| + | background: #dc2626 !important; | ||
| + | color: #fff !important; | ||
| + | } | ||
| + | |||
| + | /* Vollbild-Modus: | ||
| + | body.ut-fs-active { | ||
| + | overflow: hidden !important; | ||
| + | position: fixed !important; | ||
| + | width: 100% !important; | ||
| + | } | ||
| + | # | ||
| + | position: fixed !important; | ||
| + | top: 0 !important; | ||
| + | left: 0 !important; | ||
| + | width: 100% !important; | ||
| + | height: 100vh !important; | ||
| + | height: 100dvh !important; | ||
| + | z-index: 99999 !important; | ||
| + | background: #fff !important; | ||
| + | overflow-y: auto !important; | ||
| + | overflow-x: hidden !important; | ||
| + | } | ||
| + | /* Timer-Screen im Vollbild: volle Höhe */ | ||
| + | # | ||
| + | height: 100vh !important; | ||
| + | height: 100dvh !important; | ||
| + | } | ||
| + | /* Ergebnis-Screen im Vollbild: immer sichtbar über Timer */ | ||
| + | # | ||
| + | position: fixed !important; | ||
| + | inset: 0 !important; | ||
| + | z-index: 100001 !important; | ||
| + | } | ||
| + | /* Vollbild-Button im Vollbild: über allem */ | ||
| + | # | ||
| + | position: fixed !important; | ||
| + | top: 10px !important; | ||
| + | right: 10px !important; | ||
| + | z-index: 100002 !important; | ||
| + | } | ||
| .ut-otbadge { | .ut-otbadge { | ||
| Zeile 450: | Zeile 532: | ||
| padding: 10px 14px; | padding: 10px 14px; | ||
| min-height: 0; | min-height: 0; | ||
| + | overflow: hidden; | ||
| } | } | ||
| .ut-panel { | .ut-panel { | ||
| Zeile 493: | Zeile 576: | ||
| font-family: | font-family: | ||
| line-height: | line-height: | ||
| - | letter-spacing: | + | letter-spacing: |
| + | display: flex !important; | ||
| + | flex-direction: | ||
| + | align-items: | ||
| + | justify-content: | ||
| + | } | ||
| + | /* Einzelne Ziffer im Ring */ | ||
| + | .utrt { | ||
| + | display: inline-block !important; | ||
| + | width: 0.58em; | ||
| + | text-align: center; | ||
| + | font-family: | ||
| + | font-variant-numeric: | ||
| + | } | ||
| + | /* Doppelpunkt im Ring */ | ||
| + | .utrtc { | ||
| + | display: inline-block !important; | ||
| + | width: 0.28em; | ||
| + | text-align: center; | ||
| + | font-family: | ||
| } | } | ||
| .ut-rstat { | .ut-rstat { | ||
| Zeile 524: | Zeile 626: | ||
| } | } | ||
| .ut-rcard { | .ut-rcard { | ||
| - | width: min(640px, | + | width: min(640px, |
| background: #fff; | background: #fff; | ||
| border: 1.5px solid rgba(0, | border: 1.5px solid rgba(0, | ||
| Zeile 534: | Zeile 636: | ||
| .ut-rtitle { | .ut-rtitle { | ||
| font-family: | font-family: | ||
| - | font-size: clamp(26px, | + | font-size: clamp(26px, |
| letter-spacing: | letter-spacing: | ||
| margin-bottom: | margin-bottom: | ||
| Zeile 596: | Zeile 698: | ||
| } | } | ||
| /* ══════════════════════════════════════════════════ | /* ══════════════════════════════════════════════════ | ||
| - | RESPONSIVE — Tablet & Mobile | + | RESPONSIVE — Container-basiert (kein vw/vh) |
| + | Klassen werden per JS auf #ut-app gesetzt | ||
| ═══════════════════════════════════════════════════ */ | ═══════════════════════════════════════════════════ */ | ||
| - | /* Tablet: schmaler als 700px */ | + | /* Schmaler Container < 700px */ |
| - | @media (max-width: 700px) { | + | #ut-app.ut-sm |
| - | #ut-setup { padding: 14px 16px; overflow-y: auto; justify-content: | + | # |
| - | + | # | |
| - | .ut-hdr { margin-bottom: | + | # |
| - | .ut-hdr h1 { font-size: | + | #ut-app.ut-sm .ut-grid { |
| - | .ut-hdr p { font-size: 10px; letter-spacing: 1.5px; } | + | |
| - | + | ||
| - | .ut-grid { | + | |
| grid-template-columns: | grid-template-columns: | ||
| - | width: 100%; | ||
| gap: 10px; | gap: 10px; | ||
| margin-bottom: | margin-bottom: | ||
| } | } | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| - | /* Ziel-Karte nimmt alle Spalten ein */ | + | /* Sehr schmaler Container < 480px */ |
| - | .ut-grid .ut-card: | + | #ut-app.ut-xs #ut-setup { padding: |
| - | + | #ut-app.ut-xs .ut-hdr h1 { font-size: | |
| - | .ut-btnrow | + | #ut-app.ut-xs .ut-grid { grid-template-columns: |
| - | .ut-start-btn { font-size: 16px; padding: | + | # |
| - | .ut-now-btn | + | #ut-app.ut-xs |
| - | + | # | |
| - | .ut-wait-note { width: 100%; font-size: | + | |
| - | + | ||
| - | /* Timer-Leiste: | + | |
| - | .ut-topbar { flex-wrap: wrap; padding: 8px 12px; gap: 6px; } | + | |
| - | .ut-topinfo { gap: 8px; width: 100%; justify-content: | + | |
| - | .ut-clock { font-size: | + | |
| - | .ut-chip { font-size: 9px; gap: 3px; } | + | |
| - | .ut-chip .utv { font-size: 11px; } | + | |
| - | .ut-chip .utv.utv-time { width: 5ch; } | + | |
| - | .ut-chip .utv.utv-pct | + | |
| - | + | ||
| - | /* Timer-Ringe kleiner */ | + | |
| - | .ut-area { padding: 6px 10px; } | + | |
| - | } | + | |
| - | + | ||
| - | /* Smartphone Hochkant: schmaler als 480px */ | + | |
| - | @media (max-width: 480px) { | + | |
| - | #ut-setup { padding: 12px 12px; } | + | |
| - | + | ||
| - | .ut-grid { grid-template-columns: | + | |
| - | .ut-grid .ut-card: | + | |
| - | + | ||
| - | /* Ziel-Karte: vertikal stapeln */ | + | |
| - | .ut-grid .ut-card[style*=“flex-direction: | + | |
| - | .ut-grid .ut-card[style*=“flex-direction: | + | |
| flex-direction: | flex-direction: | ||
| align-items: | align-items: | ||
| } | } | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| - | .ut-card { padding: 16px 16px; } | + | /* Querformat |
| - | .ut-card select { font-size: 15px; padding: 13px 36px 13px 14px; } | + | |
| - | .ut-tbtn { font-size: 13px; padding: 12px 12px; } | + | |
| - | + | ||
| - | .ut-start-btn { font-size: 15px; letter-spacing: | + | |
| - | .ut-now-btn | + | |
| - | + | ||
| - | /* Topbar: alles kompakter */ | + | |
| - | .ut-clock { font-size: 15px; } | + | |
| - | .ut-chip | + | |
| - | .ut-chip .utv { font-size: 11px; } | + | |
| - | .ut-otbadge { font-size: 9px; padding: 2px 8px; } | + | |
| - | + | ||
| - | /* Timer-Ringe: | + | |
| - | .ut-area { flex-direction: | + | |
| - | .ut-divider { width: 60%; height: 1.5px; } | + | |
| - | .ut-panel { height: auto; flex: 0 0 auto; } | + | |
| - | } | + | |
| - | + | ||
| - | /* Querformat erzwingen wenn klein genug */ | + | |
| @media (max-height: | @media (max-height: | ||
| #ut-setup { flex-direction: | #ut-setup { flex-direction: | ||
| Zeile 680: | Zeile 755: | ||
| </ | </ | ||
| - | </ | ||
| - | < | ||
| - | |||
| <div id=" | <div id=" | ||
| + | <!-- Vollbild-Button: | ||
| + | <button class=" | ||
| <!-- ══ SETUP ══ --> | <!-- ══ SETUP ══ --> | ||
| - | |||
| <div id=" | <div id=" | ||
| <div class=" | <div class=" | ||
| Zeile 692: | Zeile 764: | ||
| < | < | ||
| </ | </ | ||
| - | + | | |
| - | ``` | + | <div class=" |
| - | <div class=" | + | < |
| - | <div class=" | + | <select id=" |
| - | < | + | </ |
| - | <select id=" | + | <div class=" |
| - | </ | + | < |
| - | + | <select id=" | |
| - | | + | <option value=" |
| - | < | + | <option value=" |
| - | <select id=" | + | </ |
| - | <option value=" | + | </ |
| - | <option value=" | + | <div class=" |
| - | </ | + | < |
| - | </ | + | <div class=" |
| - | + | <button class=" | |
| - | | + | <button class=" |
| - | < | + | </ |
| - | <div class=" | + | </ |
| - | <button class=" | + | <div class=" |
| - | <button class=" | + | <div style=" |
| + | <div class=" | ||
| + | <div class=" | ||
| + | </ | ||
| + | <div style=" | ||
| + | <label class=" | ||
| + | <input type=" | ||
| + | <div class=" | ||
| + | </ | ||
| + | </div> | ||
| </ | </ | ||
| - | </ | + | |
| - | + | <button | |
| - | | + | <button |
| - | <div style=" | + | |
| - | <div class=" | + | |
| - | <div class=" | + | |
| </ | </ | ||
| - | < | + | <div class=" |
| - | < | + | |
| - | <input type=" | + | & |
| - | <div class="ut-rlabels">< | + | |
| </ | </ | ||
| </ | </ | ||
| - | </ | ||
| - | |||
| - | <div class=" | ||
| - | <button class=" | ||
| - | <button class=" | ||
| - | </ | ||
| - | <div class=" | ||
| - | Warte auf Startzeit: <span id=" | ||
| - | & | ||
| - | <button onclick=" | ||
| - | </ | ||
| - | ``` | ||
| - | |||
| - | </ | ||
| - | |||
| <!-- ══ TIMER ══ --> | <!-- ══ TIMER ══ --> | ||
| - | |||
| <div id=" | <div id=" | ||
| <div class=" | <div class=" | ||
| Zeile 755: | Zeile 817: | ||
| </ | </ | ||
| </ | </ | ||
| - | + | | |
| - | ``` | + | <!-- GREEN --> |
| - | <div class=" | + | <div class=" |
| - | <!-- GREEN --> | + | <div class=" |
| - | <div class=" | + | <svg id=" |
| - | <div class=" | + | <circle cx=" |
| - | <svg id=" | + | <circle cx=" |
| - | <circle cx=" | + | <circle id=" |
| - | <circle cx=" | + | stroke="# |
| - | <circle id=" | + | stroke-dasharray=" |
| - | stroke="# | + | transform=" |
| - | stroke-dasharray=" | + | </ |
| - | transform=" | + | <div class=" |
| - | </ | + | <div class=" |
| - | <div class=" | + | <div class=" |
| - | <div class=" | + | <div class=" |
| - | <div class=" | + | </ |
| - | <div class=" | + | |
| </ | </ | ||
| - | </ | + | |
| - | </ | + | <!-- RED --> |
| - | + | <div class=" | |
| - | | + | <div class=" |
| - | + | <svg id=" | |
| - | | + | <circle cx=" |
| - | <div class=" | + | <circle cx=" |
| - | <div class=" | + | <circle id=" |
| - | <svg id=" | + | stroke="# |
| - | <circle cx=" | + | stroke-dasharray=" |
| - | <circle cx=" | + | transform=" |
| - | <circle id=" | + | </ |
| - | stroke="# | + | <div class=" |
| - | stroke-dasharray=" | + | <div class=" |
| - | transform=" | + | <div class=" |
| - | </ | + | <div class=" |
| - | <div class=" | + | </ |
| - | <div class=" | + | |
| - | <div class=" | + | |
| - | <div class=" | + | |
| </ | </ | ||
| </ | </ | ||
| </ | </ | ||
| - | </ | ||
| - | ``` | ||
| - | |||
| - | </ | ||
| - | |||
| <!-- ══ RESULT ══ --> | <!-- ══ RESULT ══ --> | ||
| - | |||
| <div id=" | <div id=" | ||
| <div class=" | <div class=" | ||
| Zeile 828: | Zeile 882: | ||
| </ | </ | ||
| </ | </ | ||
| - | |||
| </ | </ | ||
| + | < | ||
| + | (function(){ | ||
| + | 'use strict'; | ||
| + | |||
| + | var cfg = { startH:7, startM:0, duration: | ||
| + | var st = { phase: | ||
| + | total:0, limit:0, wIv:null, tIv:null, cIv:null }; | ||
| + | |||
| + | /* ── helpers ── */ | ||
| + | function pad(n){ return String(n).padStart(2, | ||
| + | function berlin(){ | ||
| + | var d=new Date(), b=new Date(d.toLocaleString(‘en-US’, | ||
| + | return {h: | ||
| + | } | ||
| + | function mmss(ms){ | ||
| + | var s=Math.floor(ms/ | ||
| + | return pad(m)+’: | ||
| + | } | ||
| + | function el(id){ return document.getElementById(id); | ||
| + | |||
| + | /* ── Init ── */ | ||
| + | function init(){ | ||
| + | var sel=el(‘ut-sel-start’); | ||
| + | for(var h=7; | ||
| + | for(var m=0; | ||
| + | if(h===17&& | ||
| + | var o=document.createElement(‘option’); | ||
| + | o.value=h+’: | ||
| + | o.textContent=pad(h)+’: | ||
| + | sel.appendChild(o); | ||
| + | } | ||
| + | } | ||
| + | var now=berlin(), | ||
| + | if(bm> | ||
| + | if(bh> | ||
| + | sel.value=bh+’: | ||
| + | startClock(); | ||
| + | } | ||
| + | |||
| + | function startClock(){ | ||
| + | function tick(){ | ||
| + | var b=berlin(); | ||
| + | var hh=pad(b.h), | ||
| + | el(‘utd-ch0’).textContent=hh[0]; | ||
| + | el(‘utd-cm0’).textContent=mm[0]; | ||
| + | el(‘utd-cs0’).textContent=ss[0]; | ||
| + | } | ||
| + | tick(); | ||
| + | st.cIv=setInterval(tick, | ||
| + | } | ||
| + | |||
| + | /* ── Setup callbacks ── */ | ||
| + | window.utSetFirst=function(w){ | ||
| + | cfg.first=w; | ||
| + | el(‘ut-btn-g’).classList.toggle(‘active’, | ||
| + | el(‘ut-btn-r’).classList.toggle(‘active’, | ||
| + | }; | ||
| + | window.utGoal=function(v){ | ||
| + | cfg.goal=parseInt(v); | ||
| + | el(‘ut-goal-val’).textContent=v+’%’; | ||
| + | el(‘ut-slider’).value=v; | ||
| + | }; | ||
| + | function applyCfg(){ | ||
| + | var p=el(‘ut-sel-start’).value.split(’: | ||
| + | cfg.startH=p[0]; | ||
| + | cfg.duration=parseInt(el(‘ut-sel-dur’).value); | ||
| + | st.limit=cfg.duration*60*1000; | ||
| + | } | ||
| + | window.utConfirm=function(){ | ||
| + | applyCfg(); | ||
| + | el(‘ut-sbtn’).disabled=true; | ||
| + | el(‘ut-nbtn’).disabled=true; | ||
| + | el(‘ut-sbtn’).textContent=‘Warte auf Startzeit…’; | ||
| + | el(‘ut-wnote’).classList.add(‘show’); | ||
| + | updWait(); | ||
| + | st.wIv=setInterval(function(){ | ||
| + | updWait(); | ||
| + | var n=berlin(); | ||
| + | if(n.h===cfg.startH&& | ||
| + | clearInterval(st.wIv); | ||
| + | } | ||
| + | },500); | ||
| + | }; | ||
| + | window.utNow=function(){ | ||
| + | clearInterval(st.wIv); | ||
| + | applyCfg(); | ||
| + | begin(); | ||
| + | }; | ||
| + | function updWait(){ el(‘ut-wdisp’).textContent=pad(cfg.startH)+’: | ||
| + | |||
| + | /* ── Begin ── */ | ||
| + | function begin(){ | ||
| + | st.phase=‘running’; | ||
| + | st.gMs=0; st.rMs=0; st.total=0; | ||
| + | st.last=Date.now(); | ||
| + | el(‘ut-gtop’).textContent=cfg.goal+’%’; | ||
| + | // Verbleibend korrekt initialisieren über Digit-Spans (nicht textContent!) | ||
| + | setMmss(‘utd-rem-0’, | ||
| + | el(‘ut-setup’).style.display=‘none’; | ||
| + | el(‘ut-timer’).style.display=‘flex’; | ||
| + | panels(); resize(); | ||
| + | st.tIv=setInterval(tick, | ||
| + | } | ||
| + | |||
| + | /* ── Tick ── */ | ||
| + | function tick(){ | ||
| + | if(st.phase===‘done’) return; | ||
| + | var now=Date.now(), | ||
| + | if(st.active===‘green’) st.gMs+=d; else st.rMs+=d; | ||
| + | st.total=st.gMs+st.rMs; | ||
| + | if(st.phase===‘running’&& | ||
| + | if(st.active===‘green’){ end(); return; } | ||
| + | else{ st.phase=‘overtime’; | ||
| + | } | ||
| + | render(); | ||
| + | } | ||
| + | |||
| + | /* ── Switch ── */ | ||
| + | window.utSwitch=function(w){ | ||
| + | if(st.phase===‘done’||st.phase===‘idle’) return; | ||
| + | if(st.phase===‘overtime’&& | ||
| + | var now=Date.now(), | ||
| + | if(st.active===‘red’) st.rMs+=d; else st.gMs+=d; | ||
| + | st.total=st.gMs+st.rMs; | ||
| + | end(); return; | ||
| + | } | ||
| + | if(st.active===w) return; | ||
| + | st.active=w; | ||
| + | panels(); render(); | ||
| + | }; | ||
| + | |||
| + | /* ── Digit helpers ── */ | ||
| + | function setMmss(d0, d1, d2, d3, ms){ | ||
| + | var s=Math.floor(ms/ | ||
| + | var mm=pad(m), ss=pad(s%60); | ||
| + | el(d0).textContent=mm[0]; | ||
| + | el(d1).textContent=mm[1]; | ||
| + | el(d2).textContent=ss[0]; | ||
| + | el(d3).textContent=ss[1]; | ||
| + | } | ||
| + | function setGreenPct(gp){ | ||
| + | // Hunderter: ‘1’ bei 100, sonst geschütztes Leerzeichen | ||
| + | el(‘utd-gp-h’).textContent = gp === 100 ? ‘1’ : ‘\u2007’; | ||
| + | // Zehner: Ziffer wenn >= 10, sonst Leerzeichen | ||
| + | el(‘utd-gp-t’).textContent = gp >= 10 ? String(Math.floor(gp / 10) % 10) : ‘\u2007’; | ||
| + | // Einer: immer eine Ziffer | ||
| + | el(‘utd-gp-o’).textContent = String(gp % 10); | ||
| + | } | ||
| + | |||
| + | /* ── Render ── */ | ||
| + | function render(){ | ||
| + | // Ring-Timer: digit-by-digit | ||
| + | setMmss(‘utrt-g0’, | ||
| + | setMmss(‘utrt-r0’, | ||
| + | |||
| + | setMmss(‘utd-total-0’, | ||
| + | setMmss(‘utd-rem-0’, | ||
| + | |||
| + | var gp=st.total> | ||
| + | setGreenPct(gp); | ||
| + | |||
| + | if(st.limit> | ||
| + | var C=816.8; | ||
| + | el(‘ut-prog-g’).style.strokeDashoffset=Math.max(0, | ||
| + | el(‘ut-prog-r’).style.strokeDashoffset=Math.max(0, | ||
| + | } | ||
| + | } | ||
| + | function panels(){ | ||
| + | el(‘ut-pg’).className=‘ut-panel’+(st.active===‘green’? | ||
| + | el(‘ut-pr’).className=‘ut-panel’+(st.active===‘red’? | ||
| + | el(‘ut-sg’).textContent=st.active===‘green’? | ||
| + | el(‘ut-sr’).textContent=st.active===‘red’? | ||
| + | } | ||
| + | |||
| + | /* ── End ── */ | ||
| + | function end(){ | ||
| + | st.phase=‘done’; | ||
| + | var tot=st.total, | ||
| + | setTimeout(function(){ | ||
| + | var gm=(st.gMs/ | ||
| + | el(‘ut-rtitle’).textContent=ok? | ||
| + | el(‘ut-rtitle’).className=‘ut-rtitle ‘+(ok? | ||
| + | el(‘ut-pg-pct’).textContent=gp+’%’; | ||
| + | el(‘ut-ag’).textContent=gm+’ min’; | ||
| + | el(‘ut-rgoal’).innerHTML=‘Ziel: | ||
| + | el(‘ut-result’).style.display=‘flex’; | ||
| + | setTimeout(function(){ el(‘ut-bg’).style.width=gp+’%’; | ||
| + | },350); | ||
| + | } | ||
| + | |||
| + | /* ── Reset ── */ | ||
| + | window.utReset=function(){ | ||
| + | var app=document.getElementById(‘ut-app’); | ||
| + | if(app.classList.contains(‘ut-fs-float’)){ | ||
| + | app.classList.remove(‘ut-fs-float’); | ||
| + | el(‘ut-fsbtn’).classList.remove(‘ut-fs-on’); | ||
| + | document.body.classList.remove(‘ut-fs-active’); | ||
| + | document.body.style.top=’’; | ||
| + | window.scrollTo(0, | ||
| + | var btn=el(‘ut-fsbtn’); | ||
| + | if(btn){ btn.textContent=‘⛶’; | ||
| + | } | ||
| + | clearInterval(st.tIv); | ||
| + | st={phase: | ||
| + | el(‘ut-result’).style.display=‘none’; | ||
| + | el(‘ut-timer’).style.display=‘none’; | ||
| + | el(‘ut-setup’).style.display=‘flex’; | ||
| + | el(‘ut-sbtn’).disabled=false; | ||
| + | el(‘ut-sbtn’).textContent=‘Stunde konfigurieren & warten’; | ||
| + | el(‘ut-wnote’).classList.remove(‘show’); | ||
| + | el(‘ut-otbadge’).style.display=‘none’; | ||
| + | el(‘ut-prog-g’).style.strokeDashoffset=816.8; | ||
| + | el(‘ut-prog-r’).style.strokeDashoffset=816.8; | ||
| + | }; | ||
| + | |||
| + | /* ── Vollbild ── */ | ||
| + | var _fsScrollY = 0; | ||
| + | window.utToggleFS = function(){ | ||
| + | var app = document.getElementById(‘ut-app’); | ||
| + | var btn = el(‘ut-fsbtn’); | ||
| + | var isFS = app.classList.contains(‘ut-fs-float’); | ||
| + | |||
| + | if(!isFS){ | ||
| + | _fsScrollY = window.scrollY; | ||
| + | app.classList.add(‘ut-fs-float’); | ||
| + | btn.classList.add(‘ut-fs-on’); | ||
| + | document.body.classList.add(‘ut-fs-active’); | ||
| + | document.body.style.top = ‘-’ + _fsScrollY + ‘px’; | ||
| + | btn.textContent = ‘✕’; | ||
| + | btn.title = ‘Vollbild beenden’; | ||
| + | } else { | ||
| + | app.classList.remove(‘ut-fs-float’); | ||
| + | btn.classList.remove(‘ut-fs-on’); | ||
| + | document.body.classList.remove(‘ut-fs-active’); | ||
| + | document.body.style.top = ‘’; | ||
| + | window.scrollTo(0, | ||
| + | btn.textContent = ‘⛶’; | ||
| + | btn.title = ‘Vollbild’; | ||
| + | } | ||
| + | setTimeout(resize, | ||
| + | setTimeout(resize, | ||
| + | }; | ||
| + | |||
| + | document.addEventListener(‘keydown’, | ||
| + | if(e.key === ‘Escape’ && document.getElementById(‘ut-app’).classList.contains(‘ut-fs-float’)){ | ||
| + | utToggleFS(); | ||
| + | } | ||
| + | }); | ||
| + | window.addEventListener(‘orientationchange’, | ||
| + | setTimeout(resize, | ||
| + | setTimeout(resize, | ||
| + | }); | ||
| + | function resize(){ | ||
| + | var app=document.getElementById(‘ut-app’); | ||
| + | var isFS = document.getElementById(‘ut-app’) && document.getElementById(‘ut-app’).classList.contains(‘ut-fs-float’); | ||
| + | var w = isFS ? window.innerWidth | ||
| + | |||
| + | // Breakpoints basierend auf tatsächlicher Container-Breite setzen | ||
| + | if(app){ | ||
| + | app.classList.toggle(‘ut-sm’, | ||
| + | app.classList.toggle(‘ut-xs’, | ||
| + | } | ||
| + | |||
| + | var area=document.querySelector(’# | ||
| + | if(!area) return; | ||
| + | |||
| + | // Im Vollbild: Fenstergröße nutzen. Sonst: tatsächliche Element-Größe. | ||
| + | var topbarH = 0; | ||
| + | var tb = document.querySelector(’# | ||
| + | if(tb) topbarH = tb.offsetHeight || 50; | ||
| + | |||
| + | var areaH = isFS | ||
| + | ? (window.innerHeight - topbarH - 10) | ||
| + | : (area.clientHeight > 20 ? area.clientHeight : window.innerHeight - topbarH - 60); | ||
| + | var areaW = isFS ? window.innerWidth : (area.clientWidth > 0 ? area.clientWidth : w); | ||
| + | |||
| + | var sz = Math.max(100, | ||
| + | [‘ut-svg-g’, | ||
| + | var s=el(id); if(s){s.style.width=sz+‘px’; | ||
| + | }); | ||
| + | var fs=Math.max(20, | ||
| + | document.querySelectorAll(’# | ||
| + | } | ||
| + | window.addEventListener(‘resize’, | ||
| + | // Auch beim Laden direkt auswerten | ||
| + | document.addEventListener(‘DOMContentLoaded’, | ||
| + | |||
| + | init(); | ||
| + | resize(); | ||
| + | })(); | ||
| + | </ | ||
| < | < | ||
| Zeile 982: | Zeile 1326: | ||
| /* ── Render ── */ | /* ── Render ── */ | ||
| function render(){ | function render(){ | ||
| - | | + | |
| - | | + | setMmss('utrt-g0',' |
| + | | ||
| setMmss(' | setMmss(' | ||
| Zeile 1022: | Zeile 1367: | ||
| /* ── Reset ── */ | /* ── Reset ── */ | ||
| window.utReset=function(){ | window.utReset=function(){ | ||
| + | var app=document.getElementById(' | ||
| + | if(app.classList.contains(' | ||
| + | app.classList.remove(' | ||
| + | el(' | ||
| + | document.body.classList.remove(' | ||
| + | document.body.style.top=''; | ||
| + | window.scrollTo(0, | ||
| + | var btn=el(' | ||
| + | if(btn){ btn.textContent=' | ||
| + | } | ||
| clearInterval(st.tIv); | clearInterval(st.tIv); | ||
| st={phase:' | st={phase:' | ||
| Zeile 1035: | Zeile 1390: | ||
| }; | }; | ||
| - | /* ── | + | /* ── |
| + | var _fsScrollY = 0; | ||
| + | window.utToggleFS = function(){ | ||
| + | var app = document.getElementById(' | ||
| + | var btn = el(' | ||
| + | var isFS = app.classList.contains(' | ||
| + | |||
| + | if(!isFS){ | ||
| + | _fsScrollY = window.scrollY; | ||
| + | app.classList.add(' | ||
| + | btn.classList.add(' | ||
| + | document.body.classList.add(' | ||
| + | document.body.style.top = ' | ||
| + | btn.textContent = ' | ||
| + | btn.title = ' | ||
| + | } else { | ||
| + | app.classList.remove(' | ||
| + | btn.classList.remove(' | ||
| + | document.body.classList.remove(' | ||
| + | document.body.style.top = ''; | ||
| + | window.scrollTo(0, | ||
| + | btn.textContent = ' | ||
| + | btn.title = ' | ||
| + | } | ||
| + | setTimeout(resize, | ||
| + | setTimeout(resize, | ||
| + | }; | ||
| + | |||
| + | document.addEventListener(' | ||
| + | if(e.key === ' | ||
| + | utToggleFS(); | ||
| + | } | ||
| + | }); | ||
| + | window.addEventListener(' | ||
| + | setTimeout(resize, | ||
| + | setTimeout(resize, | ||
| + | }); | ||
| function resize(){ | function resize(){ | ||
| + | var app=document.getElementById(' | ||
| + | var isFS = document.getElementById(' | ||
| + | var w = isFS ? window.innerWidth | ||
| + | |||
| + | // Breakpoints basierend auf tatsächlicher Container-Breite setzen | ||
| + | if(app){ | ||
| + | app.classList.toggle(' | ||
| + | app.classList.toggle(' | ||
| + | } | ||
| + | |||
| var area=document.querySelector('# | var area=document.querySelector('# | ||
| if(!area) return; | if(!area) return; | ||
| - | | + | |
| - | var areaW = area.clientWidth | + | // Im Vollbild: Fenstergröße nutzen. Sonst: tatsächliche Element-Größe. |
| - | var sz=Math.max(150, Math.min(areaH - 20, areaW / 2 - 44, 340)); | + | var topbarH = 0; |
| + | var tb = document.querySelector('# | ||
| + | if(tb) topbarH = tb.offsetHeight || 50; | ||
| + | |||
| + | | ||
| + | ? (window.innerHeight - topbarH - 10) | ||
| + | : (area.clientHeight > 20 ? area.clientHeight : window.innerHeight | ||
| + | var areaW = isFS ? window.innerWidth : (area.clientWidth > 0 ? area.clientWidth : w); | ||
| + | |||
| + | var sz = Math.max(100, Math.min(areaH - 10, areaW / 2 - 30, 340)); | ||
| [' | [' | ||
| var s=el(id); if(s){s.style.width=sz+' | var s=el(id); if(s){s.style.width=sz+' | ||
| }); | }); | ||
| - | var fs=Math.max(24,sz*0.205); | + | var fs=Math.max(20, sz*0.205); |
| document.querySelectorAll('# | document.querySelectorAll('# | ||
| } | } | ||
| window.addEventListener(' | window.addEventListener(' | ||
| + | // Auch beim Laden direkt auswerten | ||
| + | document.addEventListener(' | ||
| init(); | init(); | ||
| + | resize(); | ||
| })(); | })(); | ||
| </ | </ | ||
| - | </ | ||
| </ | </ | ||
tools/ur-timer.1773302253.txt.gz · Zuletzt geändert: von Eric Weber
