Liveloop

An interactive timeline for social media. Every post is a tiny app you can play, save, and remix.

Product

  • Feed
  • Create
  • Claude Code plugin
  • Blog

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA

Project

  • Templates
© 2026 Liveloop. All rights reserved.
LiveloopVersion history

v1Current

@ko_studio · 6/20/2026, 2:44:04 AM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;overflow:hidden;background:#0a1730;}
+ *{box-sizing:border-box;}
+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(130% 80% at 50% 0%,#15295a 0%,#0e1d40 55%,#0a1730 100%);color:#fff;-webkit-tap-highlight-color:transparent;touch-action:manipulation;-webkit-user-select:none;user-select:none;}
+ #head{padding:1.05rem 1.2rem .35rem;}
+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.1rem;line-height:1;}
+ #head p{margin:.22rem 0 0;font-size:.78rem;color:#9fb4e6;font-weight:600;}
+ #list{flex:1;min-height:0;overflow-y:auto;padding:.55rem 1rem 1.2rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:11px;}
+ .match{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:16px;padding:.8rem .9rem;}
+ .stage{font-size:.62rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#7e93c8;margin-bottom:.55rem;}
+ .trow{display:flex;align-items:center;gap:.55rem;padding:.18rem 0;}
+ .trow .fl{font-size:1.5rem;line-height:1;}
+ .trow .tn{font-size:1rem;font-weight:700;flex:1;}
+ .step{display:flex;align-items:center;gap:.3rem;}
+ .step button{width:30px;height:30px;border-radius:9px;border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.08);color:#fff;font-size:1.15rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;}
+ .step button:active{transform:scale(.92);}
+ .step .sc{min-width:26px;text-align:center;font-size:1.35rem;font-weight:900;font-variant-numeric:tabular-nums;}
+ .lock{margin-top:.7rem;width:100%;border:0;border-radius:11px;background:linear-gradient(135deg,#5b8bff,#7C5CFF);color:#fff;font-weight:800;font-size:.9rem;padding:.65rem;cursor:pointer;}
+ .lock:active{transform:scale(.98);}
+ .lock.done{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);}
+ .results{margin-top:.7rem;display:none;}
+ .results .rh{font-size:.66rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:#7e93c8;margin-bottom:.4rem;display:flex;justify-content:space-between;}
+ .bar{position:relative;height:26px;border-radius:7px;background:rgba(255,255,255,.07);margin-bottom:5px;overflow:hidden;}
+ .bar .fill{position:absolute;inset:0 auto 0 0;border-radius:7px;background:linear-gradient(90deg,#3a63d6,#6f5bff);transition:width .5s cubic-bezier(.2,.8,.3,1);}
+ .bar.you .fill{background:linear-gradient(90deg,#f7a83e,#ff7a59);}
+ .bar .lab{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between;padding:0 .6rem;font-size:.74rem;font-weight:800;z-index:1;}
+ .bar .lab .you{font-size:.6rem;background:rgba(0,0,0,.25);border-radius:5px;padding:1px 5px;margin-left:5px;}
+ .note{font-size:.68rem;color:#8aa0d6;font-weight:600;margin-top:.3rem;text-align:center;}
+</style>
+<div id="wrap">
+ <div id="head">
+ <h1>Predict the Score</h1>
+ <p>Call the result. See what everyone else predicts.</p>
+ </div>
+ <div id="list"></div>
+</div>
+<script>
+(function(){
+ var LL=window.liveloop||null;
+ var muted = LL ? LL.muted : true;
+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }
+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }
+ var _ac=null;
+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }
+ function blip(f,type,vol,dur){
+ if(muted) return; var c=actx(); if(!c) return;
+ var t=c.currentTime, o=c.createOscillator(), g=c.createGain();
+ o.type=type||'triangle'; o.frequency.setValueAtTime(f,t);
+ g.gain.setValueAtTime(0.0001,t); g.gain.exponentialRampToValueAtTime(vol||0.08,t+0.01);
+ g.gain.exponentialRampToValueAtTime(0.0001,t+(dur||0.12));
+ o.connect(g); g.connect(c.destination); o.start(t); o.stop(t+(dur||0.12)+0.03);
+ }
+ function lockSfx(){ blip(523.25,'triangle',0.1,0.12); setTimeout(function(){blip(783.99,'triangle',0.1,0.22);},90); }
+
+ var hasData=!!(LL && LL.data && LL.data.submit);
+ function esc(s){ return String(s).replace(/[&<>"]/g,function(c){ return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]; }); }
+ function validScore(s){ return /^d{1,2}-d{1,2}$/.test(s); }
+
+ // Curated marquee matchups (no fixed kickoff times — heavyweight pairings).
+ var MATCHES=[
+ {id:'m1',stage:'World Cup 2026',h:{f:'🇧🇷',n:'Brazil'}, a:{f:'🇦🇷',n:'Argentina'}},
+ {id:'m2',stage:'World Cup 2026',h:{f:'🇫🇷',n:'France'}, a:{f:'🇬🇧',n:'England'}},
+ {id:'m3',stage:'World Cup 2026',h:{f:'🇪🇸',n:'Spain'}, a:{f:'🇩🇪',n:'Germany'}},
+ {id:'m4',stage:'World Cup 2026',h:{f:'🇵🇹',n:'Portugal'}, a:{f:'🇳🇱',n:'Netherlands'}},
+ {id:'m5',stage:'Host derby', h:{f:'🇺🇸',n:'USA'}, a:{f:'🇲🇽',n:'Mexico'}},
+ {id:'m6',stage:'World Cup 2026',h:{f:'🇧🇷',n:'Brazil'}, a:{f:'🇫🇷',n:'France'}},
+ {id:'m7',stage:'World Cup 2026',h:{f:'🇦🇷',n:'Argentina'},a:{f:'🇪🇸',n:'Spain'}},
+ {id:'m8',stage:'World Cup 2026',h:{f:'🇳🇱',n:'Netherlands'},a:{f:'🇩🇪',n:'Germany'}}
+ ];
+ var ST={}; // per-match runtime state
+ MATCHES.forEach(function(m){ ST[m.id]={h:0,a:0,counts:{},mine:null,localPick:null,dirty:false}; });
+ function coll(id){ return 'wc26_'+id; }
+
+ var listEl=document.getElementById('list');
+
+ function card(m){
+ var d=document.createElement('div'); d.className='match'; d.id='c_'+m.id;
+ d.innerHTML=
+ '<div class="stage">'+m.stage+'</div>'+
+ '<div class="trow"><span class="fl">'+m.h.f+'</span><span class="tn">'+m.h.n+'</span>'+
+ '<div class="step"><button data-m="'+m.id+'" data-s="h" data-d="-1">−</button><span class="sc" id="sc_'+m.id+'_h">0</span><button data-m="'+m.id+'" data-s="h" data-d="1">+</button></div></div>'+
+ '<div class="trow"><span class="fl">'+m.a.f+'</span><span class="tn">'+m.a.n+'</span>'+
+ '<div class="step"><button data-m="'+m.id+'" data-s="a" data-d="-1">−</button><span class="sc" id="sc_'+m.id+'_a">0</span><button data-m="'+m.id+'" data-s="a" data-d="1">+</button></div></div>'+
+ '<button class="lock" id="lock_'+m.id+'">Lock it in</button>'+
+ '<div class="results" id="res_'+m.id+'"></div>';
+ listEl.appendChild(d);
+ document.getElementById('lock_'+m.id).addEventListener('pointerdown',function(e){ e.preventDefault(); lockIn(m.id); });
+ }
+ MATCHES.forEach(card);
+
+ // steppers (delegated)
+ listEl.addEventListener('pointerdown',function(e){
+ var b=e.target.closest && e.target.closest('.step button'); if(!b) return;
+ e.preventDefault();
+ var id=b.getAttribute('data-m'), s=b.getAttribute('data-s'), d=parseInt(b.getAttribute('data-d'),10);
+ var st=ST[id]; st[s]=Math.max(0,Math.min(9,st[s]+d)); st.dirty=true;
+ document.getElementById('sc_'+id+'_'+s).textContent=st[s];
+ blip(d>0?640:520,'sine',0.05,0.07);
+ refreshLockLabel(id);
+ });
+
+ function scoreStr(id){ return ST[id].h+'-'+ST[id].a; }
+ function refreshLockLabel(id){
+ var st=ST[id], btn=document.getElementById('lock_'+id);
+ if(st.mine!=null){ btn.classList.add('done'); btn.textContent = (scoreStr(id)===st.mine) ? ('Your call · '+st.mine) : ('Update pick · '+scoreStr(id)); }
+ else { btn.classList.remove('done'); btn.textContent='Lock it in'; }
+ }
+
+ function lockIn(id){
+ var st=ST[id], score=scoreStr(id);
+ st.mine=score; st.dirty=false; lockSfx(); refreshLockLabel(id);
+ if(!hasData){
+ if(st.localPick && st.counts[st.localPick]>0) st.counts[st.localPick]--; // move my vote, don't stack it
+ st.localPick=score; if(!st.counts[score]) st.counts[score]=0; st.counts[score]++; paintRes(id,true); return; }
+ // optimistic local bump
+ if(!st.counts[score]) st.counts[score]=0; st.counts[score]++;
+ paintRes(id,false);
+ try{ LL.data.submit(coll(id),{score:score},{mode:'keep_last'}).then(function(){ refreshMatch(id); }, function(){}); }catch(e){}
+ }
+
+ function paintRes(id,local){
+ var st=ST[id], res=document.getElementById('res_'+id);
+ var entries=[]; for(var k in st.counts){ if(st.counts[k]>0 && validScore(k)) entries.push({s:k,n:st.counts[k]}); }
+ entries.sort(function(a,b){ return b.n-a.n; });
+ var total=entries.reduce(function(t,e){ return t+e.n; },0);
+ if(total===0){ res.style.display='none'; return; }
+ res.style.display='block';
+ var top=entries.slice(0,4), html='<div class="rh"><span>Most predicted</span><span>'+total+' pick'+(total===1?'':'s')+'</span></div>';
+ top.forEach(function(e){
+ var pct=Math.round(e.n/total*100), you=(e.s===st.mine);
+ html+='<div class="bar'+(you?' you':'')+'"><div class="fill" style="width:'+pct+'%"></div>'+
+ '<div class="lab"><span>'+esc(e.s)+(you?'<span class="you">you</span>':'')+'</span><span>'+pct+'%</span></div></div>';
+ });
+ if(local) html+='<div class="note">live community results appear on the published loop</div>';
+ res.innerHTML=html;
+ }
+
+ function refreshMatch(id){
+ if(!hasData) return;
+ Promise.all([ LL.data.tally(coll(id),'score'), LL.data.mine(coll(id)) ]).then(function(r){
+ var counts=(r[0]&&r[0].counts)||{};
+ ST[id].counts=counts;
+ var mine=((r[1]&&r[1].records)||[])[0];
+ if(mine&&mine.data&&mine.data.score){
+ ST[id].mine=mine.data.score;
+ if(!ST[id].dirty){ // don't clobber an in-progress, unlocked stepper edit
+ var p=mine.data.score.split('-');
+ ST[id].h=Math.max(0,parseInt(p[0],10)||0); ST[id].a=Math.max(0,parseInt(p[1],10)||0);
+ document.getElementById('sc_'+id+'_h').textContent=ST[id].h;
+ document.getElementById('sc_'+id+'_a').textContent=ST[id].a;
+ }
+ refreshLockLabel(id);
+ }
+ paintRes(id,false);
+ }).catch(function(){});
+ }
+ function refreshAll(){ MATCHES.forEach(function(m){ refreshMatch(m.id); }); }
+
+ var timer=null;
+ function startPoll(){ if(!timer&&hasData) timer=setInterval(refreshAll,25000); }
+ function stopPoll(){ if(timer){ clearInterval(timer); timer=null; } }
+ if(LL && LL.onVisibility){ try{ LL.onVisibility(function(v){ if(v){ refreshAll(); startPoll(); } else stopPoll(); }); }catch(e){} }
+ document.addEventListener('visibilitychange',function(){ if(document.hidden) stopPoll(); else { refreshAll(); startPoll(); } });
+
+ if(hasData){ refreshAll(); startPoll(); }
+})();
+</script>

v1Current

@ko_studio · 6/20/2026, 2:44:04 AM

Initial version — all lines are new.

+<style>
+ html,body{height:100%;margin:0;overflow:hidden;background:#0a1730;}
+ *{box-sizing:border-box;}
+ #wrap{position:relative;height:100%;width:100%;display:flex;flex-direction:column;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(130% 80% at 50% 0%,#15295a 0%,#0e1d40 55%,#0a1730 100%);color:#fff;-webkit-tap-highlight-color:transparent;touch-action:manipulation;-webkit-user-select:none;user-select:none;}
+ #head{padding:1.05rem 1.2rem .35rem;}
+ #head h1{margin:0;font-family:"Instrument Serif",Georgia,"Times New Roman",serif;font-weight:400;font-size:2.1rem;line-height:1;}
+ #head p{margin:.22rem 0 0;font-size:.78rem;color:#9fb4e6;font-weight:600;}
+ #list{flex:1;min-height:0;overflow-y:auto;padding:.55rem 1rem 1.2rem;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:11px;}
+ .match{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.1);border-radius:16px;padding:.8rem .9rem;}
+ .stage{font-size:.62rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:#7e93c8;margin-bottom:.55rem;}
+ .trow{display:flex;align-items:center;gap:.55rem;padding:.18rem 0;}
+ .trow .fl{font-size:1.5rem;line-height:1;}
+ .trow .tn{font-size:1rem;font-weight:700;flex:1;}
+ .step{display:flex;align-items:center;gap:.3rem;}
+ .step button{width:30px;height:30px;border-radius:9px;border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.08);color:#fff;font-size:1.15rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;}
+ .step button:active{transform:scale(.92);}
+ .step .sc{min-width:26px;text-align:center;font-size:1.35rem;font-weight:900;font-variant-numeric:tabular-nums;}
+ .lock{margin-top:.7rem;width:100%;border:0;border-radius:11px;background:linear-gradient(135deg,#5b8bff,#7C5CFF);color:#fff;font-weight:800;font-size:.9rem;padding:.65rem;cursor:pointer;}
+ .lock:active{transform:scale(.98);}
+ .lock.done{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);}
+ .results{margin-top:.7rem;display:none;}
+ .results .rh{font-size:.66rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:#7e93c8;margin-bottom:.4rem;display:flex;justify-content:space-between;}
+ .bar{position:relative;height:26px;border-radius:7px;background:rgba(255,255,255,.07);margin-bottom:5px;overflow:hidden;}
+ .bar .fill{position:absolute;inset:0 auto 0 0;border-radius:7px;background:linear-gradient(90deg,#3a63d6,#6f5bff);transition:width .5s cubic-bezier(.2,.8,.3,1);}
+ .bar.you .fill{background:linear-gradient(90deg,#f7a83e,#ff7a59);}
+ .bar .lab{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between;padding:0 .6rem;font-size:.74rem;font-weight:800;z-index:1;}
+ .bar .lab .you{font-size:.6rem;background:rgba(0,0,0,.25);border-radius:5px;padding:1px 5px;margin-left:5px;}
+ .note{font-size:.68rem;color:#8aa0d6;font-weight:600;margin-top:.3rem;text-align:center;}
+</style>
+<div id="wrap">
+ <div id="head">
+ <h1>Predict the Score</h1>
+ <p>Call the result. See what everyone else predicts.</p>
+ </div>
+ <div id="list"></div>
+</div>
+<script>
+(function(){
+ var LL=window.liveloop||null;
+ var muted = LL ? LL.muted : true;
+ if(LL && LL.onMute){ try{ LL.onMute(function(m){ muted=m; }); }catch(e){} }
+ if(LL && LL.declareMedia){ try{ LL.declareMedia({sound:true}); }catch(e){} }
+ var _ac=null;
+ function actx(){ if(!_ac){ try{ _ac=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ _ac=null; } } return _ac; }
+ function blip(f,type,vol,dur){
+ if(muted) return; var c=actx(); if(!c) return;
+ var t=c.currentTime, o=c.createOscillator(), g=c.createGain();
+ o.type=type||'triangle'; o.frequency.setValueAtTime(f,t);
+ g.gain.setValueAtTime(0.0001,t); g.gain.exponentialRampToValueAtTime(vol||0.08,t+0.01);
+ g.gain.exponentialRampToValueAtTime(0.0001,t+(dur||0.12));
+ o.connect(g); g.connect(c.destination); o.start(t); o.stop(t+(dur||0.12)+0.03);
+ }
+ function lockSfx(){ blip(523.25,'triangle',0.1,0.12); setTimeout(function(){blip(783.99,'triangle',0.1,0.22);},90); }
+
+ var hasData=!!(LL && LL.data && LL.data.submit);
+ function esc(s){ return String(s).replace(/[&<>"]/g,function(c){ return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]; }); }
+ function validScore(s){ return /^d{1,2}-d{1,2}$/.test(s); }
+
+ // Curated marquee matchups (no fixed kickoff times — heavyweight pairings).
+ var MATCHES=[
+ {id:'m1',stage:'World Cup 2026',h:{f:'🇧🇷',n:'Brazil'}, a:{f:'🇦🇷',n:'Argentina'}},
+ {id:'m2',stage:'World Cup 2026',h:{f:'🇫🇷',n:'France'}, a:{f:'🇬🇧',n:'England'}},
+ {id:'m3',stage:'World Cup 2026',h:{f:'🇪🇸',n:'Spain'}, a:{f:'🇩🇪',n:'Germany'}},
+ {id:'m4',stage:'World Cup 2026',h:{f:'🇵🇹',n:'Portugal'}, a:{f:'🇳🇱',n:'Netherlands'}},
+ {id:'m5',stage:'Host derby', h:{f:'🇺🇸',n:'USA'}, a:{f:'🇲🇽',n:'Mexico'}},
+ {id:'m6',stage:'World Cup 2026',h:{f:'🇧🇷',n:'Brazil'}, a:{f:'🇫🇷',n:'France'}},
+ {id:'m7',stage:'World Cup 2026',h:{f:'🇦🇷',n:'Argentina'},a:{f:'🇪🇸',n:'Spain'}},
+ {id:'m8',stage:'World Cup 2026',h:{f:'🇳🇱',n:'Netherlands'},a:{f:'🇩🇪',n:'Germany'}}
+ ];
+ var ST={}; // per-match runtime state
+ MATCHES.forEach(function(m){ ST[m.id]={h:0,a:0,counts:{},mine:null,localPick:null,dirty:false}; });
+ function coll(id){ return 'wc26_'+id; }
+
+ var listEl=document.getElementById('list');
+
+ function card(m){
+ var d=document.createElement('div'); d.className='match'; d.id='c_'+m.id;
+ d.innerHTML=
+ '<div class="stage">'+m.stage+'</div>'+
+ '<div class="trow"><span class="fl">'+m.h.f+'</span><span class="tn">'+m.h.n+'</span>'+
+ '<div class="step"><button data-m="'+m.id+'" data-s="h" data-d="-1">−</button><span class="sc" id="sc_'+m.id+'_h">0</span><button data-m="'+m.id+'" data-s="h" data-d="1">+</button></div></div>'+
+ '<div class="trow"><span class="fl">'+m.a.f+'</span><span class="tn">'+m.a.n+'</span>'+
+ '<div class="step"><button data-m="'+m.id+'" data-s="a" data-d="-1">−</button><span class="sc" id="sc_'+m.id+'_a">0</span><button data-m="'+m.id+'" data-s="a" data-d="1">+</button></div></div>'+
+ '<button class="lock" id="lock_'+m.id+'">Lock it in</button>'+
+ '<div class="results" id="res_'+m.id+'"></div>';
+ listEl.appendChild(d);
+ document.getElementById('lock_'+m.id).addEventListener('pointerdown',function(e){ e.preventDefault(); lockIn(m.id); });
+ }
+ MATCHES.forEach(card);
+
+ // steppers (delegated)
+ listEl.addEventListener('pointerdown',function(e){
+ var b=e.target.closest && e.target.closest('.step button'); if(!b) return;
+ e.preventDefault();
+ var id=b.getAttribute('data-m'), s=b.getAttribute('data-s'), d=parseInt(b.getAttribute('data-d'),10);
+ var st=ST[id]; st[s]=Math.max(0,Math.min(9,st[s]+d)); st.dirty=true;
+ document.getElementById('sc_'+id+'_'+s).textContent=st[s];
+ blip(d>0?640:520,'sine',0.05,0.07);
+ refreshLockLabel(id);
+ });
+
+ function scoreStr(id){ return ST[id].h+'-'+ST[id].a; }
+ function refreshLockLabel(id){
+ var st=ST[id], btn=document.getElementById('lock_'+id);
+ if(st.mine!=null){ btn.classList.add('done'); btn.textContent = (scoreStr(id)===st.mine) ? ('Your call · '+st.mine) : ('Update pick · '+scoreStr(id)); }
+ else { btn.classList.remove('done'); btn.textContent='Lock it in'; }
+ }
+
+ function lockIn(id){
+ var st=ST[id], score=scoreStr(id);
+ st.mine=score; st.dirty=false; lockSfx(); refreshLockLabel(id);
+ if(!hasData){
+ if(st.localPick && st.counts[st.localPick]>0) st.counts[st.localPick]--; // move my vote, don't stack it
+ st.localPick=score; if(!st.counts[score]) st.counts[score]=0; st.counts[score]++; paintRes(id,true); return; }
+ // optimistic local bump
+ if(!st.counts[score]) st.counts[score]=0; st.counts[score]++;
+ paintRes(id,false);
+ try{ LL.data.submit(coll(id),{score:score},{mode:'keep_last'}).then(function(){ refreshMatch(id); }, function(){}); }catch(e){}
+ }
+
+ function paintRes(id,local){
+ var st=ST[id], res=document.getElementById('res_'+id);
+ var entries=[]; for(var k in st.counts){ if(st.counts[k]>0 && validScore(k)) entries.push({s:k,n:st.counts[k]}); }
+ entries.sort(function(a,b){ return b.n-a.n; });
+ var total=entries.reduce(function(t,e){ return t+e.n; },0);
+ if(total===0){ res.style.display='none'; return; }
+ res.style.display='block';
+ var top=entries.slice(0,4), html='<div class="rh"><span>Most predicted</span><span>'+total+' pick'+(total===1?'':'s')+'</span></div>';
+ top.forEach(function(e){
+ var pct=Math.round(e.n/total*100), you=(e.s===st.mine);
+ html+='<div class="bar'+(you?' you':'')+'"><div class="fill" style="width:'+pct+'%"></div>'+
+ '<div class="lab"><span>'+esc(e.s)+(you?'<span class="you">you</span>':'')+'</span><span>'+pct+'%</span></div></div>';
+ });
+ if(local) html+='<div class="note">live community results appear on the published loop</div>';
+ res.innerHTML=html;
+ }
+
+ function refreshMatch(id){
+ if(!hasData) return;
+ Promise.all([ LL.data.tally(coll(id),'score'), LL.data.mine(coll(id)) ]).then(function(r){
+ var counts=(r[0]&&r[0].counts)||{};
+ ST[id].counts=counts;
+ var mine=((r[1]&&r[1].records)||[])[0];
+ if(mine&&mine.data&&mine.data.score){
+ ST[id].mine=mine.data.score;
+ if(!ST[id].dirty){ // don't clobber an in-progress, unlocked stepper edit
+ var p=mine.data.score.split('-');
+ ST[id].h=Math.max(0,parseInt(p[0],10)||0); ST[id].a=Math.max(0,parseInt(p[1],10)||0);
+ document.getElementById('sc_'+id+'_h').textContent=ST[id].h;
+ document.getElementById('sc_'+id+'_a').textContent=ST[id].a;
+ }
+ refreshLockLabel(id);
+ }
+ paintRes(id,false);
+ }).catch(function(){});
+ }
+ function refreshAll(){ MATCHES.forEach(function(m){ refreshMatch(m.id); }); }
+
+ var timer=null;
+ function startPoll(){ if(!timer&&hasData) timer=setInterval(refreshAll,25000); }
+ function stopPoll(){ if(timer){ clearInterval(timer); timer=null; } }
+ if(LL && LL.onVisibility){ try{ LL.onVisibility(function(v){ if(v){ refreshAll(); startPoll(); } else stopPoll(); }); }catch(e){} }
+ document.addEventListener('visibilitychange',function(){ if(document.hidden) stopPoll(); else { refreshAll(); startPoll(); } });
+
+ if(hasData){ refreshAll(); startPoll(); }
+})();
+</script>
← Version history