Skip to content

Instantly share code, notes, and snippets.

@fcingolani
Last active June 30, 2026 01:13
Show Gist options
  • Select an option

  • Save fcingolani/fa3c0747f2a98418719907071258165d to your computer and use it in GitHub Desktop.

Select an option

Save fcingolani/fa3c0747f2a98418719907071258165d to your computer and use it in GitHub Desktop.
Reddit Live Comments Script

Reddit Live Comments

A browser console script that opens a live sidebar panel showing new comments on any Reddit post, auto-refreshing every 10 seconds — no extensions, no installs.


English

Requirements

  • A desktop browser with DevTools (Chrome, Firefox, Edge, Brave)
  • Any Reddit post URL containing /comments/

How to use

  1. Open the Reddit post you want to follow.
  2. Open the browser console: F12 → Console tab (or Ctrl+Shift+J on Windows/Linux, Cmd+Option+J on Mac).
  3. First time on Chrome only: type allow pasting and press Enter. This is a one-time security prompt.
  4. Copy the entire contents of reddit-live-comments.js and paste it into the console. Press Enter.
  5. A panel appears on the right side of the screen and starts loading comments automatically.
  6. To close it, paste the script again (it toggles), or click the button in the panel header.

Panel controls

Control Description
Open in a detached popup window
Refresh immediately and reset the countdown
⏸ / ▶ Pause or resume auto-refresh
Close the panel
0 Spoiler delay in seconds — comments are held back for this duration before appearing
ES / PT / EN Language selector (auto-detected from your browser locale on first load)

Notes

  • Only top-level comments are shown. Click ▸ N replies to expand a thread inline.
  • The panel auto-scrolls to the bottom when new comments arrive, but only if you are already near the bottom. Scrolling up to read stops the auto-scroll.
  • Images from i.redd.it, preview.redd.it, i.imgur.com, and GIFs from Giphy are embedded inline at a fixed height of 200px. Click any image to open it full size.
  • The script uses Reddit's public JSON API (<post-url>.json) with your existing session cookies. No data is sent anywhere else.

Español

Requisitos

  • Un navegador de escritorio con DevTools (Chrome, Firefox, Edge, Brave)
  • Cualquier post de Reddit cuya URL contenga /comments/

Cómo usarlo

  1. Abrí el post de Reddit que querés seguir.
  2. Abrí la consola del navegador: F12 → pestaña Consola (o Ctrl+Shift+J en Windows/Linux, Cmd+Option+J en Mac).
  3. Solo la primera vez en Chrome: escribí allow pasting y presioná Enter. Es una medida de seguridad que solo se pide una vez.
  4. Copiá todo el contenido de reddit-live-comments.js y pegalo en la consola. Presioná Enter.
  5. Aparece un panel en el lado derecho de la pantalla y empieza a cargar comentarios automáticamente.
  6. Para cerrarlo, pegá el script de nuevo (funciona como interruptor) o hacé clic en el botón del panel.

Controles del panel

Control Descripción
Abrir en una ventana emergente separada
Actualizar ahora y reiniciar la cuenta regresiva
⏸ / ▶ Pausar o reanudar el auto-refresco
Cerrar el panel
0 Delay anti-spoiler en segundos — los comentarios se retienen ese tiempo antes de aparecer
ES / PT / EN Selector de idioma (se detecta automáticamente del locale del navegador al inicio)

Notas

  • Solo se muestran los comentarios de primer nivel. Hacé clic en ▸ N respuestas para expandir el hilo.
  • El panel hace auto-scroll al final cuando llegan nuevos comentarios, pero solo si ya estás cerca del fondo. Si subís a leer, el scroll automático se detiene.
  • Las imágenes de i.redd.it, preview.redd.it, i.imgur.com y los GIFs de Giphy se muestran embebidos a 200px de alto. Hacé clic en cualquier imagen para abrirla en tamaño completo.
  • El script usa la API JSON pública de Reddit (<url-del-post>.json) con tus cookies de sesión. No se envía ningún dato a ningún otro lado.

