/* 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(); } })();