Benutzer-Werkzeuge

Webseiten-Werkzeuge


tools:ur-timer

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Beide Seiten, vorherige ÜberarbeitungVorherige Überarbeitung
Nächste Überarbeitung
Vorherige Überarbeitung
tools:ur-timer [12/03/2026 15:43] Eric Webertools:ur-timer [18/03/2026 19:44] (aktuell) Eric Weber
Zeile 435: Zeile 435:
  
 .ut-fsbtn { .ut-fsbtn {
-margin-leftauto+position: absolute; 
-flex-shrink0+top: 10px; 
-width: 32px+right10px
-height: 32px;+z-index100
 +width: 34px
 +height: 34px;
 border-radius: 8px; border-radius: 8px;
-border: 1.5px solid rgba(0,0,0,0.10); +border: 1.5px solid rgba(0,0,0,0.12!important
-background: rgba(248,249,252,0.95); +background: rgba(255,255,255,0.92!important
-color: #6b7280;+color: #6b7280 !important;
 font-size: 17px; font-size: 17px;
 line-height: 1; line-height: 1;
 cursor: pointer; cursor: pointer;
-display: flex;+display: flex !important;
 align-items: center; align-items: center;
 justify-content: center; justify-content: center;
-transition: all 0.15s;+transition: background 0.15s, color 0.15s, border-color 0.15s;
 padding: 0; padding: 0;
 +box-shadow: 0 1px 6px rgba(0,0,0,0.10);
 } }
 .ut-fsbtn:hover { .ut-fsbtn:hover {
-background: #fff; +background: #fff !important
-color: #16a34a; +color: #16a34a !important
-border-color: #16a34a; +border-color: #16a34a !important
-box-shadow0 2px 8px rgba(22,163,74,0.15);+
 +.ut-fsbtn.ut-fs-on { 
 +color#dc2626 !important; 
 +border-color: #dc2626 !important; 
 +background: #fee2e2 !important; 
 +
 +.ut-fsbtn.ut-fs-on:hover { 
 +background: #dc2626 !important; 
 +color: #fff !important;
 } }
  
-/* Vollbild-Modus: body wird gesperrt, Timer liegt direkt auf body */+/* Vollbild-Modus: gesamte App wird auf Vollbild gesetzt */
 body.ut-fs-active { body.ut-fs-active {
 overflow: hidden !important; overflow: hidden !important;
Zeile 465: Zeile 476:
 width: 100% !important; width: 100% !important;
 } }
-#ut-timer.ut-fs-float {+#ut-app.ut-fs-float {
 position: fixed !important; position: fixed !important;
 top: 0 !important; top: 0 !important;
Zeile 474: Zeile 485:
 z-index: 99999 !important; z-index: 99999 !important;
 background: #fff !important; background: #fff !important;
-display: flex !important; +overflow-yauto !important; 
-flex-directioncolumn !important; +overflow-x: hidden !important;
-min-height: 0 !important; +
-overflow: hidden !important;+
 } }
-#ut-timer.ut-fs-float .ut-area +/* Timer-Screen im Vollbild: volle Höhe */ 
-flex: 1 !important; +#ut-app.ut-fs-float #ut-timer 
-min-height: !important; +height: 100vh !important; 
-height: !important;+height: 100dvh !important;
 } }
-.ut-fsbtn.ut-fs-on +/* Ergebnis-Screen im Vollbild: immer sichtbar über Timer */ 
-color#dc2626 !important; +#ut-app.ut-fs-float #ut-result 
-border-color#dc2626 !important; +positionfixed !important; 
-background: #fee2e2 !important;+inset: 0 !important; 
 +z-index100001 !important; 
 +
 +/* Vollbild-Button im Vollbildüber allem */ 
 +#ut-app.ut-fs-float .ut-fsbtn { 
 +position: fixed !important; 
 +top: 10px !important; 
 +right: 10px !important; 
 +z-index: 100002 !important;
 } }
  
Zeile 739: Zeile 756:
 </style> </style>
 <div id="ut-app"> <div id="ut-app">
 +  <!-- Vollbild-Button: schwebt auf allen Screens --> 
 +  <button class="ut-fsbtn" id="ut-fsbtn" onclick="utToggleFS()" title="Vollbild">⛶</button>
   <!-- ══ SETUP ══ -->   <!-- ══ SETUP ══ -->
- 
   <div id="ut-setup">   <div id="ut-setup">
     <div class="ut-hdr">     <div class="ut-hdr">
Zeile 747: Zeile 764:
       <p>Konfiguration der Stunde</p>       <p>Konfiguration der Stunde</p>
     </div>     </div>
