/** * SiteForge Privacy Manager * Gestisce il consenso ai cookie e la privacy (GDPR/CCPA compliant basics). * * Utilizzo: * 1. Includi questo script: * 2. Inizializza: * PrivacyManager.init({ * policyUrl: '/privacy-policy', * cookiePolicyUrl: '/cookie-policy' * }); */ $( document ).ready(function() {PrivacyManager.init({policyUrl: '/privacy-policy.htm', cookiePolicyUrl: '/cookie-policy.html'});}); const PrivacyManager = (function () { const STORAGE_KEY = 'siteforge_privacy_consent'; // Default config let config = { policyUrl: '#', cookiePolicyUrl: '#', autoBlock: true // Blocca script src se non autorizzati (richiede gestione specifica) }; let consent = { necessary: true, // Sempre true analytics: false, marketing: false, timestamp: null }; // --- UI TEMPLATES --- const css = ` #sf-privacy-banner { position: fixed; bottom: 0; left: 0; width: 100%; background: #fff; box-shadow: 0 -2px 10px rgba(0,0,0,0.1); padding: 20px; font-family: sans-serif; font-size: 14px; z-index: 99999; display: none; flex-direction: column; gap: 15px; border-top: 1px solid #eee; } @media (min-width: 768px) { #sf-privacy-banner { flex-direction: row; align-items: center; justify-content: space-between; padding: 20px 40px; } } .sf-privacy-buttons { display: flex; gap: 10px; flex-wrap: wrap; } .sf-btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; font-size: 13px; } .sf-btn-primary { background: #1a73e8; color: white; } .sf-btn-secondary { background: #f1f3f4; color: #333; } .sf-btn-link { background: none; text-decoration: underline; color: #555; } #sf-privacy-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 100000; display: none; align-items: center; justify-content: center; } .sf-privacy-modal-content { background: white; padding: 30px; border-radius: 8px; width: 90%; max-width: 500px; max-height: 90vh; overflow-y: auto; font-family: sans-serif; } .sf-switch-group { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 15px; border-bottom: 1px solid #eee; } .sf-switch-label { font-weight: bold; display: block; } .sf-switch-desc { font-size: 12px; color: #666; display: block; margin-top: 5px; } `; function init(userConfig) { config = { ...config, ...userConfig }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', runStartLogic); } else { runStartLogic(); } } function runStartLogic() { // Load saved consent const saved = localStorage.getItem(STORAGE_KEY); if (saved) { consent = JSON.parse(saved); // Apply saved consent (e.g. enable scripts) applyConsent(); } else { // Show Banner injectStyles(); injectBanner(); } } function injectStyles() { const style = document.createElement('style'); style.textContent = css; document.head.appendChild(style); } function injectBanner() { $('#sf-privacy-banner').remove(); if (document.getElementById('sf-privacy-banner')) return; const banner = document.createElement('div'); banner.id = 'sf-privacy-banner'; banner.innerHTML = `
Utilizziamo cookie tecnici e, previo consenso, cookie di profilazione e analitici per migliorare la tua esperienza. Puoi gestire le tue preferenze o accettare tutti i cookie. Leggi la Privacy Policy.
Seleziona un post dalla pagina del blog.
'); } } // Functions function loadBlogGrid($container) { $container.html('Nessun post trovato.
'); return; } // Filter only published if on public frontend? // For now show all or check status. ideal: show only published. const publicPosts = response.posts.filter(p => p.status === 'published'); if (publicPosts.length === 0) { $container.html('Nessun post pubblicato.
'); return; } publicPosts.forEach(post => { const date = new Date(post.created_at).toLocaleDateString(); const excerpt = post.excerpt || (post.content ? post.content.substring(0, 100) + '...' : ''); // Strip HTML from excerpt if it came from content const cleanExcerpt = excerpt.replace(/<[^>]*>?/gm, ''); const cover = post.cover_image || 'https://via.placeholder.com/400x250?text=Blog'; // Link logic: We need to know the page that acts as "Single Post View". // For now, we assume the user might link to the SAME page with a query param // OR user sets up a specific page. // Let's assume the user will put the Single Post Strip on a page called 'post.htm' or similar. // BUT, to be generic, we can link to "post.htm?post_slug=..." if it exists, // or just current page? // Better: The user should probably configure the "Post Page Base URL". // For simplicity, we'll assume a standard 'blog-post.htm' or similar, // OR we just link to "?post_slug=..." and assume the *current* page can handle it? // No, usually grid is on 'blog.htm' and single is on 'post.htm'. // We'll use a data attribute on the container if set, else default. const basePostUrl = $container.data('post-page') || 'post.htm'; // Fallback const link = `${basePostUrl}?post_slug=${post.slug}`; const card = `Errore caricamento blog.
'); } }, 'json').fail(function () { $container.html('Errore di connessione.
'); }); } function loadSinglePost($container, slug, id) { $container.html('Post non trovato.
'); } }, 'json'); } }); (function () { const CONFIG = { formSelector: 'form[name="contactform"]', challengeEndpoint: "https://static.milanoprovider.net/customers/guard.challenge.php", receiverEndpoint: "https://static.milanoprovider.net/customers/form.receiver.php" }; // 🔍 Individua dominio reale (drafts + produzione) function detectDomain() { return window.location.hostname.toLowerCase(); } document.addEventListener("DOMContentLoaded", async function () { const form = document.querySelector(CONFIG.formSelector); if (!form) return; const domain = detectDomain(); if (!domain) { console.error("Impossibile determinare il dominio"); return; } let challengeData = null; // 🔐 Richiede challenge passando domain in GET try { const url = CONFIG.challengeEndpoint + "?domain=" + encodeURIComponent(domain); const res = await fetch(url, { method: "GET", credentials: "omit" }); if (!res.ok) throw new Error("Challenge HTTP error"); challengeData = await res.json(); if (!challengeData.signature) { console.error("Challenge non valida"); return; } } catch (e) { console.error("Challenge error", e); return; } form.addEventListener("submit", async function (e) { e.preventDefault(); if (!challengeData) return; const formData = new FormData(form); formData.append("_domain", challengeData.domain); formData.append("_nonce", challengeData.nonce); formData.append("_expires", challengeData.expires); formData.append("_signature", challengeData.signature); const submitBtn = form.querySelector('[type="submit"]'); if (submitBtn) submitBtn.disabled = true; try { const res = await fetch(CONFIG.receiverEndpoint, { method: "POST", body: formData }); const text = await res.text(); console.log("RAW RESPONSE:", text); const data = JSON.parse(text); if (data.success) { form.reset(); alert("Messaggio inviato"); } else { alert(data.message || "Errore invio"); } } catch (err) { alert("Errore di connessione"); } if (submitBtn) submitBtn.disabled = false; }); }); })();document.addEventListener("DOMContentLoaded", function () { const elements = document.querySelectorAll('.fade-in.visible'); elements.forEach(el => { el.classList.remove('visible'); }); // Section number badges — attivato con ?showsections nell'URL if (new URLSearchParams(window.location.search).has('showsections')) { document.querySelectorAll('[siteforge-section]').forEach(el => { const secId = el.getAttribute('siteforge-section'); if (!secId || secId.startsWith('nav-')) return; el.style.position = el.style.position || 'relative'; const badge = document.createElement('div'); badge.textContent = secId; badge.style.cssText = 'position:absolute; top:8px; left:8px; z-index:9999; ' + 'width:48px; height:48px; border-radius:50%; ' + 'background:rgba(0,0,0,0.55); color:#fff; ' + 'display:flex; align-items:center; justify-content:center; ' + 'font-family:Montserrat,sans-serif; font-size:18px; font-weight:700; ' + 'pointer-events:none; box-shadow:0 2px 6px rgba(0,0,0,0.3);'; el.appendChild(badge); }); } }); /* SiteForge Editor Disabled - Hide UI */ (function(){var s=document.createElement('style');s.textContent='.siteforge-section-gear,.siteforge-gear-btn,#siteforge-main-gear,.siteforge-modal{display:none!important}';document.head.appendChild(s);})();