function setCookie(name, value, days) { let expires = ""; if (days) { const date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + encodeURIComponent(value) + expires + "; path=/"; const zipInput = document.getElementById("form-field-zipcode"); const button = document.getElementById("form-button-search"); if ( zipInput && button ){ const buttonText = button.querySelector("span > span:last-child"); function updateButtonText( place ){ if ( buttonText ){ buttonText.innerHTML = place ? "Finn leverandør i " + place : "Finn leverandør"; } } function handleZipInput( rawZip ){ const zip = rawZip.replace( /\D/g, '' ); if ( zip === "" ){ updateButtonText(""); return; } if ( /^\d{4}$/.test( zip ) ){ fetch(`https://io.trebeste.no/zipcode2place?zip=${zip}`) .then( r => { if ( !r.ok ) throw new Error("Ikke funnet"); return r.json(); }) .then( data => { const city = data?.place || ''; updateButtonText( city ); }) .catch( () => { updateButtonText(""); }); } else { updateButtonText(""); } } ["input", "paste"].forEach( ev => { zipInput.addEventListener( ev, () => { setTimeout( () => handleZipInput( zipInput.value.trim() ), 0 ); }); }); setTimeout( () => handleZipInput( zipInput.value.trim() ), 90 ); } } function getCookie(name) { const nameEQ = name + "="; const ca = document.cookie.split(';'); for (let i = 0; i < ca.length; i++) { let c = ca[i].trim(); if (c.indexOf(nameEQ) === 0) { return decodeURIComponent(c.substring(nameEQ.length)); } } return null; } function getSrcQueryParam( key ) { const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const srcValue = urlParams.get( key ); return srcValue; } function showResponseMessage(message, status) { // Opprett overlay-elementet const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.3)'; // Semi-transparent black overlay.style.zIndex = '1049'; // Below the message document.body.appendChild(overlay); // Opprett div-elementet for meldingen const responseDiv = document.createElement('div'); responseDiv.style.position = 'fixed'; responseDiv.style.top = '50%'; responseDiv.style.left = '50%'; responseDiv.style.transform = 'translate(-50%, -50%)'; responseDiv.style.backgroundColor = status === 'success' ? '#4CAF50' : '#f44336'; responseDiv.style.color = 'white'; responseDiv.style.padding = '15px'; responseDiv.style.borderRadius = '3px'; responseDiv.style.zIndex = '1050'; // Above the overlay responseDiv.style.maxWidth = '90vw'; responseDiv.style.width = '380px'; responseDiv.style.cursor = 'pointer'; responseDiv.style.textAlign = 'center'; responseDiv.style.boxShadow = '0 2px 5px rgba(0, 0, 0, 0.2)'; responseDiv.style.border = '1px solid #ccc'; responseDiv.innerHTML = message; document.body.appendChild(responseDiv); function removeResponseDivAndOverlay() { if (responseDiv && responseDiv.parentNode) { responseDiv.parentNode.removeChild(responseDiv); } if (overlay && overlay.parentNode) { overlay.parentNode.removeChild(overlay); } } // Close on click of the message div or the overlay responseDiv.addEventListener('click', removeResponseDivAndOverlay); overlay.addEventListener('click', removeResponseDivAndOverlay); setTimeout(removeResponseDivAndOverlay, 8000); } function closeForm( formId ) { console.log( 'formID', formId ); const formHandle = document.getElementById( formId ); if (formHandle) { formHandle.remove(); document.body.style.overflow = 'auto'; } } function handleQuery(query, rawZipcode) { const zipcode = rawZipcode.replace( /\D/g, '' ); const resultBox = document.getElementById('query_result'); if (resultBox) console.log('Henter resultater... (' + new Date().toLocaleString() + ')'); const queryInput = document.getElementById("form-field-query"); const zipcodeInput = document.getElementById("form-field-zipcode"); const submitBtn = document.getElementById("form-button-search"); const suggestionBox = document.getElementById("suggestion_wrapper"); const suggestionIconBox = document.getElementById("suggestion_icon_wrapper"); const instructions = document.getElementById("instructions"); const header = document.getElementById("header"); const title = document.getElementById("title"); const parent = queryInput.parentElement; // Oppdater URL og lagre i cookie setCookie("last_query", query, 90); setCookie("last_zip", zipcode, 90); fetch(`https://io.trebeste.no/search/?query=${encodeURIComponent(query)}&zipcode=${encodeURIComponent(zipcode)}`) .then(res => res.text()) .then(text => { let data; try { data = JSON.parse(text); } catch (e) { resultBox.innerHTML = 'Ugyldig svar fra serveren.'; return; } // Skjul titteltekst header?.style && (header.style.position = 'unset'); // Skjul titteltekst title?.style && (title.style.display = 'none'); // Skjul instruksjonstekst instructions?.querySelector("p")?.style && (instructions.querySelector("p").style.display = 'none'); document.getElementById("content").style.display = "block"; document.getElementById("content").style.marginTop = "10px"; document.getElementById("content").style.height = "fit-content"; // Hvis ingen resultater, vis alt igjen if (!data.result || data.result.length === 0) { const newUrl = `/leverand%C3%B8r/${encodeURIComponent(query.toLowerCase())}${zipcode ? '/postnr_' + encodeURIComponent(zipcode) : ''}`; const currentUrl = location.href; history.pushState( {}, '', location.href ); history.replaceState( {}, document.title, newUrl ); zipcodeInput.style.display = ''; submitBtn.style.display = ''; suggestionBox.style.display = 'none'; suggestionIconBox.style.display = ''; parent.style.display = ''; parent.style.alignItems = ''; queryInput.style.flex = ''; queryInput.style.height = ''; queryInput.style.width = ''; zipcodeInput.style.marginTop = '6px'; submitBtn.style.marginTop = '8px'; document.getElementById("dynamic-search-icon")?.parentElement?.remove(); resultBox.innerHTML = '

Beklager, fant ingen leverandører.

'; return; } // Kompakt visning zipcodeInput.style.display = 'none'; submitBtn.style.display = 'none'; suggestionBox.style.display = 'none'; suggestionIconBox.style.display = 'none'; document.getElementById("dynamic-search-icon")?.parentElement?.remove(); document.getElementById("search").style.marginTop = "20px"; document.getElementById("search").style.marginBottom = "5px"; const newIcon = document.createElement("span"); newIcon.innerHTML = ` `; newIcon.addEventListener("click", () => queryInput.focus()); queryInput.parentNode.append(newIcon); parent.style.display = 'flex'; parent.style.alignItems = 'center'; queryInput.style.flex = '1'; queryInput.style.height = '32px'; queryInput.style.minHeight = '32px'; queryInput.style.width = '280px'; // Bygg HTML-resultater let html = `
`; let metaDescriptionText = `De tre beste i `; const combined = `${query.toLowerCase()}_${data.place.place.toLowerCase()}`; const newUrl = `/leverand%C3%B8r/${encodeURIComponent(combined)}${zipcode ? '/postnr_' + encodeURIComponent(zipcode) : ''}`; history.pushState( {}, '', location.href ); history.replaceState( {}, document.title, newUrl ); const formattedQuery = query.charAt(0).toUpperCase() + query.slice(1).toLowerCase(); metaDescriptionText += `${data.place.place} er `; document.title = `${formattedQuery} ${data.place.place} | TreBeste i ${data.place.place} | ${zipcode}`; // Topp 3 html += '
De tre beste i nærheten basert på tilbakemeldinger fra brukerne
'; data.result.slice(0, 3).forEach((c, index) => { const stars = (() => { let r = c.Stars; if (r <= 4.0) r = 4.0; else if (r <= 4.5) r = 4.5; else r = 5.0; return Array.from({ length: 5 }, (_, i) => { let starClass = 'far fa-star'; if (i < Math.floor(r)) { starClass = 'fas fa-star'; } else if (i < r) { starClass = 'fas fa-star-half-alt'; } return ``; }).join(''); })(); const cat = ''; const ratingEntry = (c.Ratings || [])[Math.floor(Math.random() * (c.Ratings || []).length)]; let ratingsHtml = ''; if (ratingEntry) { const [text, name] = ratingEntry.split('|'); ratingsHtml = `
“${text.trim()}” ‐ ${name?.trim() || ''}.
`; } html += `
${c.Name}${stars}
${c.Address}, ${c.Zip} ${c.City}
Få tilbud
Tilbakemeldinger
${ratingsHtml}
`; }); html += '
'; metaDescriptionText += data.result.slice(0, 3).map(c => c.Name).join(', '); let metaDescription = document.querySelector('meta[name="description"]'); if (!metaDescription) { metaDescription = document.createElement('meta'); metaDescription.setAttribute('name', 'description'); document.head.appendChild(metaDescription); } metaDescription.setAttribute('content', `${metaDescriptionText}`); window.requestAnimationFrame(() => { const ratingBlocks = document.querySelectorAll('.ratings'); let maxWidth = 0; // Measure max width ratingBlocks.forEach(el => { const width = el.offsetWidth; if (width > maxWidth) maxWidth = width + 10; }); // Apply max width to all ratingBlocks.forEach(el => { el.style.width = maxWidth + 'px'; }); }); // Andre const others = data.result.slice(3).slice(0,10); if (others.length > 0) { html += '
Andre som ikke er blant de tre beste
'; others.forEach(c => { html += `
${c.Name}
${c.Address}, ${c.Zip} ${c.City}
${c.Homepage.replace(/^https?:\/\//, '')}
`; }); html += '
'; } html += '
'; resultBox.innerHTML = html; window.scrollTo({ top: 0, behavior: 'smooth' }); }) .catch(error => { console.error('Feil:', error); resultBox.innerHTML = 'Det oppsto en feil. Prøv igjen senere.'; }); }