Português

Requisitos

  • Um navegador de desktop com DevTools (Chrome, Firefox, Edge, Brave)
  • Qualquer post do Reddit cuja URL contenha /comments/

Como usar

  1. Abra o post do Reddit que deseja acompanhar.
  2. Abra o console do navegador: F12 → aba Console (ou Ctrl+Shift+J no Windows/Linux, Cmd+Option+J no Mac).
  3. Apenas na primeira vez no Chrome: digite allow pasting e pressione Enter. É uma medida de segurança pedida apenas uma vez.
  4. Copie todo o conteúdo de reddit-live-comments.js e cole no console. Pressione Enter.
  5. Um painel aparece no lado direito da tela e começa a carregar comentários automaticamente.
  6. Para fechá-lo, cole o script novamente (funciona como interruptor) ou clique no botão no cabeçalho do painel.

Controles do painel

Controle Descrição
Abrir em uma janela pop-up separada
Atualizar agora e reiniciar a contagem regressiva
⏸ / ▶ Pausar ou retomar a atualização automática
Fechar o painel
0 Delay anti-spoiler em segundos — os comentários ficam retidos por esse tempo antes de aparecer
ES / PT / EN Seletor de idioma (detectado automaticamente pelo locale do navegador na primeira execução)

Notas

  • Apenas comentários de primeiro nível são exibidos. Clique em ▸ N respostas para expandir o thread.
  • O painel faz auto-scroll até o final quando novos comentários chegam, mas somente se você já estiver perto do fundo. Rolar para cima para ler interrompe o auto-scroll.
  • Imagens de i.redd.it, preview.redd.it, i.imgur.com e GIFs do Giphy são exibidos embutidos com altura fixa de 200px. Clique em qualquer imagem para abri-la em tamanho completo.
  • O script usa a API JSON pública do Reddit (<url-do-post>.json) com seus cookies de sessão. Nenhum dado é enviado a terceiros.
