From e4fdd8457d2d320eea502f0801fc22eceb8947b1 Mon Sep 17 00:00:00 2001 From: Petri Hienonen Date: Thu, 13 Nov 2025 18:12:17 +0200 Subject: Nothing --- app/components.js | 57 +++++++++++++++++++++++++++++++--------- app/dom.js | 14 ++++++++++ app/geometry.js | 56 +++++++++++++++++++++++++++++++-------- app/main.js | 47 ++++++++++++--------------------- app/map.js | 34 ++++++++++++------------ app/models.js | 78 ++++++++++++------------------------------------------- 6 files changed, 154 insertions(+), 132 deletions(-) (limited to 'app') diff --git a/app/components.js b/app/components.js index 6531206..1c8c6aa 100644 --- a/app/components.js +++ b/app/components.js @@ -1,5 +1,5 @@ import { Dom, DomOptions, ToastType } from "dom"; -import { AreaParam, District, Filters, House, HouseParameter, Weights } from "models"; +import { AreaParam, Filters, House, HouseParameter, Weights } from "models"; export class Widgets { /** @@ -422,7 +422,7 @@ export class Sidebar { children: [ Dom.heading( 3, - "Weights", + "Scoring", new DomOptions({ styles: { color: "#333", @@ -715,34 +715,67 @@ export class Modal { const imgSect = Dom.div( new DomOptions({ children: [ - Dom.div( + Dom.span( + "Images", new DomOptions({ - id: "img_title", - styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "10px" }, + styles: { + fontSize: "14px", + fontWeight: "bold", + marginBottom: "10px", + }, }), ), Dom.div( new DomOptions({ children: house.images.slice(0, 3).map((src) => { - return Dom.img( - src, + // Wrap image in anchor tag that opens in new tab + return Dom.a( new DomOptions({ - attributes: { loading: "lazy" }, - styles: { borderRadius: "4px", flexShrink: "0", height: "100px" }, + attributes: { + href: src, + rel: "noopener noreferrer", + target: "_blank", + }, + children: [ + Dom.img( + src, + new DomOptions({ + attributes: { + alt: "House image", + loading: "lazy", + }, + styles: { + borderRadius: "4px", + cursor: "pointer", + flexShrink: "0", + height: "100px", + transition: "opacity 0.2s ease", + }, + }), + ), + ], + styles: { + display: "block", + textDecoration: "none", + }, }), ); }), - - styles: { display: "flex", gap: "10px", overflowX: "auto", paddingBottom: "5px" }, + styles: { + display: "flex", + gap: "10px", + overflowX: "auto", + paddingBottom: "5px", + }, }), ), ], styles: { marginBottom: "20px" }, }), ); + frag.appendChild(imgSect); } - return frag; } diff --git a/app/dom.js b/app/dom.js index 4419205..8e73a09 100644 --- a/app/dom.js +++ b/app/dom.js @@ -119,6 +119,20 @@ export class Dom { return strong; } + /** + * Create a `` + * @param {DomOptions} o + */ + static a(o) { + const link = document.createElement("a"); + Object.assign(link.style, o.styles); + if (o.id) link.id = o.id; + for (const cls of o.classes) link.classList.add(cls); + for (const [k, v] of Object.entries(o.attributes)) link.setAttribute(k, v); + if (o.children) link.append(...o.children); + return link; + } + /** * Create a `