- +    <div class="ut-grid"> 
-``` +      <div class="ut-card"> 
-<div class="ut-grid"> +        <label>Startzeit</label> 
-  <div class="ut-card"> +        <select id="ut-sel-start"></select> 
-    <label>Startzeit</label> +      </div> 
-    <select id="ut-sel-start"></select> +      <div class="ut-card"> 
-  </div> +        <label>Stundendauer</label> 
- +        <select id="ut-sel-dur"> 
-  <div class="ut-card"> +          <option value="45" selected>45 Minuten</option> 
-    <label>Stundendauer</label> +          <option value="90">90 Minuten</option> 
-    <select id="ut-sel-dur"> +        </select> 
-      <option value="45" selected>45 Minuten</option> +      </div> 
-      <option value="90">90 Minuten</option> +      <div class="ut-card"> 
-    </select> +        <label>Erster aktiver Timer</label> 
-  </div> +        <div class="ut-tchoice"> 
- +          <button class="ut-tbtn green active" id="ut-btn-g" onclick="utSetFirst('green')">● Grün</button> 
-  <div class="ut-card"> +          <button class="ut-tbtn red"          id="ut-btn-r" onclick="utSetFirst('red')">● Rot</button
-    <label>Erster aktiver Timer</label> +        </div> 
-    <div class="ut-tchoice"> +      </div> 
-      <button class="ut-tbtn green active" id="ut-btn-g" onclick="utSetFirst('green')">● Grün</button> +      <div class="ut-card" style="grid-column:1/-1;flex-direction:row;align-items:center;gap:20px;padding:22px 22px 20px 22px;"> 
-      <button class="ut-tbtn red"          id="ut-btn-r" onclick="utSetFirst('red')">● Rot</button>+        <div style="flex-shrink:0;min-width:78px;text-align:center;"> 
 +          <div class="ut-goal-val" id="ut-goal-val">75%</div> 
 +          <div class="ut-goal-sub">Ziel Grün</div> 
 +        </div> 
 +        <div style="flex:1;display:flex;flex-direction:column;gap:8px;"> 
 +          <label class="ut-card-label">Ziel: Anteil grüner Timer-Zeit</label> 
 +          <input type="range" id="ut-slider" min="50" max="95" step="5" value="75" oninput="utGoal(this.value)"> 
 +          <div class="ut-rlabels"><span>50%</span><span>95%</span></div> 
 +        </div> 
 +      </div>
     </div>     </div>
-  </div> +    <div class="ut-btnrow"> 
- +      <button class="ut-start-btn" id="ut-sbtn" onclick="utConfirm()">Stunde konfigurieren &amp; warten</button
-  <div class="ut-card" style="grid-column:1/-1;flex-direction:row;align-items:center;gap:20px;padding:22px 22px 20px 22px;"> +      <button class="ut-now-btn"   id="ut-nbtn" onclick="utNow()" title="Sofort starten ohne Wartezeit">▶ Sofort starten</button>
-    <div style="flex-shrink:0;min-width:78px;text-align:center;"> +
-      <div class="ut-goal-val" id="ut-goal-val">75%</div+
-      <div class="ut-goal-sub">Ziel Grün</div>+
     </div>     </div>
-    <div style="flex:1;display:flex;flex-direction:column;gap:8px;"> +    <div class="ut-wait-note" id="ut-wnote"> 
-      <label class="ut-card-label">Ziel: Anteil grüner Timer-Zeit</label> +      Warte auf Startzeit: <span id="ut-wdisp">--:--</span> 
-      <input type="range" id="ut-slider" min="50" max="95" step="5" value="75" oninput="utGoal(this.value)"> +      &nbsp;·&nbsp; 
-      <div class="ut-rlabels"><span>50%</span><span>95%</span></div>+      <button onclick="utNow()">Sofort starten</button>
     </div>     </div>
   </div>   </div>
-</div> 
- 
-<div class="ut-btnrow"> 
-  <button class="ut-start-btn" id="ut-sbtn" onclick="utConfirm()">Stunde konfigurieren &amp; warten</button> 
-  <button class="ut-now-btn"   id="ut-nbtn" onclick="utNow()" title="Sofort starten ohne Wartezeit">▶ Sofort starten</button> 
-</div> 
-<div class="ut-wait-note" id="ut-wnote"> 
-  Warte auf Startzeit: <span id="ut-wdisp">--:--</span> 
-  &nbsp;·&nbsp; 
-  <button onclick="utNow()">Sofort starten</button> 
-</div> 
-``` 
- 
-  </div> 
- 
   <!-- ══ TIMER ══ -->   <!-- ══ TIMER ══ -->
- 
   <div id="ut-timer">   <div id="ut-timer">
     <div class="ut-topbar">     <div class="ut-topbar">
Zeile 808: Zeile 815:
         <div class="ut-chip gc"><span>Grün</span><span class="utv utv-pct" id="ut-gcur"><span class="utd utdd" id="utd-gp-h"> </span><span class="utd utdd" id="utd-gp-t">0</span><span class="utd utdd" id="utd-gp-o">0</span><span class="utdd utdpc">%</span></span></div>         <div class="ut-chip gc"><span>Grün</span><span class="utv utv-pct" id="ut-gcur"><span class="utd utdd" id="utd-gp-h"> </span><span class="utd utdd" id="utd-gp-t">0</span><span class="utd utdd" id="utd-gp-o">0</span><span class="utdd utdpc">%</span></span></div>
         <span class="ut-otbadge" id="ut-otbadge" style="display:none">Nachzeit</span>         <span class="ut-otbadge" id="ut-otbadge" style="display:none">Nachzeit</span>
-        <button class="ut-fsbtn" id="ut-fsbtn" onclick="utToggleFS()" title="Vollbild">⛶</button> 
       </div>       </div>
     </div>     </div>