(function () {
var PANEL_ID = 'rlc-panel';
var STYLE_ID = 'rlc-style';
var INTERVAL = 10000;
if (document.getElementById(PANEL_ID)) {
clearInterval(window.__rlcTimer); clearInterval(window.__rlcProg);
window.__rlcTimer = window.__rlcProg = null;
document.getElementById(PANEL_ID).remove();
var s = document.getElementById(STYLE_ID); if (s) s.remove();
return;
}
if (!/\/comments\//.test(location.pathname)) {
alert('Open this on a Reddit post page (/comments/ in the URL).');
return;
}
var JSON_URL = location.origin + location.pathname.replace(/\/+$/, '') + '.json?sort=new&limit=200&raw_json=1';
var LANGS = {
es: {
title: '🔴 Comentarios en vivo',
loading: 'Cargando…',
noData: 'Sin datos.',
paused: 'en pausa',
nextIn: 'próximo en {0}s',
updated: 'Actualizado {0} · {1} comentario{2}{3}',
error: '⚠ Error ({0}), reintentando…',
replies: '▸ {0} respuesta{1}{2}',
repliesOpen: '▾ {0} respuesta{1}{2}',
delayTitle: 'Delay anti-spoiler (segundos)',
popupTitle: 'Abrir en ventana emergente',
refreshTitle:'Actualizar ahora',
pauseTitle: 'Pausar/Reanudar',
closeTitle: 'Cerrar',
popupBlocked:'El navegador bloqueó el popup. Permitilo para este sitio y reintentá.',
agoS: 'hace {0}s', agoM: 'hace {0}m', agoH: 'hace {0}h', agoD: 'hace {0}d'
},
pt: {
title: '🔴 Comentários ao vivo',
loading: 'Carregando…',
noData: 'Sem dados.',
paused: 'pausado',
nextIn: 'próximo em {0}s',
updated: 'Atualizado {0} · {1} comentário{2}{3}',
error: '⚠ Erro ({0}), tentando novamente…',
replies: '▸ {0} resposta{1}{2}',
repliesOpen: '▾ {0} resposta{1}{2}',
delayTitle: 'Delay anti-spoiler (segundos)',
popupTitle: 'Abrir em janela pop-up',
refreshTitle:'Atualizar agora',
pauseTitle: 'Pausar/Retomar',
closeTitle: 'Fechar',
popupBlocked:'O navegador bloqueou o pop-up. Permita para este site e tente novamente.',
agoS: 'há {0}s', agoM: 'há {0}min', agoH: 'há {0}h', agoD: 'há {0}d'
},
en: {
title: '🔴 Live Comments',
loading: 'Loading…',
noData: 'No data.',
paused: 'paused',
nextIn: 'next in {0}s',
updated: 'Updated {0} · {1} comment{2}{3}',
error: '⚠ Error ({0}), retrying…',
replies: '▸ {0} repl{1}{2}',
repliesOpen: '▾ {0} repl{1}{2}',
delayTitle: 'Spoiler delay (seconds)',
popupTitle: 'Open in popup window',
refreshTitle:'Refresh now',
pauseTitle: 'Pause/Resume',
closeTitle: 'Close',
popupBlocked:'The browser blocked the popup. Allow it for this site and try again.',
agoS: '{0}s ago', agoM: '{0}m ago', agoH: '{0}h ago', agoD: '{0}d ago'
}
};
function fmt(tpl) {
var args = arguments;
return tpl.replace(/\{(\d+)\}/g, function(_, i){ return args[+i+1] != null ? args[+i+1] : ''; });
}
function detectLang() {
var loc = (navigator.language || 'en').toLowerCase();
if (loc.startsWith('pt')) return 'pt';
if (loc.startsWith('es')) return 'es';
return 'en';
}
var SHARED_CSS =
'.rlc-wrap{display:flex;flex-direction:column;height:100%;background:#0b1416;color:#d7dadc;' +
'font:14px/1.45 system-ui,"Segoe UI",Roboto,Arial,sans-serif}' +
'.rlc-wrap *{box-sizing:border-box}' +
'.rlc-head{display:flex;align-items:center;gap:6px;padding:9px 12px;background:#11201f;border-bottom:1px solid #1f2c2e;flex:0 0 auto}' +
'.rlc-title{font-weight:700;font-size:14px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}' +
'.rlc-delay-wrap{display:flex;align-items:center;gap:4px;font-size:12px;color:#8a9396}' +
'.rlc-delay-wrap input{width:42px;background:#0e1a1b;border:1px solid #1f2c2e;border-radius:5px;' +
'color:#d7dadc;font-size:12px;padding:3px 5px;text-align:center;-moz-appearance:textfield}' +
'.rlc-delay-wrap input::-webkit-inner-spin-button{-webkit-appearance:none}' +
'.rlc-btn{cursor:pointer;background:#1f2c2e;border:none;color:#d7dadc;border-radius:6px;padding:4px 9px;font-size:14px;line-height:1}' +
'.rlc-btn:hover{background:#2a3a3c}' +
'.rlc-lang{background:#0e1a1b;border:1px solid #1f2c2e;border-radius:5px;color:#8a9396;' +
'font-size:11px;padding:3px 4px;cursor:pointer}' +
'.rlc-lang:hover{color:#d7dadc}' +
'.rlc-status{display:flex;justify-content:space-between;gap:8px;padding:5px 12px;font-size:12px;' +
'color:#8a9396;background:#0e1a1b;border-bottom:1px solid #1f2c2e;flex:0 0 auto}' +
'.rlc-cd{color:#6fb1ff;white-space:nowrap;font-variant-numeric:tabular-nums}' +
'.rlc-feed{flex:1 1 auto;overflow-y:auto;padding:6px 10px 14px;overscroll-behavior:contain}' +
'.rlc-c{padding:8px 2px;border-bottom:1px solid #162325}' +
'.rlc-meta{font-size:12px;color:#8a9396;margin-bottom:3px}' +
'.rlc-meta b{color:#9ecbff;font-weight:600}' +
'.rlc-body{white-space:normal;word-break:break-word}' +
'.rlc-body p{margin:.3em 0}' +
'.rlc-body a{color:#6fb1ff}' +
'.rlc-img{display:block;width:100%;height:200px;object-fit:contain;background:#0e1a1b;border-radius:6px;margin-top:6px;cursor:pointer}' +
'.rlc-toggle{margin-top:5px;font-size:12px;color:#6fb1ff;cursor:pointer;user-select:none}' +
'.rlc-replies{margin-top:6px;padding-left:8px;border-left:2px solid #1f2c2e}' +
'.rlc-reply{padding:5px 0;border-top:1px solid #16232540}' +
'.rlc-bar{flex:0 0 auto;height:5px;background:#0e1a1b;border-top:1px solid #1f2c2e;overflow:hidden}' +
'.rlc-fill{height:100%;width:0;background:linear-gradient(90deg,#1f6f63,#34d3b8);transition:width .12s linear}' +
'.rlc-bar.rlc-pp .rlc-fill{background:#3a4a4c;transition:none}';
function RLC(cfg) {
var byId = {};
var paused = false;
var nextAt = 0;
var feed = cfg.feedEl, stEl = cfg.stEl, cdEl = cfg.cdEl;
var barEl = cfg.barEl, fillEl = cfg.fillEl;
var INTERVAL = cfg.interval;
var JSON_URL = cfg.jsonUrl;
var delayInput = cfg.delayInput;
var langSelect = cfg.langSelect;
var LANGS_LOCAL = cfg.langs;
var lang = cfg.lang || 'en';
function tr(key){ return LANGS_LOCAL[lang][key] || LANGS_LOCAL['en'][key] || key; }
function fmtLocal(key) {
var args = [tr(key)].concat(Array.prototype.slice.call(arguments, 1));
return fmt.apply(null, args);
}
function ago(u) {
var s = Math.max(0, Math.floor(Date.now()/1000 - u));
if (s < 60) return fmtLocal('agoS', s);
var m = Math.floor(s/60); if (m < 60) return fmtLocal('agoM', m);
var h = Math.floor(m/60); if (h < 24) return fmtLocal('agoH', h);
return fmtLocal('agoD', Math.floor(h/24));
}
function replyLabel(n, more, open) {
var key = open ? 'repliesOpen' : 'replies';
var plural = lang === 'en' ? (n > 1 ? 'ies' : 'y') : (n > 1 ? 's' : '');
return fmtLocal(key, n, plural, more ? '+' : '');
}
function applyLang() {
var titleEl = cfg.wrapEl && cfg.wrapEl.querySelector('.rlc-title');
if (titleEl) titleEl.textContent = tr('title');
if (cfg.refreshBtn) cfg.refreshBtn.title = tr('refreshTitle');
if (cfg.pauseBtn) cfg.pauseBtn.title = tr('pauseTitle');
if (cfg.closeBtn) cfg.closeBtn.title = tr('closeTitle');
if (cfg.popupBtn) cfg.popupBtn.title = tr('popupTitle');
if (delayInput && delayInput.parentElement) delayInput.parentElement.title = tr('delayTitle');
feed.querySelectorAll('.rlc-toggle').forEach(function(tg) {
var open = tg.textContent[0] === '▾';
var row = tg.closest('.rlc-c');
if (!row || !row._replies) return;
var rc = countReplies(row._replies);
tg.textContent = replyLabel(rc.n, rc.more, open);
});
feed.querySelectorAll('.rlc-time').forEach(function(el) {
var utc = parseFloat(el.dataset.utc);
if (!isNaN(utc)) el.textContent = ago(utc);
});
}
if (langSelect) {
langSelect.value = lang;
langSelect.addEventListener('change', function() {
lang = langSelect.value;
applyLang();
});
}
var holdQueue = [];
function getDelaySecs(){ return Math.max(0, parseFloat(delayInput.value)||0); }
function flushQueue(){
var now = Date.now(), delaySecs = getDelaySecs();
var near = feed.scrollHeight - feed.scrollTop - feed.clientHeight < 80;
var added = 0;
holdQueue = holdQueue.filter(function(item){
if (now - item.arrivedAt < delaySecs*1000) return true;
if (!byId[item.d.id]){ var el=makeRow(item.d); byId[item.d.id]=el; feed.appendChild(el); added++; }
else updateRow(byId[item.d.id], item.d);
return false;
});
if (added && near) feed.scrollTop = feed.scrollHeight;
}
setInterval(flushQueue, 500);
function esc(s){return(s==null?'':String(s)).replace(/[&<>"]/g,function(c){return{'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];});}
function decodeHtml(h){var el=document.createElement('textarea');el.innerHTML=h||'';return el.value;}
function countReplies(r){var n=0,more=false;(function w(r){if(!r||!r.data||!r.data.children)return;r.data.children.forEach(function(c){if(c.kind==='t1'){n++;w(c.data.replies);}else if(c.kind==='more')more=true;});})(r);return{n:n,more:more};}
var IMG_RE = /^https?:\/\/(preview\.redd\.it|i\.redd\.it|i\.imgur\.com|media\d*\.giphy\.com|media\.giphy\.com|giphy\.com\/media)[^\s"<>]*/i;
var GIPHY_RE = /^https?:\/\/(?:www\.)?giphy\.com\/gifs\/(?:[^\/]+-)?([a-zA-Z0-9]+)\/?(?:\?.*)?$/;
function embedImages(container){
container.querySelectorAll('a').forEach(function(a){
var href=a.href||'';
var m=href.match(GIPHY_RE);
var src=m?'https://media.giphy.com/media/'+m[1]+'/giphy.gif':(IMG_RE.test(href)?href:null);
if(!src)return;
var img=document.createElement('img');
img.src=src; img.className='rlc-img'; img.loading='lazy'; img.alt='';
img.onclick=function(){window.open(href,'_blank');};
img.onload=function(){if(feed.scrollHeight-feed.scrollTop-feed.clientHeight<120)feed.scrollTop=feed.scrollHeight;};
if(a.textContent.trim()===href||a.textContent.trim()===''){a.replaceWith(img);}
else{a.insertAdjacentElement('afterend',img);}
});
}
function safeHtml(bodyHtml){
var tmp=document.createElement('div'); tmp.innerHTML=decodeHtml(bodyHtml);
tmp.querySelectorAll('script,style,iframe,link,meta,form').forEach(function(n){n.remove();});
tmp.querySelectorAll('a').forEach(function(a){a.target='_blank';a.rel='noopener noreferrer';});
embedImages(tmp); return tmp.innerHTML;
}
function renderReplies(replies, depth){
var f=document.createDocumentFragment();
if(!replies||!replies.data||!replies.data.children)return f;
replies.data.children.forEach(function(c){
if(c.kind!=='t1')return;
var d=c.data, row=document.createElement('div');
row.className='rlc-reply'; row.style.marginLeft=Math.min(depth,6)*10+'px';
row.innerHTML='<div class="rlc-meta"><b>u/'+esc(d.author)+'</b> · '+d.score+' · <span class="rlc-time" data-utc="'+d.created_utc+'">'+ago(d.created_utc)+'</span></div>'+
'<div class="rlc-body">'+safeHtml(d.body_html)+'</div>';
var sub=renderReplies(d.replies,depth+1); if(sub.childNodes.length)row.appendChild(sub);
f.appendChild(row);
});
return f;
}
function fillRow(row, d){
var rc=countReplies(d.replies); row._replies=d.replies;
row.innerHTML=
'<div class="rlc-meta"><b>u/'+esc(d.author)+'</b>'+
' · <span class="rlc-score">'+d.score+'</span>'+
' · <span class="rlc-time" data-utc="'+d.created_utc+'">'+ago(d.created_utc)+'</span></div>'+
'<div class="rlc-body">'+safeHtml(d.body_html)+'</div>'+
(rc.n>0?'<div class="rlc-toggle" role="button">'+replyLabel(rc.n,rc.more,false)+'</div><div class="rlc-replies" hidden></div>':'');
}
function makeRow(d){ var r=document.createElement('div'); r.className='rlc-c'; r.dataset.id=d.id; fillRow(r,d); return r; }
function updateRow(row, d){
var sc=row.querySelector('.rlc-score'); if(sc)sc.textContent=d.score;
var tm=row.querySelector('.rlc-time'); if(tm)tm.textContent=ago(d.created_utc);
row._replies=d.replies;
var rc=countReplies(d.replies), tg=row.querySelector('.rlc-toggle');
if(rc.n>0&&!tg){fillRow(row,d);}
else if(tg){
var open=tg.textContent[0]==='▾';
tg.textContent=replyLabel(rc.n,rc.more,open);
var box=row.querySelector('.rlc-replies');
if(box&&!box.hidden){box.innerHTML='';box.appendChild(renderReplies(d.replies,0));}
}
}
(cfg.snapshot||[]).forEach(function(s){
var row=document.createElement('div'); row.className='rlc-c'; row.dataset.id=s.id;
row.innerHTML=s.html;
try{if(s.rep)row._replies=JSON.parse(s.rep);}catch(e){}
byId[s.id]=row; feed.appendChild(row);
});
if(feed.children.length){feed.scrollTop=feed.scrollHeight;feed.dataset.loaded='1';}
feed.addEventListener('click',function(e){
var tg=e.target.closest&&e.target.closest('.rlc-toggle'); if(!tg)return;
var row=tg.closest('.rlc-c'); var box=row.querySelector('.rlc-replies'); if(!box)return;
var rc=countReplies(row._replies);
if(box.hidden){box.innerHTML='';box.appendChild(renderReplies(row._replies,0));box.hidden=false;tg.textContent=replyLabel(rc.n,rc.more,true);}
else{box.hidden=true;tg.textContent=replyLabel(rc.n,rc.more,false);}
});
function setStatus(txt){ stEl.textContent=txt; }
function poll(){
if(paused)return;
nextAt=Date.now()+INTERVAL;
fetch(JSON_URL,{credentials:'same-origin',headers:{'Accept':'application/json'}})
.then(function(r){if(!r.ok)throw new Error('HTTP '+r.status);return r.json();})
.then(function(data){
var listing=data&&data[1]&&data[1].data&&data[1].data.children;
if(!listing){setStatus(tr('noData'));return;}
var tops=[]; listing.forEach(function(c){if(c.kind==='t1')tops.push(c.data);});
tops.sort(function(a,b){return a.created_utc-b.created_utc;});
var now=Date.now();
tops.forEach(function(d){
if(byId[d.id]){updateRow(byId[d.id],d);return;}
var inQ=holdQueue.some(function(i){return i.d.id===d.id;});
if(!inQ)holdQueue.push({d:d,arrivedAt:now});
});
flushQueue();
feed.dataset.loaded='1';
var time=new Date();
var hh=('0'+time.getHours()).slice(-2)+':'+('0'+time.getMinutes()).slice(-2)+':'+('0'+time.getSeconds()).slice(-2);
var visible=feed.querySelectorAll('.rlc-c').length;
var plural = lang==='en'?(visible!==1?'s':''):(visible!==1?'s':'');
setStatus(fmtLocal('updated', hh, visible, plural, ''));
})
.catch(function(e){setStatus(fmtLocal('error', e.message||'red'));});
}
var _loopTimer;
function startLoop(){
clearInterval(_loopTimer); nextAt=Date.now()+INTERVAL;
_loopTimer=setInterval(poll,INTERVAL); return _loopTimer;
}
function updateProgress(){
if(paused){cdEl.textContent=tr('paused');return;}
var rem=nextAt-Date.now(), pct=100*(1-rem/INTERVAL);
if(pct<0)pct=0; if(pct>100)pct=100;
fillEl.style.width=pct.toFixed(1)+'%';
cdEl.textContent=fmtLocal('nextIn', Math.max(0,Math.ceil(rem/1000)));
}
cfg.pauseBtn.addEventListener('click',function(){
paused=!paused; cfg.pauseBtn.textContent=paused?'▶':'⏸';
if(paused){barEl.classList.add('rlc-pp');}
else{barEl.classList.remove('rlc-pp');poll();startLoop();}
});
cfg.refreshBtn.addEventListener('click',function(){
if(paused){paused=false;cfg.pauseBtn.textContent='⏸';barEl.classList.remove('rlc-pp');}
poll();startLoop();
});
applyLang();
poll();
var lt=startLoop();
var pt=setInterval(updateProgress,100);
return { stopAll: function(){ clearInterval(lt); clearInterval(pt); } };
}
function langSelectHTML(current) {
return '<select class="rlc-lang" title="Language / Idioma / Língua">' +
['es','pt','en'].map(function(l){
return '<option value="'+l+'"'+(current===l?' selected':'')+'>'+l.toUpperCase()+'<\/option>';
}).join('') +
'<\/select>';
}
var initLang = detectLang();
var style = document.createElement('style');
style.id = STYLE_ID;
style.textContent =
'#'+PANEL_ID+'{position:fixed;top:0;right:0;width:420px;max-width:96vw;height:100vh;' +
'z-index:2147483647;box-shadow:-4px 0 24px rgba(0,0,0,.5);border-left:1px solid #1f2c2e}' +
SHARED_CSS +
'#'+PANEL_ID+' .rlc-wrap{height:100vh}';
document.head.appendChild(style);
var panel = document.createElement('div');
panel.id = PANEL_ID;
panel.innerHTML =
'<div class="rlc-wrap">' +
'<div class="rlc-head">' +
'<span class="rlc-title"></span>' +
'<label class="rlc-delay-wrap"><input type="number" class="rlc-delay-input" value="0" min="0" max="3600" step="5"></label>' +
'<button class="rlc-btn rlc-popup-btn">⧉</button>' +
'<button class="rlc-btn rlc-refresh-btn">⟳</button>' +
'<button class="rlc-btn rlc-pause-btn">⏸</button>' +
'<button class="rlc-btn rlc-close-btn">✕</button>' +
langSelectHTML(initLang) +
'</div>' +
'<div class="rlc-status"><span class="rlc-st"></span><span class="rlc-cd"></span></div>' +
'<div class="rlc-feed"></div>' +
'<div class="rlc-bar"><div class="rlc-fill"></div></div>' +
'</div>';
document.body.appendChild(panel);
var motor = RLC({
wrapEl: panel.querySelector('.rlc-wrap'),
feedEl: panel.querySelector('.rlc-feed'),
stEl: panel.querySelector('.rlc-st'),
cdEl: panel.querySelector('.rlc-cd'),
barEl: panel.querySelector('.rlc-bar'),
fillEl: panel.querySelector('.rlc-fill'),
pauseBtn: panel.querySelector('.rlc-pause-btn'),
refreshBtn: panel.querySelector('.rlc-refresh-btn'),
closeBtn: panel.querySelector('.rlc-close-btn'),
popupBtn: panel.querySelector('.rlc-popup-btn'),
delayInput: panel.querySelector('.rlc-delay-input'),
langSelect: panel.querySelector('.rlc-lang'),
jsonUrl: JSON_URL,
interval: INTERVAL,
snapshot: [],
lang: initLang,
langs: LANGS
});
function destroyPanel() {
motor.stopAll();
window.__rlcTimer = window.__rlcProg = null;
panel.remove();
var s = document.getElementById(STYLE_ID); if (s) s.remove();
}
panel.querySelector('.rlc-close-btn').addEventListener('click', destroyPanel);
panel.querySelector('.rlc-popup-btn').addEventListener('click', function () {
var ph = window.screen.availHeight || 900;
var pw = 460;
var pl = (window.screen.availWidth || 1440) - pw;
var popup = window.open('', 'rlc_popup',
'width='+pw+',height='+ph+',left='+pl+',top=0,resizable=yes,scrollbars=no,toolbar=no,menubar=no,location=no,status=no');
if (!popup) { alert(LANGS[initLang].popupBlocked); return; }
var currentLang = panel.querySelector('.rlc-lang').value;
var snapshot = [];
panel.querySelectorAll('.rlc-feed .rlc-c').forEach(function(el){
snapshot.push({ id: el.dataset.id, html: el.innerHTML, rep: el._replies ? JSON.stringify(el._replies) : null });
});
var popupHtml =
'<!DOCTYPE html><html lang="'+currentLang+'"><head><meta charset="utf-8">' +
'<title></title>' +
'<style>html,body{margin:0;height:100%;overflow:hidden}#rlc-root{height:100vh}' +
SHARED_CSS+'.rlc-wrap{height:100vh}.rlc-img{height:200px}<\/style>' +
'<\/head><body>' +
'<div id="rlc-root"><div class="rlc-wrap">' +
'<div class="rlc-head">' +
'<span class="rlc-title"><\/span>' +
'<label class="rlc-delay-wrap"><input type="number" id="pb-delay" value="'+(panel.querySelector('.rlc-delay-input').value||0)+'" min="0" max="3600" step="5"><\/label>' +
'<button class="rlc-btn" id="pb-refresh">\u27F3<\/button>' +
'<button class="rlc-btn" id="pb-pause">\u23F8<\/button>' +
langSelectHTML(currentLang) +
'<\/div>' +
'<div class="rlc-status"><span id="pb-st"><\/span><span class="rlc-cd" id="pb-cd"><\/span><\/div>' +
'<div class="rlc-feed" id="pb-feed"><\/div>' +
'<div class="rlc-bar" id="pb-bar"><div class="rlc-fill" id="pb-fill"><\/div><\/div>' +
'<\/div><\/div>' +
'<\/body><\/html>';
popup.document.open();
popup.document.write(popupHtml);
popup.document.close();
var scriptSrc =
'var LANGS='+JSON.stringify(LANGS)+';' +
'var fmt='+fmt.toString()+';' +
'var RLC='+RLC.toString()+';' +
'RLC({' +
'wrapEl:document.querySelector(".rlc-wrap"),' +
'feedEl:document.getElementById("pb-feed"),' +
'stEl:document.getElementById("pb-st"),' +
'cdEl:document.getElementById("pb-cd"),' +
'barEl:document.getElementById("pb-bar"),' +
'fillEl:document.getElementById("pb-fill"),' +
'pauseBtn:document.getElementById("pb-pause"),' +
'refreshBtn:document.getElementById("pb-refresh"),' +
'langSelect:document.querySelector(".rlc-lang"),' +
'delayInput:document.getElementById("pb-delay"),' +
'jsonUrl:'+JSON.stringify(JSON_URL)+',' +
'interval:'+INTERVAL+',' +
'snapshot:'+JSON.stringify(snapshot)+',' +
'lang:'+JSON.stringify(currentLang)+',' +
'langs:LANGS' +
'});';
var blob = new Blob([scriptSrc], { type: 'application/javascript' });
var blobUrl = URL.createObjectURL(blob);
var scr = popup.document.createElement('script');
scr.src = blobUrl;
scr.onload = function(){ URL.revokeObjectURL(blobUrl); };
popup.document.head.appendChild(scr);
destroyPanel();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment