diff --git a/.DS_Store b/.DS_Store index f30f425..ca9a239 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/test/script.js b/test/script.js new file mode 100644 index 0000000..ce6c585 --- /dev/null +++ b/test/script.js @@ -0,0 +1,272 @@ +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); +});