document.addEventListener('DOMContentLoaded', function() { // Elementer for å vise artikler const itavisenArticlesContainer = document.getElementById('itavisen-articles'); const teknoArticlesContainer = document.getElementById('tekno-articles'); // CORS Proxyer for å omgå CORS-begrensninger const corsProxies = [ 'https://corsproxy.io/?', 'https://cors-anywhere.herokuapp.com/', 'https://api.codetabs.com/v1/proxy/?quest=', 'https://api.allorigins.win/raw?url=' ]; let currentProxyIndex = 0; const corsProxy = corsProxies[currentProxyIndex]; // RSS-feed URLs const itavisenRSSUrl = 'https://itavisen.no/feed/'; const teknoRSSUrl = 'https://www.tek.no/feed/'; // Oppdatert til korrekt RSS-feed URL for Tek.no // Vis lasteindikatorer itavisenArticlesContainer.innerHTML = '
Laster inn artikler...
'; teknoArticlesContainer.innerHTML = '
Laster inn artikler...
'; // Funksjon for å hente og parse RSS-feed // Funksjon for å prøve alternative proxyer hvis den første feiler async function fetchWithFallbackProxy(url) { let lastError; // Prøv hver proxy i rekkefølge for (let i = 0; i < corsProxies.length; i++) { try { const proxyUrl = corsProxies[i] + encodeURIComponent(url); console.log(`Forsøker proxy ${i+1}/${corsProxies.length}: ${corsProxies[i]}`); // Legg til timeout for å unngå at forespørselen henger for lenge const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 sekunder timeout const response = await fetch(proxyUrl, { signal: controller.signal }); clearTimeout(timeoutId); // Fjern timeout hvis forespørselen lykkes if (!response.ok) { throw new Error(`HTTP feil! status: ${response.status}`); } const text = await response.text(); // Sjekk om responsen er tom eller ikke inneholder XML if (!text || text.trim() === '') { throw new Error('Mottok tomt dokument fra serveren'); } // Enkel validering for å sjekke om responsen ser ut som XML if (!text.includes('<') || !text.includes('>')) { throw new Error('Responsen ser ikke ut til å være gyldig XML'); } return text; } catch (error) { // Spesifikk håndtering av timeout if (error.name === 'AbortError') { console.warn(`Proxy ${i+1} timeout: Forespørselen tok for lang tid`); lastError = new Error('Timeout - forespørselen tok for lang tid'); } else { console.warn(`Proxy ${i+1} feilet:`, error.message); lastError = error; } // Fortsett til neste proxy } } // Hvis vi kommer hit, har alle proxyer feilet throw new Error(`Alle proxyer feilet. Siste feil: ${lastError.message}`); } async function fetchRSSFeed(url, container) { try { console.log(`Forsøker å hente RSS fra: ${url}`); // Bruk fallback-mekanismen for å hente data const data = await fetchWithFallbackProxy(url); // Sjekk om responsen er tom if (!data || data.trim() === '') { throw new Error('Mottok tomt dokument fra serveren'); } console.log(`Mottatt data lengde: ${data.length} tegn`); // Logg de første 100 tegnene for debugging console.log(`Første 100 tegn av responsen: ${data.substring(0, 100)}...`); const parser = new DOMParser(); const xmlDoc = parser.parseFromString(data, 'text/xml'); // Sjekk om parsing var vellykket const parserError = xmlDoc.querySelector('parsererror'); if (parserError) { console.error('XML parsing feilet, detaljer:', parserError.textContent); console.error('Mottatt XML data:', data.substring(0, 500)); // Logg de første 500 tegnene throw new Error('XML parsing feilet: ' + parserError.textContent); } // Sjekk om dokumentet har root element const rootElement = xmlDoc.documentElement; if (!rootElement || rootElement.nodeName === 'html') { console.error('Ugyldig XML-dokument mottatt:', data.substring(0, 500)); throw new Error('Ugyldig XML-dokument: Mangler root element eller feil format'); } // Hent artikler fra XML const items = xmlDoc.querySelectorAll('item'); // Fjern lasteindikatoren container.innerHTML = ''; // Sjekk om vi har artikler if (items.length === 0) { container.innerHTML = '
Ingen artikler funnet i RSS-feeden.
'; return; } // Begrens til 10 artikler const maxArticles = Math.min(items.length, 10); for (let i = 0; i < maxArticles; i++) { const item = items[i]; // Håndterer CDATA-seksjoner i tittel og beskrivelse let title = item.querySelector('title')?.textContent || 'Ingen tittel'; title = title.replace(/^\s*\s*$/g, ''); // Fjerner CDATA-markører const link = item.querySelector('link')?.textContent || '#'; const pubDate = item.querySelector('pubDate')?.textContent || ''; let description = item.querySelector('description')?.textContent || 'Ingen beskrivelse'; description = description.replace(/^\s*\s*$/g, ''); // Fjerner CDATA-markører // Formater dato const date = pubDate ? new Date(pubDate) : new Date(); const formattedDate = date.toLocaleString('no-NO', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); // Sjekk om artikkelen har et bilde (enclosure) let imageUrl = ''; const enclosure = item.querySelector('enclosure'); if (enclosure && enclosure.getAttribute('url') && enclosure.getAttribute('type')?.startsWith('image/')) { imageUrl = enclosure.getAttribute('url'); } // Opprett artikkel-element const articleElement = document.createElement('div'); articleElement.className = 'article'; // Legg til bilde hvis tilgjengelig let imageHtml = ''; if (imageUrl) { imageHtml = `
${title}
`; } articleElement.innerHTML = `

${title}

${formattedDate}
${imageHtml}
${stripHtml(description).substring(0, 150)}...
`; container.appendChild(articleElement); } } catch (error) { console.error('Feil ved henting av RSS feed:', error); container.innerHTML = `

Kunne ikke laste inn artikler.

Feilmelding: ${error.message}

Prøv å oppdatere siden eller sjekk nettverkstilkoblingen din.

`; // Logg mer detaljert feilinformasjon til konsollen for debugging if (error.stack) { console.error('Stack trace:', error.stack); } } } // Hjelpefunksjon for å fjerne HTML-tags fra tekst function stripHtml(html) { const temp = document.createElement('div'); temp.innerHTML = html; return temp.textContent || temp.innerText || ''; } // Hjelpefunksjon for å forsøke å hente RSS med retry async function fetchWithRetry(url, container, maxRetries = 2) { let retryCount = 0; let lastError; while (retryCount <= maxRetries) { try { if (retryCount > 0) { console.log(`Forsøker på nytt (${retryCount}/${maxRetries}) for ${url}`); // Vis melding om at vi prøver på nytt container.innerHTML = `
Forsøker på nytt (${retryCount}/${maxRetries})...
`; // Vent litt før neste forsøk await new Promise(resolve => setTimeout(resolve, 1500)); } await fetchRSSFeed(url, container); return; // Vellykket, avslutt retry-løkken } catch (error) { lastError = error; console.warn(`Forsøk ${retryCount + 1}/${maxRetries + 1} feilet for ${url}:`, error.message); retryCount++; } } // Hvis vi kommer hit, har alle forsøk feilet console.error(`Alle forsøk feilet for ${url}:`, lastError); container.innerHTML = `

Kunne ikke laste inn artikler etter flere forsøk.

Feilmelding: ${lastError.message}

Prøv å oppdatere siden eller sjekk nettverkstilkoblingen din.

`; } // Hent artikler fra begge kilder med retry-mekanisme fetchWithRetry(itavisenRSSUrl, itavisenArticlesContainer); fetchWithRetry(teknoRSSUrl, teknoArticlesContainer); // Legg til knapp for å oppdatere feeds const header = document.querySelector('header'); const refreshButton = document.createElement('button'); refreshButton.textContent = 'Oppdater nyheter'; refreshButton.className = 'refresh-button'; refreshButton.addEventListener('click', function() { // Vis lasteindikatorer igjen itavisenArticlesContainer.innerHTML = '
Laster inn artikler...
'; teknoArticlesContainer.innerHTML = '
Laster inn artikler...
'; // Hent artikler på nytt fetchRSSFeed(itavisenRSSUrl, itavisenArticlesContainer); fetchRSSFeed(teknoRSSUrl, teknoArticlesContainer); }); header.appendChild(refreshButton); // Legg til stil for oppdateringsknappen const style = document.createElement('style'); style.textContent = ` .refresh-button { background-color: #3498db; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; font-size: 14px; margin-top: 15px; transition: background-color 0.3s; } .refresh-button:hover { background-color: #2980b9; } `; document.head.appendChild(style); });