General

Artículos sobre General relacionados con Todos Sobre Tus Mascotas.

← Ver todas las categorías

document.addEventListener('DOMContentLoaded', function() { // ✅ NUEVO: Scroll suave para enlaces del índice const tocLinks = document.querySelectorAll('.toc-link'); tocLinks.forEach(link => { link.addEventListener('click', function(e) { const href = this.getAttribute('href'); if (href && href.startsWith('#')) { const targetId = href.substring(1); const targetElement = document.getElementById(targetId); if (targetElement) { e.preventDefault(); const offsetTop = targetElement.offsetTop - 20; // Compensar header si existe window.scrollTo({ top: offsetTop, behavior: 'smooth' }); } } }); }); // ✅ NUEVO: Actualización dinámica de imágenes sin deploy function updateImages() { const articleImages = document.querySelectorAll('img[data-article-slug]'); if (articleImages.length === 0) return; // Obtener dominio actual (del atributo data-site-domain o window.location) const getDomain = () => { const firstImage = articleImages[0]; const dataDomain = firstImage ? firstImage.getAttribute('data-site-domain') : null; if (dataDomain && dataDomain.trim() !== '') { // Limpiar dominio (remover http://, https://, www.) let cleanDomain = dataDomain.trim(); if (cleanDomain.startsWith('http://')) { cleanDomain = cleanDomain.substring(7); } else if (cleanDomain.startsWith('https://')) { cleanDomain = cleanDomain.substring(8); } if (cleanDomain.startsWith('www.')) { cleanDomain = cleanDomain.substring(4); } return cleanDomain.split('/')[0]; } // Fallback: usar hostname actual return window.location.hostname; }; const domain = getDomain(); // Función para actualizar imagen async function updateArticleImage(img) { const slug = img.getAttribute('data-article-slug'); if (!slug || !domain) return; // Evitar actualizar si ya se actualizó recientemente if (img.dataset.updated === 'true') return; try { const functionUrl = 'https://us-central1-ia-autoblog-factory.cloudfunctions.net/getArticleImageBySlug'; const response = await fetch(functionUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain, slug }) }); if (!response.ok) { throw new Error('HTTP ' + response.status); } const data = await response.json(); if (data.success && data.imageUrl && data.imageUrl.trim() !== '') { if (data.imageUrl !== img.src) { // Solo actualizar si la nueva URL es diferente y válida img.src = data.imageUrl; img.dataset.updated = 'true'; // Mostrar imagen cuando cargue img.onload = function() { img.classList.add('article-image-verified'); img.style.visibility = ''; // Remover inline style para que el CSS funcione img.style.opacity = ''; // Remover inline style para que el CSS funcione }; console.log('Imagen actualizada dinamicamente: ' + slug); } else { // Imagen coincide, mostrarla inmediatamente img.classList.add('article-image-verified'); img.style.visibility = ''; // Remover inline style para que el CSS funcione img.style.opacity = ''; // Remover inline style para que el CSS funcione } } else { // Si no hay imagen en BD pero hay imagen hardcodeada, mostrarla de todas formas img.classList.add('article-image-verified'); img.style.visibility = ''; // Remover inline style para que el CSS funcione img.style.opacity = ''; // Remover inline style para que el CSS funcione } } catch (error) { // Fallback silencioso - mantener imagen original y mostrarla img.classList.add('article-image-verified'); img.style.visibility = ''; // Remover inline style para que el CSS funcione img.style.opacity = ''; // Remover inline style para que el CSS funcione console.log('No se pudo actualizar imagen dinamicamente (usando imagen original): ' + slug); } } // Actualizar todas las imágenes articleImages.forEach(updateArticleImage); } // ✅ NUEVO: Actualización dinámica de color sin deploy function updateSiteColor() { const colorContainer = document.querySelector('[data-site-color]'); if (!colorContainer) return; const domain = colorContainer.getAttribute('data-site-domain') || window.location.hostname; let cleanDomain = domain.trim(); if (cleanDomain.startsWith('http://')) { cleanDomain = cleanDomain.substring(7); } else if (cleanDomain.startsWith('https://')) { cleanDomain = cleanDomain.substring(8); } if (cleanDomain.startsWith('www.')) { cleanDomain = cleanDomain.substring(4); } cleanDomain = cleanDomain.split('/')[0]; fetch('https://us-central1-ia-autoblog-factory.cloudfunctions.net/getSiteColorByDomain', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: cleanDomain }) }) .then(r => r.json()) .then(data => { if (data.success && data.color) { // Actualizar todos los elementos que usan el color const style = document.createElement('style'); style.id = 'dynamic-site-color'; style.textContent = 'footer { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '.main-header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '#header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + 'body #header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '.main-header #header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + 'header #header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '.read-more { background-color: ' + data.color + ' !important; color: #fff !important; } ' + '.schema-nav-burger .schema-nav-burger-lines span { background: #ffffff !important; }'; // Remover estilo anterior si existe const oldStyle = document.getElementById('dynamic-site-color'); if (oldStyle) oldStyle.remove(); document.head.appendChild(style); } }) .catch(err => console.log('No se pudo actualizar color dinamicamente')); } // ✅ NUEVO: Actualización dinámica de logo sin deploy (igual que imágenes de artículos) function updateSiteLogo() { // Buscar logo por atributo data-site-logo o por clase .site-logo let logoImg = document.querySelector('img[data-site-logo]'); if (!logoImg) { // Fallback: buscar por clase si no tiene atributo data- logoImg = document.querySelector('img.site-logo'); } // Si no hay logo de imagen, buscar logo de texto (#logo puede ser h1 o h2) let logoTextElement = null; if (!logoImg) { logoTextElement = document.querySelector('#logo'); // Verificar que sea un elemento de texto (h1, h2) y no un link con imagen if (logoTextElement && (logoTextElement.tagName === 'H1' || logoTextElement.tagName === 'H2')) { // OK, es un logo de texto que podemos reemplazar } else { logoTextElement = null; } } // Si no hay ni logo de imagen ni logo de texto, no podemos hacer nada if (!logoImg && !logoTextElement) return; // Obtener dominio del atributo data-site-domain, contenedor de color, o hostname let domain = null; if (logoImg) { domain = logoImg.getAttribute('data-site-domain'); } if (!domain) { const colorContainer = document.querySelector('[data-site-color]'); domain = colorContainer ? colorContainer.getAttribute('data-site-domain') : window.location.hostname; } let cleanDomain = domain.trim(); if (cleanDomain.startsWith('http://')) { cleanDomain = cleanDomain.substring(7); } else if (cleanDomain.startsWith('https://')) { cleanDomain = cleanDomain.substring(8); } if (cleanDomain.startsWith('www.')) { cleanDomain = cleanDomain.substring(4); } cleanDomain = cleanDomain.split('/')[0]; fetch('https://us-central1-ia-autoblog-factory.cloudfunctions.net/getSiteLogoByDomain', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: cleanDomain }) }) .then(r => r.json()) .then(data => { if (data.success && data.logo && data.logo.trim() !== '') { if (logoImg) { // Ya hay logo de imagen, solo actualizar si es diferente if (data.logo !== logoImg.src) { logoImg.src = data.logo; console.log('Logo actualizado dinamicamente:', data.logo); } } else if (logoTextElement) { // No hay logo de imagen, pero hay logo de texto - crear logo de imagen const niche = logoTextElement.textContent.trim() || 'Mi Sitio'; const logoLink = document.createElement('a'); logoLink.href = '/'; logoLink.id = 'logo'; logoLink.className = 'logo-image-link'; const newLogoImg = document.createElement('img'); newLogoImg.src = data.logo; newLogoImg.alt = niche; newLogoImg.className = 'site-logo'; newLogoImg.setAttribute('data-site-logo', 'true'); newLogoImg.setAttribute('data-site-domain', cleanDomain); logoLink.appendChild(newLogoImg); // Reemplazar el elemento de texto con el nuevo logo const logoWrap = logoTextElement.parentElement; if (logoWrap && logoWrap.classList.contains('logo-wrap')) { logoWrap.replaceChild(logoLink, logoTextElement); console.log('Logo creado dinamicamente desde texto:', data.logo); } } } }) .catch(err => console.log('No se pudo actualizar logo dinamicamente (usando logo original)')); } // Ejecutar inmediatamente (ya estamos dentro de DOMContentLoaded) updateImages(); updateSiteColor(); updateSiteLogo(); // También ejecutar después de un delay para asegurar que todas las imágenes estén cargadas setTimeout(() => { updateImages(); updateSiteColor(); updateSiteLogo(); }, 1000); }); // ✅ CORRECCIÓN: Ejecutar updateSiteColor() inmediatamente ANTES de DOMContentLoaded para evitar parpadeo // Esto aplica el color dinámico antes de que se renderice el CSS hardcodeado (function() { function updateSiteColorImmediate() { const colorContainer = document.querySelector('[data-site-color]'); if (!colorContainer) return; const domain = colorContainer.getAttribute('data-site-domain') || window.location.hostname; let cleanDomain = domain.trim(); if (cleanDomain.startsWith('http://')) { cleanDomain = cleanDomain.substring(7); } else if (cleanDomain.startsWith('https://')) { cleanDomain = cleanDomain.substring(8); } if (cleanDomain.startsWith('www.')) { cleanDomain = cleanDomain.substring(4); } cleanDomain = cleanDomain.split('/')[0]; fetch('https://us-central1-ia-autoblog-factory.cloudfunctions.net/getSiteColorByDomain', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: cleanDomain }) }) .then(r => r.json()) .then(data => { if (data.success && data.color) { const style = document.createElement('style'); style.id = 'dynamic-site-color-immediate'; style.textContent = 'footer { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '.main-header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '#header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + 'body #header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '.main-header #header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + 'header #header { background: ' + data.color + ' !important; background-color: ' + data.color + ' !important; } ' + '.read-more { background-color: ' + data.color + ' !important; color: #fff !important; } ' + '.schema-nav-burger .schema-nav-burger-lines span { background: #ffffff !important; }'; const oldStyle = document.getElementById('dynamic-site-color-immediate'); if (oldStyle) oldStyle.remove(); document.head.appendChild(style); } }) .catch(err => {}); } // Ejecutar inmediatamente si el DOM ya está listo if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', updateSiteColorImmediate); } else { updateSiteColorImmediate(); } })();