import { Throttler } from "./Throttler"; import { setTopbarOffset, addToggleDropdownListener } from "./topbar"; import { Coordinate, Position, convertPixelsToCoordinate, convertCoordinateToPixels } from "./coordinates"; import { Size } from "./size"; import { Tooltip } from "./Tooltip"; import { loadReviews } from "./review"; const tooltip = new Tooltip(document.getElementById("tooltip")!); type Square = { x1: number, y1: number, x2: number, y2: number, }; type ZipCodeReverseResponse = { nr: number | null; navn: string; visueltcenter: number[]; bbox: number[]; }; async function fetchZipCode({ longitude, latitude, }: Coordinate): Promise { return fetch( `https://api.dataforsyningen.dk/postnumre/reverse?x=${longitude}&y=${latitude}&landpostnumre`, ) .then((request) => request.json()) .then((data) => { let zipCode = parseInt(data.nr); return { ...data, nr: isNaN(zipCode) ? null : zipCode, } as ZipCodeReverseResponse; }) .catch(() => null as never); } let currentBoundary: Array | null = null; async function fetchAndDisplayZipCode(coords: Coordinate) { if (currentBoundary && coords.longitude > currentBoundary[0] && coords.latitude > currentBoundary[1] && coords.longitude < currentBoundary[2] && coords.latitude < currentBoundary[3] ) return; const response = await fetchZipCode(coords); currentBoundary = response.bbox; displayZipCode( document.querySelector("#zip-code")!, response.nr, response.navn, response.visueltcenter ? { longitude: response.visueltcenter[0], latitude: response.visueltcenter[1] } : null, response.bbox ? { x1: response.bbox[0], y1: response.bbox[1], x2: response.bbox[2], y2: response.bbox[3] } : null, ); } function displayMousePosition(element: HTMLParagraphElement, mouse: Position) { element.innerHTML = `Mouse position: (${mouse.x}px, ${mouse.y}px)`; } function displayCoords(element: HTMLParagraphElement, coords: Coordinate) { const longitude = coords.longitude.toFixed(3); const latitude = coords.latitude.toFixed(3); element.innerHTML = `Coords: ${longitude}, ${latitude}`; } function displayZipCode( element: HTMLParagraphElement, zipCode: number | null, name: string | null, center: Coordinate | null, boundary: Square | null, ) { element.innerHTML = zipCode === null ? `Postnummer ikke fundet` : `Postnummer: ${zipCode}, ${name}`; tooltip.setText(zipCode ? `${zipCode} ${name}` : ""); const dot = document.getElementById("dot")!; const boundaryElem = document.getElementById("boundary")!; if (!center || !boundary) { dot.style.display = "none"; boundaryElem.style.display = "none"; return; } const mapImg = document.getElementById("map")!; const mapSize: Size = { width: mapImg.clientWidth, height: mapImg.clientHeight, }; // Draw dot const position = convertCoordinateToPixels(center, mapSize); const rect = document.getElementById("map")!.getBoundingClientRect(); dot.style.display = "block"; dot.style.left = position.x + rect.left + "px"; dot.style.top = position.y + rect.top + document.documentElement.scrollTop + "px"; // Draw boundary const bottomleft = convertCoordinateToPixels({ longitude: boundary.x1, latitude: boundary.y1 }, mapSize); const topright = convertCoordinateToPixels({ longitude: boundary.x2, latitude: boundary.y2 }, mapSize); boundaryElem.style.display = "block"; boundaryElem.style.left = bottomleft.x + rect.left + "px"; boundaryElem.style.top = topright.y + rect.top + document.documentElement.scrollTop + "px"; boundaryElem.style.width = topright.x - bottomleft.x + "px"; boundaryElem.style.height = bottomleft.y - topright.y + "px"; } function setupMap( mousePositionElement: HTMLParagraphElement, coordsElement: HTMLParagraphElement, zipCodeElement: HTMLParagraphElement, ) { const mapImg = document.querySelector("#map")!; const fetcher = new Throttler(200); mapImg.addEventListener('mousemove', async (event: MouseEvent) => { const mousePosition: Position = { x: event.offsetX, y: event.offsetY }; displayMousePosition(mousePositionElement, mousePosition); const mapSize: Size = { width: mapImg.clientWidth, height: mapImg.clientHeight, }; const coords = convertPixelsToCoordinate(mousePosition, mapSize); displayCoords(coordsElement, coords); fetcher.call(async () => await fetchAndDisplayZipCode(coords)); }); mapImg.addEventListener("mouseup", async (event: MouseEvent) => { const mousePosition: Position = { x: event.offsetX, y: event.offsetY }; displayMousePosition(mousePositionElement, mousePosition); const mapSize: Size = { width: mapImg.clientWidth, height: mapImg.clientHeight, }; const coords = convertPixelsToCoordinate(mousePosition, mapSize); displayCoords(coordsElement, coords); fetcher.call(async () => await fetchAndDisplayZipCode(coords)); }); mapImg.onmouseleave = (_event: MouseEvent) => { displayZipCode(zipCodeElement, null, null, null, null); }; } function setupSearchBar(zipCodeElement: HTMLParagraphElement) { const searchBar = document.querySelector("#search-bar")!; const searchInput = document.querySelector("#search-input")!; searchInput.addEventListener("keydown", (event) => { if (event.key.length === 1 && !"0123456789".includes(event.key)) event.preventDefault(); }); searchBar.addEventListener("submit", async (event: Event) => { event.preventDefault(); const inputValue = searchInput.value; if (!/^\d+$/.test(inputValue)) return; const data = await ( await fetch( `https://api.dataforsyningen.dk/postnumre?nr=${inputValue}`, ) ).json(); displayZipCode( zipCodeElement, data.length ? parseInt(data[0]["nr"]) : null, data.length ? data[0]["navn"] : null, data.length ? { longitude: data[0]["visueltcenter"][0], latitude: data[0]["visueltcenter"][1] } : null, data.length ? { x1: data[0]["bbox"][0], y1: data[0]["bbox"][1], x2: data[0]["bbox"][2], y2: data[0]["bbox"][3] } : null, ); }); } function pageRedirects() { const reviewRedirect = document.getElementById("reviews-redirect")! const mapRedirect = document.getElementById("map-redirect")! const mainElement = document.getElementById("main")! reviewRedirect.addEventListener("click", () => { mainElement.innerHTML = `

Anmeldelser

${loadReviews()}
` const dropdown = document.getElementById("dropdown")!; dropdown.classList.remove("enabled"); }); mapRedirect.addEventListener("click", () => { mainElement.innerHTML = `

Postnummer ikke fundet

` const [mousePositionElement, coordsElement, zipCodeElement] = [ "#mouse-position", "#coords", "#zip-code", ].map((id) => document.querySelector(id)!); setupSearchBar(zipCodeElement); setupMap(mousePositionElement, coordsElement, zipCodeElement); const dropdown = document.getElementById("dropdown")!; dropdown.classList.remove("enabled"); }) } function main() { if (navigator.userAgent.match("Chrome")) { location.href = "https://mozilla.org/firefox"; } const [mousePositionElement, coordsElement, zipCodeElement] = [ "#mouse-position", "#coords", "#zip-code", ].map((id) => document.querySelector(id)!); setupSearchBar(zipCodeElement); setupMap(mousePositionElement, coordsElement, zipCodeElement); setTopbarOffset(); addToggleDropdownListener(); pageRedirects(); } main();