- +    <div class="ut-area"> 
-``` +      <!-- GREEN --> 
-<div class="ut-area"> +      <div class="ut-panel" id="ut-pg"> 
-  <!-- GREEN --> +        <div class="ut-rwrap" onclick="utSwitch('green')"> 
-  <div class="ut-panel" id="ut-pg"> +          <svg id="ut-svg-g" viewBox="0 0 300 300" width="260" height="260"> 
-    <div class="ut-rwrap" onclick="utSwitch('green')"> +            <circle cx="150" cy="150" r="130" fill="rgba(255,255,255,0.75)"/> 
-      <svg id="ut-svg-g" viewBox="0 0 300 300" width="260" height="260"> +            <circle cx="150" cy="150" r="130" fill="none" stroke="#dcfce7" stroke-width="15"/> 
-        <circle cx="150" cy="150" r="130" fill="rgba(255,255,255,0.75)"/> +            <circle id="ut-prog-g" cx="150" cy="150" r="130" fill="none" 
-        <circle cx="150" cy="150" r="130" fill="none" stroke="#dcfce7" stroke-width="15"/> +              stroke="#22c55e" stroke-width="15" stroke-linecap="round" 
-        <circle id="ut-prog-g" cx="150" cy="150" r="130" fill="none" +              stroke-dasharray="816.8" stroke-dashoffset="816.8" 
-          stroke="#22c55e" stroke-width="15" stroke-linecap="round" +              transform="rotate(-90 150 150)"/> 
-          stroke-dasharray="816.8" stroke-dashoffset="816.8" +          </svg> 
-          transform="rotate(-90 150 150)"/> +          <div class="ut-rinner"> 
-      </svg> +            <div class="ut-rlbl" style="color:#16a34a">Grün</div> 
-      <div class="ut-rinner"> +            <div class="ut-rtime" id="ut-tg" style="color:#16a34a"><span class="utrt" id="utrt-g0">0</span><span class="utrt" id="utrt-g1">0</span><span class="utrtc">:</span><span class="utrt" id="utrt-g2">0</span><span class="utrt" id="utrt-g3">0</span></div> 
-        <div class="ut-rlbl" style="color:#16a34a">Grün</div> +            <div class="ut-rstat" id="ut-sg" style="color:#16a34a">Aktiv</div> 
-        <div class="ut-rtime" id="ut-tg" style="color:#16a34a"><span class="utrt" id="utrt-g0">0</span><span class="utrt" id="utrt-g1">0</span><span class="utrtc">:</span><span class="utrt" id="utrt-g2">0</span><span class="utrt" id="utrt-g3">0</span></div> +          </div> 
-        <div class="ut-rstat" id="ut-sg" style="color:#16a34a">Aktiv</div>+        </div>
       </div>       </div>
-    </div> +      <div class="ut-divider"></div> 
-  </div> +      <!-- RED --> 
- +      <div class="ut-panel" id="ut-pr"> 
-  <div class="ut-divider"></div> +        <div class="ut-rwrap" onclick="utSwitch('red')"> 
- +          <svg id="ut-svg-r" viewBox="0 0 300 300" width="260" height="260"> 
-  <!-- RED --> +            <circle cx="150" cy="150" r="130" fill="rgba(255,255,255,0.75)"/> 
-  <div class="ut-panel" id="ut-pr"> +            <circle cx="150" cy="150" r="130" fill="none" stroke="#fee2e2" stroke-width="15"/> 
-    <div class="ut-rwrap" onclick="utSwitch('red')"> +            <circle id="ut-prog-r" cx="150" cy="150" r="130" fill="none" 
-      <svg id="ut-svg-r" viewBox="0 0 300 300" width="260" height="260"> +              stroke="#ef4444" stroke-width="15" stroke-linecap="round" 
-        <circle cx="150" cy="150" r="130" fill="rgba(255,255,255,0.75)"/> +              stroke-dasharray="816.8" stroke-dashoffset="816.8" 
-        <circle cx="150" cy="150" r="130" fill="none" stroke="#fee2e2" stroke-width="15"/> +              transform="rotate(-90 150 150)"/> 
-        <circle id="ut-prog-r" cx="150" cy="150" r="130" fill="none" +          </svg> 
-          stroke="#ef4444" stroke-width="15" stroke-linecap="round" +          <div class="ut-rinner"> 
-          stroke-dasharray="816.8" stroke-dashoffset="816.8" +            <div class="ut-rlbl" style="color:#dc2626">Rot</div> 
-          transform="rotate(-90 150 150)"/> +            <div class="ut-rtime" id="ut-tr" style="color:#dc2626"><span class="utrt" id="utrt-r0">0</span><span class="utrt" id="utrt-r1">0</span><span class="utrtc">:</span><span class="utrt" id="utrt-r2">0</span><span class="utrt" id="utrt-r3">0</span></div> 
-      </svg> +            <div class="ut-rstat" id="ut-sr" style="color:#dc2626">Pausiert</div> 
-      <div class="ut-rinner"> +          </div> 
-        <div class="ut-rlbl" style="color:#dc2626">Rot</div> +        </div>
-        <div class="ut-rtime" id="ut-tr" style="color:#dc2626"><span class="utrt" id="utrt-r0">0</span><span class="utrt" id="utrt-r1">0</span><span class="utrtc">:</span><span class="utrt" id="utrt-r2">0</span><span class="utrt" id="utrt-r3">0</span></div> +
-        <div class="ut-rstat" id="ut-sr" style="color:#dc2626">Pausiert</div>+
       </div>       </div>
     </div>     </div>
   </div>   </div>
-</div> 
-``` 
- 
-  </div> 
- 
   <!-- ══ RESULT ══ -->   <!-- ══ RESULT ══ -->
- 
   <div id="ut-result">   <div id="ut-result">
     <div class="ut-rcard">     <div class="ut-rcard">
Zeile 884: Zeile 882:
     </div>     </div>
   </div>   </div>
- 
 </div><!-- #ut-app --> </div><!-- #ut-app -->
