/* Eurodac Video Stories
Citeste playlist-ul video Elementor de pe pagina de produs si il re-randeaza
ca un rand de stories. Playlist-ul vechi ramane in DOM (el tine datele) si e
ascuns DOAR dupa ce randul s-a construit cu succes — daca ceva pica, nimic
nu dispare de pe pagina. */
(function () {
"use strict";
/* Toate video-urile au un intro si un outro cu logo, montate de client.
Orice redare porneste de la secunda 10, iar buclele sar inapoi la 10
inainte de outro — utilizatorul nu le vede niciodata. */
var SKIP_HOVER = 15;
var SKIP_AUTO = 15;
var OUTRO = 10; // secunde taiate de la coada, la bucle
var TITLE = "Utilajele în acțiune";
var SUB = "Filmări reale din producție — apasă pentru varianta completă";
var desktop = matchMedia("(hover:hover) and (pointer:fine)").matches;
/* Titlurile din playlist repeta tipul utilajului („Masina...", „Linie...") si abia
apoi spun ce face. Tipul devine un kicker mic deasupra, titlul ramane actiunea. */
var TYPES = [
[/^ma[sș]in[ăa]\s+/i, "Mașină"],
[/^lini[ea]\s+/i, "Linie"],
[/^sta[tț]ie\s+/i, "Stație"],
[/^echipament\s+/i, "Echipament"],
[/^utilaj\s+/i, "Utilaj"]
];
function niceTitle(raw) {
var s = String(raw || "").trim().replace(/\s{2,}/g, " ");
var k = "";
for (var i = 0; i < TYPES.length; i++) {
if (TYPES[i][0].test(s)) { k = TYPES[i][1]; s = s.replace(TYPES[i][0], ""); break; }
}
s = s.replace(/^(automat[ăa]?\s+)?(de\s+|pentru\s+|pt\.?\s+)+/i, "");
s = s.replace(/\s+de\s+dozare\s*$/i, "");
s = s.replace(/recipiente\s+tip\s+/i, "");
s = s.replace(/\bpicaturi\b/gi, "picături").replace(/\bsi\b/gi, "și")
.replace(/\blineara\b/gi, "lineară").replace(/\b50ml\b/gi, "50 ml");
s = s.toLowerCase();
s = s.charAt(0).toUpperCase() + s.slice(1);
return { k: k, t: s || raw };
}
function parseWidget(w) {
var raw = w.getAttribute("data-settings");
if (!raw) return [];
var cfg;
try { cfg = JSON.parse(raw); } catch (e) { return []; }
var tabs = cfg && cfg.tabs;
if (!Array.isArray(tabs)) return [];
var out = [];
tabs.forEach(function (t) {
var url = t && t.hosted_url && t.hosted_url.url;
if (!url) return; // doar video-uri gazduite
var th = (t.thumbnail && t.thumbnail.url) || "";
if (th.indexOf("/plugins/elementor/") !== -1) th = ""; // placeholderul Elementor nu e poster
out.push({ t: t.title || "", u: url, p: th });
});
return out;
}
function el(tag, cls, txt) {
var n = document.createElement(tag);
if (cls) n.className = cls;
if (txt != null) n.textContent = txt;
return n;
}
function fmtDur(sec) {
var s = Math.round(sec);
return Math.floor(s / 60) + ":" + String(s % 60).padStart(2, "0");
}
function build(widget, V) {
var wrap = el("section", "evs-wrap");
/* grila se scaleaza dupa cate videouri exista: 3 -> 3 pe toata latimea,
2 -> 2, 1 -> unul centrat; 4+ pastreaza caruselul de 4 */
if (V.length <= 3) wrap.classList.add("evs-n" + V.length);
wrap.appendChild(el("h2", "evs-h2", TITLE));
wrap.appendChild(el("p", "evs-sub", SUB));
var shell = el("div", "evs-shell");
var al = el("button", "evs-arr evs-arr--l", "‹"); al.setAttribute("aria-label", "Înapoi");
var ar = el("button", "evs-arr evs-arr--r", "›"); ar.setAttribute("aria-label", "Înainte");
var row = el("div", "evs-row");
shell.appendChild(al); shell.appendChild(row); shell.appendChild(ar);
wrap.appendChild(shell);
var cards = [];
V.forEach(function (v, i) {
var c = el("div", "evs-card");
c.setAttribute("role", "button");
c.setAttribute("tabindex", "0");
c.setAttribute("aria-label", v.t);
if (v.p) {
var img = el("img"); img.loading = "lazy"; img.src = v.p; img.alt = "";
c.appendChild(img);
}
var vid = el("video");
vid.muted = true; vid.loop = true; vid.playsInline = true;
vid.preload = v.p ? "none" : "metadata";
if (!v.p) vid.src = v.u;
c.appendChild(vid);
c.appendChild(el("div", "evs-scrim"));
var play = el("div", "evs-play");
play.innerHTML = '';
c.appendChild(play);
var nice = niceTitle(v.t);
var tw = el("div", "evs-tw");
if (nice.k) tw.appendChild(el("div", "evs-kick", nice.k));
tw.appendChild(el("div", "evs-title", nice.t));
c.appendChild(tw);
function preview(at) {
var t = at == null ? SKIP_HOVER : at;
if (!vid.src) {
vid.src = v.u;
vid.addEventListener("loadedmetadata", function () {
var start = vid.duration > t + 6 ? t : 0;
var end = vid.duration > 30 ? vid.duration - OUTRO : vid.duration;
if (start) vid.currentTime = start;
// bucla ocoleste outro-ul: inainte de coada, sarim inapoi la start
vid.addEventListener("timeupdate", function () {
if (end < vid.duration && vid.currentTime >= end) vid.currentTime = start;
});
}, { once: true });
}
var p = vid.play(); if (p && p.catch) p.catch(function () {});
c.classList.add("evs-previewing");
}
c.addEventListener("click", function () { open(i); });
c.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); open(i); }
});
row.appendChild(c);
cards.push({ c: c, vid: vid, preview: preview });
});
// stil story-feed: toate cardurile ruleaza mut, in bucla, cat timp sunt
// in ecran; pornesc esalonat (250ms intre ele) ca sa nu sugrume banda si
// se opresc cand ies din viewport — pe mobil ruleaza doar ce se vede.
cards.forEach(function (x, k) { x.c.__evsIdx = k; });
if ("IntersectionObserver" in window) {
var t0 = null;
var io = new IntersectionObserver(function (es) {
es.forEach(function (e) {
var card = cards[e.target.__evsIdx];
if (!card) return;
if (e.isIntersecting) {
if (t0 === null) t0 = Date.now();
var wait = Math.max(0, 250 * e.target.__evsIdx - (Date.now() - t0));
card.tmr = setTimeout(function () { card.preview(SKIP_AUTO); }, wait);
} else {
clearTimeout(card.tmr);
card.vid.pause();
card.c.classList.remove("evs-previewing");
}
});
}, { threshold: 0.35 });
cards.forEach(function (x) { io.observe(x.c); });
} else if (desktop && cards[0]) {
cards[0].preview(SKIP_AUTO);
}
// browserul pauzeaza video-urile cand tabul devine invizibil; la revenire, repornim
document.addEventListener("visibilitychange", function () {
if (document.hidden) return;
cards.forEach(function (x) {
if (x.c.classList.contains("evs-previewing")) {
var p = x.vid.play(); if (p && p.catch) p.catch(function () {});
}
});
});
function step() {
var c = row.firstElementChild;
return c ? c.getBoundingClientRect().width + 16 : 300;
}
al.onclick = function () { row.scrollBy({ left: -2 * step() }); };
ar.onclick = function () { row.scrollBy({ left: 2 * step() }); };
function arrows() {
al.disabled = row.scrollLeft < 8;
ar.disabled = row.scrollLeft > row.scrollWidth - row.clientWidth - 8;
}
row.addEventListener("scroll", arrows);
addEventListener("resize", arrows);
// popup
var lb = el("div", "evs-lb");
lb.setAttribute("role", "dialog"); lb.setAttribute("aria-modal", "true");
var pv = el("button", "evs-nav evs-prev", "‹"); pv.setAttribute("aria-label", "Anteriorul");
var nx = el("button", "evs-nav evs-next", "›"); nx.setAttribute("aria-label", "Următorul");
var panel = el("div", "evs-panel");
var x = el("button", "evs-x", "✕"); x.setAttribute("aria-label", "Închide");
var lbv = el("video"); lbv.controls = true; lbv.playsInline = true;
var foot = el("div", "evs-foot");
var lbk = el("div", "evs-lb-k");
var lbt = el("div", "evs-lb-t");
var lbc = el("div", "evs-lb-c");
foot.appendChild(lbk); foot.appendChild(lbt); foot.appendChild(lbc);
var ld = el("div", "evs-load");
panel.appendChild(x); panel.appendChild(lbv); panel.appendChild(ld); panel.appendChild(foot);
lb.appendChild(pv); lb.appendChild(panel); lb.appendChild(nx);
document.body.appendChild(lb);
var cur = 0;
function open(i) {
cur = (i + V.length) % V.length;
// continuitate: daca preview-ul cardului rula, popupul continua de la aceeasi secunda
var at = 0;
var cv = cards[cur].vid;
if (cv.src && !cv.paused && cv.currentTime > 0.5) at = cv.currentTime;
lbv.src = V[cur].u;
// continuitate din preview sau, implicit, start dupa intro (secunda 10)
lbv.addEventListener("loadedmetadata", function () {
var start = at > 0 ? at : (lbv.duration > 16 ? SKIP_AUTO : 0);
if (start) lbv.currentTime = start;
}, { once: true });
var nk = niceTitle(V[cur].t);
lbk.textContent = nk.k;
lbk.style.display = nk.k ? "" : "none";
lbt.textContent = nk.t;
lbc.textContent = (cur + 1) + " / " + V.length;
var deja = lb.classList.contains("evs-on");
lb.classList.add("evs-on");
panel.classList.add("evs-loading");
if (!deja) {
// intrarea: un cadru pentru display, apoi tranzitia de opacitate/scale
requestAnimationFrame(function () {
requestAnimationFrame(function () { lb.classList.add("evs-in"); });
});
}
document.body.style.overflow = "hidden";
var p = lbv.play(); if (p && p.catch) p.catch(function () {});
}
// spinnerul apare la incarcare/buffering si dispare cand curge video-ul
lbv.addEventListener("playing", function () { panel.classList.remove("evs-loading"); });
lbv.addEventListener("canplay", function () { panel.classList.remove("evs-loading"); });
lbv.addEventListener("waiting", function () { panel.classList.add("evs-loading"); });
function close() {
lb.classList.remove("evs-in");
setTimeout(function () { lb.classList.remove("evs-on"); }, 240);
document.body.style.overflow = "";
lbv.pause(); lbv.removeAttribute("src"); lbv.load();
}
x.onclick = close;
pv.onclick = function () { open(cur - 1); };
nx.onclick = function () { open(cur + 1); };
lb.addEventListener("click", function (e) { if (e.target === lb) close(); });
var tX = 0, tY = 0, tOK = false;
panel.addEventListener("touchstart", function (e) {
var t = e.touches[0]; tX = t.clientX; tY = t.clientY;
// bara de controls a video-ului ramane a scrub-ului, nu a gestului
tOK = t.clientY < panel.getBoundingClientRect().bottom - 64;
}, { passive: true });
panel.addEventListener("touchend", function (e) {
if (!tOK) return;
var t = e.changedTouches[0], dx = t.clientX - tX, dy = t.clientY - tY;
if (Math.abs(dx) > 56 && Math.abs(dx) > 2 * Math.abs(dy)) open(cur + (dx < 0 ? 1 : -1));
else if (dy > 80 && Math.abs(dy) > 2 * Math.abs(dx)) close();
}, { passive: true });
addEventListener("keydown", function (e) {
if (!lb.classList.contains("evs-on")) return;
if (e.key === "Escape") close();
if (e.key === "ArrowLeft") open(cur - 1);
if (e.key === "ArrowRight") open(cur + 1);
});
/* Plasare: pe toata latimea, chiar inainte de sectiunea „Produse recomandate".
Daca sectiunea aia nu exista pe pagina, cadem pe locul playlistului. */
var anchor = null;
/* intai sectiunea de carduri "related" (hfHpb--related), oricum s-ar numi titlul;
apoi, ca rezerva, titlul vechi „Produse recomandate” / noul „Din aceeasi categorie” */
var relSec = document.querySelector(".hfHpb--related");
if (relSec) anchor = relSec.closest("section.elementor-section, .e-con") || relSec;
if (!anchor) {
var heads = document.querySelectorAll("h1,h2,h3,h4");
for (var hI = 0; hI < heads.length; hI++) {
if (/produse\s+recomandate|din\s+aceea[sș]i\s+categorie/i.test(heads[hI].textContent)) {
anchor = heads[hI].closest("section.elementor-section, .e-con, section") || heads[hI];
break;
}
}
}
if (anchor && anchor.parentNode) {
anchor.parentNode.insertBefore(wrap, anchor);
} else {
widget.parentNode.insertBefore(wrap, widget);
}
widget.style.display = "none";
arrows();
}
var built = false;
function start() {
if (built) return true;
var widgets = document.querySelectorAll(".elementor-widget-video-playlist");
for (var i = 0; i < widgets.length; i++) {
var V = parseWidget(widgets[i]);
if (V.length) { build(widgets[i], V); built = true; return true; } // un singur rand
}
return false;
}
/* Elementor hidrateaza pagina progresiv, deci widgetul poate aparea (sau primi
data-settings) dupa DOMContentLoaded. Reincercam cu pauze crescatoare. */
function boot() {
if (start()) return;
var delays = [300, 800, 1600, 3000, 5000];
(function tick(k) {
if (k >= delays.length) return;
setTimeout(function () { if (!start()) tick(k + 1); }, delays[k]);
})(0);
}
/* Link discret „sau scrie-ne pe WhatsApp" sub butonul „Adauga in lista".
Doar pe desktop (CSS-ul il ascunde pe mobil, unde exista deja butonul plutitor). */
function addWhatsApp() {
if (document.querySelector(".evs-wa")) return;
var actions = document.querySelector(".co-product-actions");
if (!actions) return;
var a = el("a", "evs-wa");
a.href = "https://wa.me/40722450863";
a.target = "_blank";
a.rel = "noopener";
a.innerHTML = '' +
'sau scrie-ne pe WhatsApp';
actions.insertAdjacentElement("afterend", a);
}
function totul() { addWhatsApp(); boot(); }
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", totul);
} else {
totul();
}
})();