---
canonical_url: "https://lmdiario.com.ar/contenido/520688/agenda-cultural-widget-portada-01"
title: "Agenda Cultural - Widget Portada_01"
page_type: "WebPage"
date_modified: "2026-06-29T18:04:42-03:00"
---

# Agenda Cultural - Widget Portada_01

CONTENEDOR PRINCIPAL

CABECERA SIMPLE COMPACTA

Cargando semana...

Controles de Navegación del Carrusel

Botón Acción Principal (Abriendo en la misma página)

[Ver más eventos](https://lmdiario.com.ar/contenido/520514/agenda-cultural-y-eventos-03)

CONTENEDOR DEL CARRUSEL

Sincronizando sumario...

FILA INDICADORA (PUNTOS DE PAGINACIÓN)

FICHA POP-UP (MODAL)

![Portada noticia](https://)

## Título de la Noticia

Redacción LMDiario

Descripción del XML

Botón de acción del modal (Abriendo en la misma página)

[Leer Nota Completa](#)

========================================================================== LÓGICA JAVASCRIPT EXCLUSIVA, OPTIMIZADA Y AUTÓNOMA ==========================================================================

document.addEventListener("DOMContentLoaded", () => { // CONFIGURACIONES GENERALES const RSS_URL = 'https://lmdiario.com.ar/rss/categoria/cultura.xml'; const REFRESH_RATE = 5 * 60 * 1000; // Sincronización automática de feed cada 5 minutos const MAX_VISIBLE_ITEMS = 7; // Límite de noticias visibles estipuladas ampliado a 7 // ESTADO DE NAVEGACIÓN Y CARRUSEL let newsData = []; let currentWeekStartDate = null; let currentCarouselIndex = 0; let touchStartX = 0; let touchEndX = 0; // ELEMENTOS DEL DOM const weekIndicator = document.getElementById('week-date-indicator'); const carouselTrack = document.getElementById('carousel-track'); const carouselDotsContainer = document.getElementById('carousel-dots'); const btnPrev = document.getElementById('btn-prev'); const btnNext = document.getElementById('btn-next'); // Modal const modal = document.getElementById('news-modal'); const btnCloseModal = document.getElementById('btn-close-modal'); // --------------------------------------------------------- // INICIALIZACIÓN // --------------------------------------------------------- initReader(); setInterval(initReader, REFRESH_RATE); // Escuchar cambios de tamaño para recalcular slides de carrusel window.addEventListener('resize', () => { updateCarouselPosition(); renderDots(); }); // Controles del Carrusel (Avanzar/Retroceder de a una tarjeta) btnPrev.addEventListener('click', () => { if (currentCarouselIndex > 0) { currentCarouselIndex--; updateCarouselPosition(); } }); btnNext.addEventListener('click', () => { const visibleCards = getVisibleCardsCount(); if (currentCarouselIndex < newsData.length - visibleCards) { currentCarouselIndex++; updateCarouselPosition(); } }); // Soporte Swipe en Móvil const viewport = document.getElementById('carousel-viewport'); viewport.addEventListener('touchstart', (e) => { touchStartX = e.changedTouches[0].screenX; }, { passive: true }); viewport.addEventListener('touchend', (e) => { touchEndX = e.changedTouches[0].screenX; handleSwipe(); }, { passive: true }); // Eventos de Modal btnCloseModal.addEventListener('click', closeModal); modal.addEventListener('click', (e) => { if(e.target === modal) closeModal(); }); // --------------------------------------------------------- // SENSOR DE GESTOS TÁCTILES // --------------------------------------------------------- function handleSwipe() { const threshold = 50; if (touchStartX - touchEndX > threshold) { // Deslizar izquierda -> Siguiente const visibleCards = getVisibleCardsCount(); if (currentCarouselIndex < newsData.length - visibleCards) { currentCarouselIndex++; updateCarouselPosition(); } } else if (touchEndX - touchStartX > threshold) { // Deslizar derecha -> Anterior if (currentCarouselIndex > 0) { currentCarouselIndex--; updateCarouselPosition(); } } } // --------------------------------------------------------- // LECTURA DE RSS (ADAPTADO MISMO DOMINIO) // --------------------------------------------------------- async function initReader() { try { const fetchOptions = { method: 'GET', cache: 'no-cache' }; const response = await fetch(RSS_URL, fetchOptions); if (!response.ok) { throw new Error(`HTTP Error: ${response.status}`); } const xmlString = await response.text(); processXML(xmlString); } catch (error) { console.warn("Lector RSS: Error de lectura.", error); showEmptyMessage(); } } // --------------------------------------------------------- // PROCESAMIENTO ROBUSTO DEL XML Y SISTEMA FALLBACK CORREGIDO // --------------------------------------------------------- function processXML(xmlString) { const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlString, "text/xml"); const items = xmlDoc.querySelectorAll("item"); let parsedData = []; items.forEach((item, index) => { const titleNode = item.querySelector("title"); const linkNode = item.querySelector("link"); const descNode = item.querySelector("description"); const pubDateNode = item.querySelector("pubDate"); const title = titleNode ? titleNode.textContent : "Sin título"; const link = linkNode ? linkNode.textContent : "#"; const description = descNode ? descNode.textContent : ""; const pubDateStr = pubDateNode ? pubDateNode.textContent : new Date().toUTCString(); // Extracción inteligente de portada let imageUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiNlOGU2ZTMiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjQiIGZpbGw9IiM3YTc3NzMiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGR5PSIuM2VtIj5TaW4gaW1hZ2VuPC90ZXh0Pjwvc3ZnPg=='; const enclosure = item.querySelector("enclosure"); if (enclosure && enclosure.getAttribute("url")) { imageUrl = enclosure.getAttribute("url"); } else { const imgRegex = /<img[^>]+src="([^">]+)"/i; const match = description.match(imgRegex); if (match && match[1]) { imageUrl = match[1]; } } let cleanDesc = description.replace(/<img[^>]*>/gi, ""); const pubDate = new Date(pubDateStr); parsedData.push({ id: index, title: title, link: link, description: cleanDesc, imageUrl: imageUrl, dateObj: pubDate, dayAndMonth: getDayAndMonthStr(pubDate), dateWorded: formatDateToWords(pubDate) }); }); // Ordenar por fecha decreciente (más recientes primero) // Se añade validación robusta para evitar fallos si hay fechas NaN parsedData.sort((a, b) => { const timeA = isNaN(a.dateObj.getTime()) ? 0 : a.dateObj.getTime(); const timeB = isNaN(b.dateObj.getTime()) ? 0 : b.dateObj.getTime(); return timeB - timeA; }); if (parsedData.length === 0) { showEmptyMessage(); return; } // Obtener fecha del Lunes de la semana actual REAL del calendario const today = new Date(); currentWeekStartDate = getMonday(today); let mondayRange = new Date(currentWeekStartDate).setHours(0,0,0,0); let sundayRange = new Date(currentWeekStartDate); sundayRange.setDate(sundayRange.getDate() + 6); let sundayRangeTime = sundayRange.setHours(23,59,59,999); // Filtrar las noticias que corresponden a esta semana actual let filteredItems = parsedData.filter(item => { const t = item.dateObj.getTime(); return t >= mondayRange && t <= sundayRangeTime; }); // ========================================================= // SCRIPT DEL FALLBACK (FLEXIBLE: EVITA TARJETAS VACÍAS LOS LUNES) // ========================================================= // Si la semana actual NO tiene 7 noticias (por ejemplo, los lunes/martes), // se suprime el límite estricto y se recuperan las 7 más recientes de todo el feed // para garantizar que el widget SIEMPRE tenga contenido al 100%. if (filteredItems.length < MAX_VISIBLE_ITEMS) { filteredItems = parsedData.slice(0, MAX_VISIBLE_ITEMS); // Ajustamos el "reloj" de la cabecera a la semana del artículo más reciente recuperado if (filteredItems.length > 0) { currentWeekStartDate = getMonday(filteredItems[0].dateObj); } } else { filteredItems = filteredItems.slice(0, MAX_VISIBLE_ITEMS); } // ========================================================= newsData = filteredItems; currentCarouselIndex = 0; // Reiniciar posición de carrusel // Actualizar cabecera con el rango de fechas de la semana mostrada const sunday = new Date(currentWeekStartDate); sunday.setDate(currentWeekStartDate.getDate() + 6); const monthNames = ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"]; // Aplicando formato estricto: "Semana del [día] de [mes] al [día] de [mes]" const startDay = currentWeekStartDate.getDate(); const startMonth = monthNames[currentWeekStartDate.getMonth()]; const endDay = sunday.getDate(); const endMonth = monthNames[sunday.getMonth()]; weekIndicator.textContent = `Semana del ${startDay} de ${startMonth} al ${endDay} de ${endMonth}`; renderCarousel(); } // --------------------------------------------------------- // RENDERIZADO DEL CARRUSEL // --------------------------------------------------------- function renderCarousel() { carouselTrack.innerHTML = ''; if (newsData.length === 0) { showEmptyMessage(); return; } newsData.forEach(item => { const card = createNewsCard(item); carouselTrack.appendChild(card); }); updateCarouselPosition(); renderDots(); } function createNewsCard(item) { const card = document.createElement('article'); card.className = 'news-card'; // Enlaces modificados a target="_self" para abrir en la misma pestaña card.innerHTML = ` <div class="card-img-wrap"> <div class="card-date-badge"> <svg width="12" height="12" fill="#ff5a1f" viewBox="0 0 16 16"><path d="M11 6.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-1zM11 9.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-1zM3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM2 2a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H2z"/></svg> <span>${item.dayAndMonth}</span> </div> <img src="${item.imageUrl}" alt="Portada" loading="lazy"> </div> <div class="card-content"> <h3 class="card-title">${item.title}</h3> <div class="card-footer"> <a href="${item.link}" target="_self" class="card-link-btn" onclick="event.stopPropagation()"> Leer original <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/></svg> </a> </div> </div> `; card.addEventListener('click', () => openModal(item)); return card; } function getVisibleCardsCount() { const width = window.innerWidth; if (width <= 650) return 1; if (width <= 1024) return 2; return 3; } function updateCarouselPosition() { if (newsData.length === 0) return; const visibleCards = getVisibleCardsCount(); // Asegurar que el index está en el rango correcto if (currentCarouselIndex > newsData.length - visibleCards) { currentCarouselIndex = Math.max(0, newsData.length - visibleCards); } // Calcular ancho de tarjetas más brecha de 20px const cardNode = carouselTrack.querySelector('.news-card'); if (cardNode) { const cardWidth = cardNode.getBoundingClientRect().width; const offset = currentCarouselIndex * (cardWidth + 20); carouselTrack.style.transform = `translateX(-${offset}px)`; } // Actualizar estado de botones btnPrev.disabled = (currentCarouselIndex === 0); btnNext.disabled = (currentCarouselIndex >= newsData.length - visibleCards); // Sincronizar dots const dots = carouselDotsContainer.querySelectorAll('.dot'); dots.forEach((dot, idx) => { if (idx === currentCarouselIndex) { dot.classList.add('active'); } else { dot.classList.remove('active'); } }); } function renderDots() { carouselDotsContainer.innerHTML = ''; const visibleCards = getVisibleCardsCount(); const totalDots = Math.max(0, newsData.length - visibleCards + 1); // Si todos caben en pantalla, no necesitamos puntos if (totalDots <= 1) return; for (let i = 0; i < totalDots; i++) { const dot = document.createElement('div'); dot.className = 'dot'; if (i === currentCarouselIndex) dot.classList.add('active'); dot.addEventListener('click', () => { currentCarouselIndex = i; updateCarouselPosition(); }); carouselDotsContainer.appendChild(dot); } } function showEmptyMessage() { weekIndicator.textContent = "Sin noticias esta semana"; carouselTrack.innerHTML = ` <div style="width:100%; text-align: center; padding: 60px 20px; color: var(--text-muted); font-size: 1.1rem; font-weight: 500;"> No se encontraron publicaciones.<br> <span style="font-size:0.95rem; font-weight:normal;">Sincronizando de nuevo pronto...</span> </div> `; btnPrev.disabled = true; btnNext.disabled = true; carouselDotsContainer.innerHTML = ''; } // --------------------------------------------------------- // OPERACIONES DE MODAL / POP-UP // --------------------------------------------------------- function openModal(item) { document.getElementById('modal-img').src = item.imageUrl; document.getElementById('modal-title').textContent = item.title; document.getElementById('modal-date').textContent = item.dateWorded; document.getElementById('modal-description').innerHTML = item.description; document.getElementById('modal-link').href = item.link; modal.classList.add('active'); document.body.style.overflow = 'hidden'; } function closeModal() { modal.classList.remove('active'); document.body.style.overflow = ''; setTimeout(() => { document.getElementById('modal-img').src = ''; document.getElementById('modal-description').innerHTML = ''; }, 300); } // --------------------------------------------------------- // UTILERÍAS DE FECHAS Y TEXTO // --------------------------------------------------------- function getMonday(d) { d = new Date(d); const day = d.getDay(); const diff = d.getDate() - day + (day === 0 ? -6 : 1); return new Date(d.setDate(diff)); } function getDayAndMonthStr(date) { if (isNaN(date)) return "-"; const monthsShort = ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]; return `${date.getDate()} ${monthsShort[date.getMonth()]}`; } function formatDateToWords(date) { if (isNaN(date)) return "Fecha desconocida"; const daysLong = ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"]; const monthsLong = ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"]; return `${daysLong[date.getDay()]}, ${date.getDate()} de ${monthsLong[date.getMonth()]} de ${date.getFullYear()}`; } });

---

*Contenido creado y optimizado para IA con [Medios CMS](https://medios.io)* — Plataforma profesional para la gestión de medios digitales y portales de noticias.
