/*!
* ZCJ Top Citite Azi - widget responsive
* Sursa: sectiunea "Top citite azi" de pe homepage-ul zcj.ro (same-origin, fara CORS)
*
* Utilizare:
*
*
*
* Optiuni (data-attributes pe container):
* data-limit="5" numarul de articole (implicit 5)
* data-refresh="600" refresh automat, in secunde (implicit 600 = 10 min; 0 = dezactivat)
* data-title="Top citite azi" titlul afisat (gol = fara titlu)
* data-source="/" pagina din care se extrage sectiunea
* data-target="_self" target pentru linkuri (_blank pentru tab nou)
*/
(function () {
'use strict';
var CACHE_KEY = 'zcjtc:v1';
var STYLE_ID = 'zcjtc-style';
var SECTION_RE = /top\s*citite/i;
var CSS = [
'.zcjtc{--zcjtc-accent:#c1121f;--zcjtc-fg:#141414;--zcjtc-muted:#6b7280;--zcjtc-line:#e5e7eb;--zcjtc-bg:transparent;',
'box-sizing:border-box;width:100%;max-width:100%;color:var(--zcjtc-fg);background:var(--zcjtc-bg);',
'font-family:inherit;line-height:1.35;-webkit-font-smoothing:antialiased}',
'.zcjtc *,.zcjtc *::before,.zcjtc *::after{box-sizing:border-box}',
'.zcjtc-head{display:flex;align-items:center;gap:10px;margin:0 0 12px}',
'.zcjtc-head h3{margin:0;font-size:clamp(15px,1.05rem,18px);font-weight:800;letter-spacing:.01em;text-transform:uppercase;color:inherit}',
'.zcjtc-head::after{content:"";flex:1 1 auto;height:2px;background:var(--zcjtc-accent);opacity:.85;border-radius:2px}',
'.zcjtc-list{list-style:none;margin:0;padding:0;counter-reset:zcjtc}',
'.zcjtc-list>li{counter-increment:zcjtc;border-bottom:1px solid var(--zcjtc-line)}',
'.zcjtc-list>li:last-child{border-bottom:0}',
'.zcjtc-list>li>a{display:flex;align-items:flex-start;gap:10px;padding:10px 2px;text-decoration:none;color:inherit;transition:background-color .15s ease}',
'.zcjtc-list>li>a:hover,.zcjtc-list>li>a:focus-visible{background:rgba(0,0,0,.035)}',
'.zcjtc-list>li>a:focus-visible{outline:2px solid var(--zcjtc-accent);outline-offset:-2px}',
'.zcjtc-num{flex:0 0 auto;min-width:1.5em;font-size:clamp(17px,1.15rem,20px);font-weight:800;line-height:1.15;color:var(--zcjtc-accent);font-variant-numeric:tabular-nums;text-align:center}',
'.zcjtc-num::before{content:counter(zcjtc)}',
'.zcjtc-body{flex:1 1 auto;min-width:0}',
'.zcjtc-title{display:block;font-size:clamp(13.5px,.92rem,15.5px);font-weight:600;overflow-wrap:anywhere}',
'.zcjtc-list>li>a:hover .zcjtc-title{color:var(--zcjtc-accent)}',
'.zcjtc-meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:4px;font-size:11.5px;color:var(--zcjtc-muted)}',
'.zcjtc-tag{display:inline-block;padding:1px 5px;border-radius:3px;background:var(--zcjtc-accent);color:#fff;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}',
'.zcjtc-msg{padding:10px 2px;font-size:13px;color:var(--zcjtc-muted)}',
'.zcjtc-msg button{margin-left:8px;padding:3px 9px;font:inherit;font-size:12px;border:1px solid var(--zcjtc-line);border-radius:4px;background:#fff;color:inherit;cursor:pointer}',
'.zcjtc-sk{padding:10px 2px;border-bottom:1px solid var(--zcjtc-line)}',
'.zcjtc-sk span{display:block;height:11px;border-radius:3px;background:linear-gradient(90deg,#ececec 25%,#f6f6f6 37%,#ececec 63%);background-size:400% 100%;animation:zcjtc-sh 1.3s ease infinite}',
'.zcjtc-sk span+span{margin-top:6px;width:55%}',
'@keyframes zcjtc-sh{0%{background-position:100% 50%}100%{background-position:0 50%}}',
'@media (prefers-reduced-motion:reduce){.zcjtc-sk span{animation:none}}',
'@media (prefers-color-scheme:dark){.zcjtc:not([data-theme="light"]){--zcjtc-fg:#f2f2f2;--zcjtc-muted:#9ca3af;--zcjtc-line:#2c2c2c;--zcjtc-accent:#ff5a5f}',
'.zcjtc:not([data-theme="light"]) .zcjtc-list>li>a:hover{background:rgba(255,255,255,.06)}',
'.zcjtc:not([data-theme="light"]) .zcjtc-msg button{background:#1c1c1c}',
'.zcjtc:not([data-theme="light"]) .zcjtc-sk span{background:linear-gradient(90deg,#242424 25%,#2f2f2f 37%,#242424 63%);background-size:400% 100%}}'
].join('');
function injectStyle() {
if (document.getElementById(STYLE_ID)) return;
var s = document.createElement('style');
s.id = STYLE_ID;
s.textContent = CSS;
(document.head || document.documentElement).appendChild(s);
}
/* ---------- parsare ---------- */
function findSection(doc) {
var heads = doc.querySelectorAll('h1,h2,h3,h4,.titlu-1');
for (var i = 0; i < heads.length; i++) {
var t = (heads[i].textContent || '').trim();
if (SECTION_RE.test(t)) {
var box = heads[i].parentElement;
if (box && box.querySelector('.box-item')) return box;
}
}
return null;
}
function parse(doc, base) {
var box = findSection(doc);
if (!box) return null;
var nodes = box.querySelectorAll('.box-item');
var out = [];
for (var i = 0; i < nodes.length; i++) {
var it = nodes[i];
var a = it.querySelector('.box-item-title a') || it.querySelector('a[href]');
if (!a) continue;
var clone = a.cloneNode(true);
var lab = clone.querySelectorAll('.inline-labels, .label');
for (var j = 0; j < lab.length; j++) { if (lab[j].parentNode) lab[j].parentNode.removeChild(lab[j]); }
var title = (clone.textContent || '').replace(/\s+/g, ' ').trim();
var href = a.getAttribute('href') || '';
if (!title || !href) continue;
var dateEl = it.querySelector('.post-date');
var tags = [];
var labEls = a.querySelectorAll('.label');
for (var k = 0; k < labEls.length; k++) {
var lt = (labEls[k].textContent || '').replace(/\s+/g, ' ').trim();
if (lt) tags.push(lt);
}
out.push({
title: title,
url: new URL(href, base || location.href).href,
time: dateEl ? (dateEl.textContent || '').replace(/\s+/g, ' ').trim() : '',
tags: tags
});
}
return out.length ? out : null;
}
/* ---------- date ---------- */
function readCache(maxAge) {
try {
var raw = sessionStorage.getItem(CACHE_KEY);
if (!raw) return null;
var o = JSON.parse(raw);
if (!o || !o.items || !o.items.length) return null;
if (maxAge && Date.now() - o.t > maxAge) return null;
return o.items;
} catch (e) { return null; }
}
function writeCache(items) {
try { sessionStorage.setItem(CACHE_KEY, JSON.stringify({ t: Date.now(), items: items })); } catch (e) {}
}
function fetchItems(source, maxAge, force) {
// 1. daca widgetul e chiar pe pagina care contine sectiunea, o citim direct din DOM
var local = parse(document, location.href);
if (local) { writeCache(local); return Promise.resolve(local); }
// 2. cache de sesiune
if (!force) {
var cached = readCache(maxAge);
if (cached) return Promise.resolve(cached);
}
// 3. fetch same-origin + parsare
var url = source + (source.indexOf('?') === -1 ? '?' : '&') + 'zcjtc=' + Date.now();
return fetch(url, { credentials: 'same-origin', headers: { 'X-Requested-With': 'zcj-top-citite' } })
.then(function (r) {
if (!r.ok) throw new Error('HTTP ' + r.status);
return r.text();
})
.then(function (html) {
var doc = new DOMParser().parseFromString(html, 'text/html');
var items = parse(doc, new URL(source, location.href).href);
if (!items) throw new Error('Sectiunea "Top citite azi" nu a fost gasita');
writeCache(items);
return items;
});
}
/* ---------- randare ---------- */
function el(tag, cls, text) {
var n = document.createElement(tag);
if (cls) n.className = cls;
if (text != null) n.textContent = text;
return n;
}
function skeleton(box, n) {
box.textContent = '';
for (var i = 0; i < n; i++) {
var d = el('div', 'zcjtc-sk');
d.appendChild(el('span'));
d.appendChild(el('span'));
box.appendChild(d);
}
}
function renderList(box, items, opt) {
box.textContent = '';
var ol = el('ol', 'zcjtc-list');
items.slice(0, opt.limit).forEach(function (it) {
var li = el('li');
var a = el('a');
a.href = it.url;
a.target = opt.target;
if (opt.target === '_blank') a.rel = 'noopener';
a.appendChild(el('span', 'zcjtc-num'));
var body = el('div', 'zcjtc-body');
body.appendChild(el('span', 'zcjtc-title', it.title));
if (it.time || (it.tags && it.tags.length)) {
var meta = el('div', 'zcjtc-meta');
(it.tags || []).forEach(function (t) { meta.appendChild(el('span', 'zcjtc-tag', t)); });
if (it.time) meta.appendChild(el('span', null, it.time));
body.appendChild(meta);
}
a.appendChild(body);
li.appendChild(a);
ol.appendChild(li);
});
box.appendChild(ol);
}
function renderError(box, retry) {
box.textContent = '';
var m = el('div', 'zcjtc-msg', 'Lista nu a putut fi incarcata.');
var b = el('button', null, 'Reincearca');
b.type = 'button';
b.addEventListener('click', retry);
m.appendChild(b);
box.appendChild(m);
}
/* ---------- init ---------- */
function init(root) {
if (!root || root.getAttribute('data-zcjtc-ready') === '1') return null;
root.setAttribute('data-zcjtc-ready', '1');
injectStyle();
var opt = {
limit: Math.max(1, parseInt(root.getAttribute('data-limit'), 10) || 5),
refresh: (function (v) { return v === null ? 600 : (parseInt(v, 10) || 0); })(root.getAttribute('data-refresh')) * 1000,
title: root.getAttribute('data-title') === null ? 'Top citite azi' : root.getAttribute('data-title'),
source: root.getAttribute('data-source') || '/',
target: root.getAttribute('data-target') || '_self'
};
root.classList.add('zcjtc');
root.textContent = '';
if (opt.title) {
var head = el('div', 'zcjtc-head');
head.appendChild(el('h3', null, opt.title));
root.appendChild(head);
}
var box = el('div', 'zcjtc-body-wrap');
box.setAttribute('aria-live', 'polite');
box.setAttribute('aria-busy', 'true');
root.appendChild(box);
var timer = null;
var last = 0;
function load(force) {
if (!force) skeleton(box, opt.limit);
box.setAttribute('aria-busy', 'true');
return fetchItems(opt.source, opt.refresh || 600000, force)
.then(function (items) {
last = Date.now();
renderList(box, items, opt);
})
.catch(function () {
var cached = readCache(0);
if (cached) { renderList(box, cached, opt); }
else { renderError(box, function () { load(true); }); }
})
.then(function () { box.setAttribute('aria-busy', 'false'); });
}
function schedule() {
if (!opt.refresh) return;
clearInterval(timer);
timer = setInterval(function () {
if (document.hidden) return;
load(true);
}, opt.refresh);
}
document.addEventListener('visibilitychange', function () {
if (!document.hidden && opt.refresh && Date.now() - last > opt.refresh) load(true);
});
load(false);
schedule();
return { reload: function () { return load(true); }, element: root };
}
function boot() {
var nodes = document.querySelectorAll('[data-zcj-top-citite], #zcj-top-citite');
for (var i = 0; i < nodes.length; i++) init(nodes[i]);
}
window.ZcjTopCitite = { init: init, boot: boot, parse: parse };
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot);
else boot();
})();