- 
 <script> <script>
 (function(){ (function(){
 'use strict'; 'use strict';
  
-var cfg = { startH:7, startM:0, duration:45, first:'green', goal:75 }; +var cfg = { startH:7, startM:0, duration:45, first:green, goal:75 }; 
-var st  = { phase:'idle', active:'green', gMs:0, rMs:0, last:null, +var st  = { phase:idle, active:green, gMs:0, rMs:0, last:null, 
-            total:0, limit:0, wIv:null, tIv:null, cIv:null };+total:0, limit:0, wIv:null, tIv:null, cIv:null };
  
 /* ── helpers ── */ /* ── helpers ── */
-function pad(n){ return String(n).padStart(2,'0'); }+function pad(n){ return String(n).padStart(2,0); }
 function berlin(){ function berlin(){
-  var d=new Date(), b=new Date(d.toLocaleString('en-US',{timeZone:'Europe/Berlin'})); +var d=new Date(), b=new Date(d.toLocaleString(en-US,{timeZone:Europe/Berlin})); 
-  return {h:b.getHours(),m:b.getMinutes(),s:b.getSeconds(),date:b};+return {h:b.getHours(),m:b.getMinutes(),s:b.getSeconds(),date:b};
 } }
 function mmss(ms){ function mmss(ms){
-  var s=Math.floor(ms/1000), m=Math.floor(s/60); +var s=Math.floor(ms/1000), m=Math.floor(s/60); 
-  return pad(m)+':'+pad(s%60);+return pad(m)+:+pad(s%60);
 } }
 function el(id){ return document.getElementById(id); } function el(id){ return document.getElementById(id); }
Zeile 909: Zeile 905:
 /* ── Init ── */ /* ── Init ── */
 function init(){ function init(){
-  var sel=el('ut-sel-start'); +var sel=el(ut-sel-start); 
-  for(var h=7;h<=17;h++){ +for(var h=7;h<=17;h++){ 
-    for(var m=0;m<60;m+=5){ +for(var m=0;m<60;m+=5){ 
-      if(h===17&&m>0) break; +if(h===17&&m>0) break; 
-      var o=document.createElement('option'); +var o=document.createElement(option); 
-      o.value=h+':'+m; +o.value=h+:+m; 
-      o.textContent=pad(h)+':'+pad(m)+Uhr'+o.textContent=pad(h)+:+pad(m)+’ Uhr
-      sel.appendChild(o); +sel.appendChild(o); 
-    +
-  +
-  var now=berlin(), bh=now.h, bm=Math.ceil((now.m+1)/5)*5; +var now=berlin(), bh=now.h, bm=Math.ceil((now.m+1)/5)*5; 
-  if(bm>=60){bm=0;bh++;+if(bm>=60){bm=0;bh++;
-  if(bh>17){bh=17;bm=0;+if(bh>17){bh=17;bm=0;
-  sel.value=bh+':'+bm; +sel.value=bh+:+bm; 
-  startClock();+startClock();
 } }
  
 function startClock(){ function startClock(){
-  function tick(){ +function tick(){ 
-    var b=berlin(); +var b=berlin(); 
-    var hh=pad(b.h), mm=pad(b.m), ss=pad(b.s); +var hh=pad(b.h), mm=pad(b.m), ss=pad(b.s); 
-    el('utd-ch0').textContent=hh[0]; el('utd-ch1').textContent=hh[1]; +el(utd-ch0).textContent=hh[0]; el(utd-ch1).textContent=hh[1]; 
-    el('utd-cm0').textContent=mm[0]; el('utd-cm1').textContent=mm[1]; +el(utd-cm0).textContent=mm[0]; el(utd-cm1).textContent=mm[1]; 
-    el('utd-cs0').textContent=ss[0]; el('utd-cs1').textContent=ss[1]; +el(utd-cs0).textContent=ss[0]; el(utd-cs1).textContent=ss[1]; 
-  +
-  tick(); +tick(); 
-  st.cIv=setInterval(tick,500);+st.cIv=setInterval(tick,500);
 } }
  
 /* ── Setup callbacks ── */ /* ── Setup callbacks ── */
 window.utSetFirst=function(w){ window.utSetFirst=function(w){
-  cfg.first=w; +cfg.first=w; 
-  el('ut-btn-g').classList.toggle('active',w==='green'); +el(ut-btn-g).classList.toggle(active,w===green); 
-  el('ut-btn-r').classList.toggle('active',w==='red');+el(ut-btn-r).classList.toggle(active,w===red);
 }; };
 window.utGoal=function(v){ window.utGoal=function(v){
-  cfg.goal=parseInt(v); +cfg.goal=parseInt(v); 
-  el('ut-goal-val').textContent=v+'%'+el(ut-goal-val).textContent=v+%
-  el('ut-slider').value=v;+el(ut-slider).value=v;
 }; };
 function applyCfg(){ function applyCfg(){
-  var p=el('ut-sel-start').value.split(':').map(Number); +var p=el(ut-sel-start).value.split(:).map(Number); 
-  cfg.startH=p[0]; cfg.startM=p[1]; +cfg.startH=p[0]; cfg.startM=p[1]; 
-  cfg.duration=parseInt(el('ut-sel-dur').value); +cfg.duration=parseInt(el(ut-sel-dur).value); 
-  st.limit=cfg.duration*60*1000;+st.limit=cfg.duration*60*1000;
 } }
 window.utConfirm=function(){ window.utConfirm=function(){
-  applyCfg(); +applyCfg(); 
-  el('ut-sbtn').disabled=true; +el(ut-sbtn).disabled=true; 
-  el('ut-nbtn').disabled=true; +el(ut-nbtn).disabled=true; 
-  el('ut-sbtn').textContent='Warte auf Startzeit…'+el(ut-sbtn).textContent=Warte auf Startzeit…
-  el('ut-wnote').classList.add('show'); +el(ut-wnote).classList.add(show); 
-  updWait(); +updWait(); 
-  st.wIv=setInterval(function(){ +st.wIv=setInterval(function(){ 
-    updWait(); +updWait(); 
-    var n=berlin(); +var n=berlin(); 
-    if(n.h===cfg.startH&&n.m===cfg.startM&&n.s<3){ +if(n.h===cfg.startH&&n.m===cfg.startM&&n.s<3){ 
-      clearInterval(st.wIv); begin(); +clearInterval(st.wIv); begin(); 
-    +
-  },500);+},500);
 }; };
 window.utNow=function(){ window.utNow=function(){
-  clearInterval(st.wIv); +clearInterval(st.wIv); 
-  applyCfg(); +applyCfg(); 
-  begin();+begin();
 }; };
-function updWait(){ el('ut-wdisp').textContent=pad(cfg.startH)+':'+pad(cfg.startM); }+function updWait(){ el(ut-wdisp).textContent=pad(cfg.startH)+:+pad(cfg.startM); }
  
 /* ── Begin ── */ /* ── Begin ── */
 function begin(){ function begin(){
-  st.phase='running'; st.active=cfg.first; +st.phase=running; st.active=cfg.first; 
-  st.gMs=0; st.rMs=0; st.total=0; +st.gMs=0; st.rMs=0; st.total=0; 
-  st.last=Date.now(); +st.last=Date.now(); 
-  el('ut-gtop').textContent=cfg.goal+'%'+el(ut-gtop).textContent=cfg.goal+%
-  // Verbleibend korrekt initialisieren über Digit-Spans (nicht textContent!) +// Verbleibend korrekt initialisieren über Digit-Spans (nicht textContent!) 
-  setMmss('utd-rem-0','utd-rem-1','utd-rem-2','utd-rem-3', st.limit); +setMmss(utd-rem-0,utd-rem-1,utd-rem-2,utd-rem-3, st.limit); 
-  el('ut-setup').style.display='none'+el(ut-setup).style.display=none
-  el('ut-timer').style.display='flex'+el(ut-timer).style.display=flex
-  panels(); resize(); +panels(); resize(); 
-  st.tIv=setInterval(tick,100);+st.tIv=setInterval(tick,100);
 } }
  
 /* ── Tick ── */ /* ── Tick ── */
 function tick(){ function tick(){
-  if(st.phase==='done') return; +if(st.phase===done) return; 
-  var now=Date.now(), d=now-st.last; st.last=now; +var now=Date.now(), d=now-st.last; st.last=now; 
-  if(st.active==='green') st.gMs+=d; else st.rMs+=d; +if(st.active===green) st.gMs+=d; else st.rMs+=d; 
-  st.total=st.gMs+st.rMs; +st.total=st.gMs+st.rMs; 
-  if(st.phase==='running'&&st.total>=st.limit){ +if(st.phase===running&&st.total>=st.limit){ 
-    if(st.active==='green'){ end(); return; } +if(st.active===green){ end(); return; } 
-    else{ st.phase='overtime'; el('ut-otbadge').style.display='inline-flex'; } +else{ st.phase=overtime; el(ut-otbadge).style.display=inline-flex; } 
-  +
-  render();+render();
 } }
  
 /* ── Switch ── */ /* ── Switch ── */
 window.utSwitch=function(w){ window.utSwitch=function(w){
-  if(st.phase==='done'||st.phase==='idle') return; +if(st.phase===done||st.phase===idle) return; 
-  if(st.phase==='overtime'&&w==='green'){ +if(st.phase===overtime&&w===green){ 
-    var now=Date.now(),d=now-st.last; st.last=now; +var now=Date.now(),d=now-st.last; st.last=now; 
-    if(st.active==='red') st.rMs+=d; else st.gMs+=d; +if(st.active===red) st.rMs+=d; else st.gMs+=d; 
-    st.total=st.gMs+st.rMs; +st.total=st.gMs+st.rMs; 
-    end(); return; +end(); return; 
-  +
-  if(st.active===w) return; +if(st.active===w) return; 
-  st.active=w; st.last=Date.now(); +st.active=w; st.last=Date.now(); 
-  panels(); render();+panels(); render();
 }; };
  
 /* ── Digit helpers ── */ /* ── Digit helpers ── */
 function setMmss(d0, d1, d2, d3, ms){ function setMmss(d0, d1, d2, d3, ms){
-  var s=Math.floor(ms/1000), m=Math.floor(s/60); +var s=Math.floor(ms/1000), m=Math.floor(s/60); 
-  var mm=pad(m), ss=pad(s%60); +var mm=pad(m), ss=pad(s%60); 
-  el(d0).textContent=mm[0]; +el(d0).textContent=mm[0]; 
-  el(d1).textContent=mm[1]; +el(d1).textContent=mm[1]; 
-  el(d2).textContent=ss[0]; +el(d2).textContent=ss[0]; 
-  el(d3).textContent=ss[1];+el(d3).textContent=ss[1];
 } }
 function setGreenPct(gp){ function setGreenPct(gp){
-  // Hunderter: '1bei 100, sonst geschütztes Leerzeichen +// Hunderter: 1’ bei 100, sonst geschütztes Leerzeichen 
-  el('utd-gp-h').textContent = gp === 100 ? '1'\u2007'+el(utd-gp-h).textContent = gp === 100 ? 1’ \u2007
-  // Zehner: Ziffer wenn >= 10, sonst Leerzeichen +// Zehner: Ziffer wenn >= 10, sonst Leerzeichen 
-  el('utd-gp-t').textContent = gp >= 10 ? String(Math.floor(gp / 10) % 10) : '\u2007'+el(utd-gp-t).textContent = gp >= 10 ? String(Math.floor(gp / 10) % 10) : \u2007
-  // Einer: immer eine Ziffer +// Einer: immer eine Ziffer 
-  el('utd-gp-o').textContent = String(gp % 10);+el(utd-gp-o).textContent = String(gp % 10);
 } }
  
 /* ── Render ── */ /* ── Render ── */
 function render(){ function render(){
-  // Ring-Timer: digit-by-digit +// Ring-Timer: digit-by-digit 
-  setMmss('utrt-g0','utrt-g1','utrt-g2','utrt-g3', st.gMs); +setMmss(utrt-g0,utrt-g1,utrt-g2,utrt-g3, st.gMs); 
-  setMmss('utrt-r0','utrt-r1','utrt-r2','utrt-r3', st.rMs);+setMmss(utrt-r0,utrt-r1,utrt-r2,utrt-r3, st.rMs);
  
-  setMmss('utd-total-0','utd-total-1','utd-total-2','utd-total-3', st.total); +setMmss(utd-total-0,utd-total-1,utd-total-2,utd-total-3, st.total); 
-  setMmss('utd-rem-0',  'utd-rem-1',  'utd-rem-2',  'utd-rem-3',  Math.max(0,st.limit-st.total));+setMmss(utd-rem-0,  utd-rem-1,  utd-rem-2,  utd-rem-3,  Math.max(0,st.limit-st.total));
  
-  var gp=st.total>0?Math.round(st.gMs/st.total*100):0; +var gp=st.total>0?Math.round(st.gMs/st.total*100):0; 
-  setGreenPct(gp);+setGreenPct(gp);
  
-  if(st.limit>0){ +if(st.limit>0){ 
-    var C=816.8; +var C=816.8; 
-    el('ut-prog-g').style.strokeDashoffset=Math.max(0,C-(st.gMs/st.limit)*C); +el(ut-prog-g).style.strokeDashoffset=Math.max(0,C-(st.gMs/st.limit)*C); 
-    el('ut-prog-r').style.strokeDashoffset=Math.max(0,C-(st.rMs/st.limit)*C); +el(ut-prog-r).style.strokeDashoffset=Math.max(0,C-(st.rMs/st.limit)*C); 
-  }+}
 } }
 function panels(){ function panels(){
-  el('ut-pg').className='ut-panel'+(st.active==='green'?ag':''); +el(ut-pg).className=ut-panel+(st.active===green?’ ag:’’); 
-  el('ut-pr').className='ut-panel'+(st.active==='red'?ar':''); +el(ut-pr).className=ut-panel+(st.active===red?’ ar:’’); 
-  el('ut-sg').textContent=st.active==='green'?'Läuft':'Pausiert'+el(ut-sg).textContent=st.active===green?Läuft:Pausiert
-  el('ut-sr').textContent=st.active==='red'?'Läuft':'Pausiert';+el(ut-sr).textContent=st.active===red?Läuft:Pausiert;
 } }
  
 /* ── End ── */ /* ── End ── */
 function end(){ function end(){
-  st.phase='done'; clearInterval(st.tIv); render(); +st.phase=done; clearInterval(st.tIv); render(); 
-  var tot=st.total, gp=tot>0?Math.round(st.gMs/tot*100):0, rp=100-gp, ok=gp>=cfg.goal; +var tot=st.total, gp=tot>0?Math.round(st.gMs/tot*100):0, rp=100-gp, ok=gp>=cfg.goal; 
-  setTimeout(function(){ +setTimeout(function(){ 
-    var gm=(st.gMs/60000).toFixed(1), rm=(st.rMs/60000).toFixed(1); +var gm=(st.gMs/60000).toFixed(1), rm=(st.rMs/60000).toFixed(1); 
-    el('ut-rtitle').textContent=ok?'✓ Ziel erreicht!':'✗ Ziel nicht erreicht'+el(ut-rtitle).textContent=ok?✓ Ziel erreicht!:✗ Ziel nicht erreicht
-    el('ut-rtitle').className='ut-rtitle '+(ok?'ok':'no'); +el(ut-rtitle).className=ut-rtitle +(ok?ok:no); 
-    el('ut-pg-pct').textContent=gp+'%'; el('ut-pr-pct').textContent=rp+'%'+el(ut-pg-pct).textContent=gp+%; el(ut-pr-pct).textContent=rp+%
-    el('ut-ag').textContent=gm+min';  el('ut-ar').textContent=rm+min'+el(ut-ag).textContent=gm+’ min;  el(ut-ar).textContent=rm+’ min
-    el('ut-rgoal').innerHTML='Ziel: <strong>'+cfg.goal+'% grüne Zeit</strong> &nbsp;·&nbsp; Ergebnis: <strong>'+gp+'% grün</strong> / <strong>'+rp+'% rot</strong>'+el(ut-rgoal).innerHTML=Ziel: <strong>+cfg.goal+% grüne Zeit</strong>  ·  Ergebnis: <strong>+gp+% grün</strong> / <strong>+rp+% rot</strong>
-    el('ut-result').style.display='flex'+el(ut-result).style.display=flex
-    setTimeout(function(){ el('ut-bg').style.width=gp+'%'; el('ut-br').style.width=rp+'%'; },80); +setTimeout(function(){ el(ut-bg).style.width=gp+%; el(ut-br).style.width=rp+%; },80); 
-  },350);+},350);
 } }
  
 /* ── Reset ── */ /* ── Reset ── */
 window.utReset=function(){ window.utReset=function(){
-  // Vollbild beenden falls aktiv +var app=document.getElementById(ut-app’); 
-  var timer=el('ut-timer'); +if(app.classList.contains(ut-fs-float)){ 
-  if(timer.classList.contains('ut-fs-float')){ +app.classList.remove(ut-fs-float); 
-    timer.classList.remove('ut-fs-float'); +el(ut-fsbtn).classList.remove(ut-fs-on); 
-    el('ut-fsbtn').classList.remove('ut-fs-on'); +document.body.classList.remove(ut-fs-active); 
-    document.body.classList.remove('ut-fs-active'); +document.body.style.top=’’
-    document.body.style.top=''+window.scrollTo(0,_fsScrollY||0); 
-    window.scrollTo(0,_fsScrollY||0); +var btn=el(ut-fsbtn); 
-    var btn=el('ut-fsbtn'); +if(btn){ btn.textContent=; btn.title=Vollbild; } 
-    if(btn){ btn.textContent=''; btn.title='Vollbild'; } +
-  +clearInterval(st.tIv); clearInterval(st.wIv); 
-  clearInterval(st.tIv); clearInterval(st.wIv); +st={phase:idle,active:green,gMs:0,rMs:0,last:null,total:0,limit:0,wIv:null,tIv:null,cIv:st.cIv}; 
-  st={phase:'idle',active:'green',gMs:0,rMs:0,last:null,total:0,limit:0,wIv:null,tIv:null,cIv:st.cIv}; +el(ut-result).style.display=none
-  el('ut-result').style.display='none'+el(ut-timer).style.display=none
-  el('ut-timer').style.display='none'+el(ut-setup).style.display=flex
-  el('ut-setup').style.display='flex'+el(ut-sbtn).disabled=false; el(ut-nbtn).disabled=false; 
-  el('ut-sbtn').disabled=false; el('ut-nbtn').disabled=false; +el(ut-sbtn).textContent=Stunde konfigurieren & warten
-  el('ut-sbtn').textContent='Stunde konfigurieren & warten'+el(ut-wnote).classList.remove(show); 
-  el('ut-wnote').classList.remove('show'); +el(ut-otbadge).style.display=none
-  el('ut-otbadge').style.display='none'+el(ut-prog-g).style.strokeDashoffset=816.8; 
-  el('ut-prog-g').style.strokeDashoffset=816.8; +el(ut-prog-r).style.strokeDashoffset=816.8;
-  el('ut-prog-r').style.strokeDashoffset=816.8;+
 }; };
  
Zeile 1106: Zeile 1101:
 var _fsScrollY = 0; var _fsScrollY = 0;
 window.utToggleFS = function(){ window.utToggleFS = function(){
-  var timer el('ut-timer'); +var app  document.getElementById(ut-app’); 
-  var btn   = el('ut-fsbtn'); +var btn  = el(ut-fsbtn); 
-  var isFS  timer.classList.contains('ut-fs-float');+var isFS = app.classList.contains(ut-fs-float);
  
-  if(!isFS){ +if(!isFS){ 
-    // Vollbild AN +_fsScrollY = window.scrollY; 
-    _fsScrollY = window.scrollY; +app.classList.add(ut-fs-float); 
-    timer.classList.add('ut-fs-float'); +btn.classList.add(ut-fs-on); 
-    btn.classList.add('ut-fs-on'); +document.body.classList.add(ut-fs-active); 
-    document.body.classList.add('ut-fs-active'); +document.body.style.top = -’ + _fsScrollY + px
-    document.body.style.top = '-+ _fsScrollY + 'px'+btn.textContent = 
-    btn.textContent = ''+btn.title = Vollbild beenden
-    btn.title = 'Vollbild beenden'+} else { 
-  } else { +app.classList.remove(ut-fs-float); 
-    // Vollbild AUS +btn.classList.remove(ut-fs-on); 
-    timer.classList.remove('ut-fs-float'); +document.body.classList.remove(ut-fs-active); 
-    btn.classList.remove('ut-fs-on'); +document.body.style.top = ‘’
-    document.body.classList.remove('ut-fs-active'); +window.scrollTo(0, _fsScrollY); 
-    document.body.style.top = ''+btn.textContent = 
-    window.scrollTo(0, _fsScrollY); +btn.title = Vollbild
-    btn.textContent = ''+
-    btn.title = 'Vollbild'+setTimeout(resize, 50); 
-  +setTimeout(resize, 350);
-  setTimeout(resize, 50); +
-  setTimeout(resize, 350);+
 }; };
  
-// Escape-Taste und Orientierungswechsel +document.addEventListener(keydown, function(e){ 
-document.addEventListener('keydown', function(e){ +if(e.key === Escape’ && document.getElementById(ut-app’).classList.contains(ut-fs-float)){ 
-  if(e.key === 'Escape&& el('ut-timer').classList.contains('ut-fs-float')){ +utToggleFS(); 
-    utToggleFS(); +}
-  }+
 }); });
-window.addEventListener('orientationchange', function(){ +window.addEventListener(orientationchange, function(){ 
-  setTimeout(resize, 100); +setTimeout(resize, 100); 
-  setTimeout(resize, 400);+setTimeout(resize, 400);
 }); });
 function resize(){ function resize(){
-  var app=document.getElementById('ut-app'); +var app=document.getElementById(ut-app); 
-  var isFS = el('ut-timer') && el('ut-timer').classList.contains('ut-fs-float'); +var isFS = document.getElementById(ut-app’) && document.getElementById(ut-app’).classList.contains(ut-fs-float); 
-  var w = isFS ? window.innerWidth  : (app ? app.offsetWidth : window.innerWidth);+var w = isFS ? window.innerWidth  : (app ? app.offsetWidth : window.innerWidth);
  
-  // Breakpoints basierend auf tatsächlicher Container-Breite setzen +// Breakpoints basierend auf tatsächlicher Container-Breite setzen 
-  if(app){ +if(app){ 
-    app.classList.toggle('ut-sm', w < 700); +app.classList.toggle(ut-sm, w < 700); 
-    app.classList.toggle('ut-xs', w < 480); +app.classList.toggle(ut-xs, w < 480); 
-  }+}
  
-  var area=document.querySelector('#ut-app .ut-area'); +var area=document.querySelector(#ut-app .ut-area); 
-  if(!area) return;+if(!area) return;
  
-  // Im Vollbild: Fenstergröße nutzen. Sonst: tatsächliche Element-Größe. +// Im Vollbild: Fenstergröße nutzen. Sonst: tatsächliche Element-Größe. 
-  var topbarH = 0; +var topbarH = 0; 
-  var tb = document.querySelector('#ut-app .ut-topbar'); +var tb = document.querySelector(#ut-app .ut-topbar); 
-  if(tb) topbarH = tb.offsetHeight || 50;+if(tb) topbarH = tb.offsetHeight || 50;
  
-  var areaH = isFS +var areaH = isFS 
-    ? (window.innerHeight - topbarH - 10) +? (window.innerHeight - topbarH - 10) 
-    : (area.clientHeight > 20 ? area.clientHeight : window.innerHeight - topbarH - 60); +: (area.clientHeight > 20 ? area.clientHeight : window.innerHeight - topbarH - 60); 
-  var areaW = isFS ? window.innerWidth : (area.clientWidth > 0 ? area.clientWidth : w);+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 sz = Math.max(100, Math.min(areaH - 10, areaW / 2 - 30, 340)); 
-  ['ut-svg-g','ut-svg-r'].forEach(function(id){ +[ut-svg-g,ut-svg-r].forEach(function(id){ 
-    var s=el(id); if(s){s.style.width=sz+'px';s.style.height=sz+'px';} +var s=el(id); if(s){s.style.width=sz+px;s.style.height=sz+px;} 
-  }); +}); 
-  var fs=Math.max(20, sz*0.205); +var fs=Math.max(20, sz*0.205); 
-  document.querySelectorAll('#ut-app .ut-rtime').forEach(function(e){e.style.fontSize=fs+'px';});+document.querySelectorAll(#ut-app .ut-rtime).forEach(function(e){e.style.fontSize=fs+px;});
 } }
-window.addEventListener('resize',resize);+window.addEventListener(resize,resize);
 // Auch beim Laden direkt auswerten // Auch beim Laden direkt auswerten
-document.addEventListener('DOMContentLoaded', resize);+document.addEventListener(DOMContentLoaded, resize);
  
 init(); init();
Zeile 1375: Zeile 1367:
 /* ── Reset ── */ /* ── Reset ── */
 window.utReset=function(){ window.utReset=function(){
-  // Vollbild beenden falls aktiv +  var app=document.getElementById('ut-app'); 
-  var timer=el('ut-timer'); +  if(app.classList.contains('ut-fs-float')){ 
-  if(timer.classList.contains('ut-fs-float')){ +    app.classList.remove('ut-fs-float');
-    timer.classList.remove('ut-fs-float');+
     el('ut-fsbtn').classList.remove('ut-fs-on');     el('ut-fsbtn').classList.remove('ut-fs-on');
     document.body.classList.remove('ut-fs-active');     document.body.classList.remove('ut-fs-active');
Zeile 1402: Zeile 1393:
 var _fsScrollY = 0; var _fsScrollY = 0;
 window.utToggleFS = function(){ window.utToggleFS = function(){
-  var timer el('ut-timer'); +  var app  document.getElementById('ut-app'); 
-  var btn   = el('ut-fsbtn'); +  var btn  = el('ut-fsbtn'); 
-  var isFS  timer.classList.contains('ut-fs-float');+  var isFS = app.classList.contains('ut-fs-float');
  
   if(!isFS){   if(!isFS){
-    // Vollbild AN 
     _fsScrollY = window.scrollY;     _fsScrollY = window.scrollY;
-    timer.classList.add('ut-fs-float');+    app.classList.add('ut-fs-float');
     btn.classList.add('ut-fs-on');     btn.classList.add('ut-fs-on');
     document.body.classList.add('ut-fs-active');     document.body.classList.add('ut-fs-active');
Zeile 1416: Zeile 1406:
     btn.title = 'Vollbild beenden';     btn.title = 'Vollbild beenden';
   } else {   } else {
-    // Vollbild AUS +    app.classList.remove('ut-fs-float');
-    timer.classList.remove('ut-fs-float');+
     btn.classList.remove('ut-fs-on');     btn.classList.remove('ut-fs-on');
     document.body.classList.remove('ut-fs-active');     document.body.classList.remove('ut-fs-active');
Zeile 1429: Zeile 1418:
 }; };
  
-// Escape-Taste und Orientierungswechsel 
 document.addEventListener('keydown', function(e){ document.addEventListener('keydown', function(e){
-  if(e.key === 'Escape' && el('ut-timer').classList.contains('ut-fs-float')){+  if(e.key === 'Escape' && document.getElementById('ut-app').classList.contains('ut-fs-float')){
     utToggleFS();     utToggleFS();
   }   }
Zeile 1441: Zeile 1429:
 function resize(){ function resize(){
   var app=document.getElementById('ut-app');   var app=document.getElementById('ut-app');
-  var isFS = el('ut-timer') && el('ut-timer').classList.contains('ut-fs-float');+  var isFS = document.getElementById('ut-app') && document.getElementById('ut-app').classList.contains('ut-fs-float');
   var w = isFS ? window.innerWidth  : (app ? app.offsetWidth : window.innerWidth);   var w = isFS ? window.innerWidth  : (app ? app.offsetWidth : window.innerWidth);
  
tools/ur-timer.1773326614.txt.gz · Zuletzt geändert: von Eric Weber