From 62827771cd6bf29cde2951e7e5f83d5de477e94f Mon Sep 17 00:00:00 2001 From: Anita Lipsky <7695311+purplebugs@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:16:12 +0200 Subject: [PATCH] feat: Map marker as web component (#33) --- src/alpaca-map-marker.js | 170 +++++++++++++++++++++++++++++++++++++++ src/alpaca-map.js | 155 ++++++----------------------------- 2 files changed, 196 insertions(+), 129 deletions(-) create mode 100644 src/alpaca-map-marker.js diff --git a/src/alpaca-map-marker.js b/src/alpaca-map-marker.js new file mode 100644 index 0000000..d26daa1 --- /dev/null +++ b/src/alpaca-map-marker.js @@ -0,0 +1,170 @@ +import { LitElement, html, css } from "lit"; +import { iconStyles, iconHouseFlag, iconKey } from "./svg-icons"; + +export default class AlpacaMapMarker extends LitElement { + static properties = { + name: { type: String }, + category: { type: String }, + count: { type: Number }, + city: { type: String }, + address: { type: String }, + directions: { type: String }, + highlight: { + type: String, + converter: (value) => { + if (value === "true") { + return "highlight"; + } else { + return ""; + } + }, + } /* If a property changes the element re-renders */, + }; + + static styles = [ + iconStyles, + css` + /********* Farm styles in unhighlighted state *********/ + /* Ref: https://developers.google.com/maps/documentation/javascript/advanced-markers/html-markers#maps_advanced_markers_html-css */ + + .farm { + display: flex; + align-items: center; + justify-content: center; + + background-color: white; + border-radius: 1rem; + box-shadow: 10px 10px 5px #0003; + color: var(--almost-black); + + /* Override google map font to avoid flicker when load */ + font: + 400 1.5em Poppins, + Arial, + sans-serif; + padding: 0.75rem; + + width: auto; + max-width: 15rem; + } + + .farm::after { + border-left: 9px solid transparent; + border-right: 9px solid transparent; + content: ""; + height: 0; + left: 50%; + position: absolute; + top: 100%; + transform: translate(-50%); + width: 0; + z-index: 1; + } + + .farm .summary { + display: flex; + align-items: center; + justify-content: center; + + font-size: 1.5rem; + gap: 0.5rem; + } + + .farm .details { + display: none; + flex-direction: column; + flex: 1; + } + + /********* Farm styles in highlighted state *********/ + + /* .farm.highlight { + background-color: #ffffff; + border-radius: 8px; + box-shadow: 10px 10px 5px rgba(0, 0, 0, 0.2); + height: 80px; + padding: 8px 15px; + width: auto; + } */ + + .farm.highlight .details { + display: flex; + } + + /********* Farm category colours *********/ + .farm.private { + border: 0.2em solid var(--private-farm); + } + + .farm.public { + border: 0.2em solid var(--public-farm); + } + + .farm.private::after { + border-top: 9px solid var(--private-farm); + } + + .farm.public::after { + border-top: 9px solid var(--public-farm); + } + + .farm.private .icon svg { + fill: var(--private-farm); + } + + .farm.public .icon svg { + fill: var(--public-farm); + } + `, + ]; + + constructor() { + super(); + this.name; + this.category; + this.count; + this.city; + this.address; + this.directions; + this.highlight = false; + } + + // When element is connected to the DOM connectedCallback() is called. + // This is needed in order to know the value of this.key which is passed in from the attribute + + connectedCallback() { + super.connectedCallback(); + } + + render() { + return html`
+
+
+ ${this.category === "private" + ? iconKey().htmlObject + : iconHouseFlag().htmlObject} +
+
${this.count} 🦙
+
+ +
+

${this.name}

+ ${this.city} +
${this.address}
+
+ Directions +
+
+
`; + } +} + +if (!customElements.get("alpaca-map-marker")) { + customElements.define("alpaca-map-marker", AlpacaMapMarker); +} diff --git a/src/alpaca-map.js b/src/alpaca-map.js index 9278ae4..1584b9e 100644 --- a/src/alpaca-map.js +++ b/src/alpaca-map.js @@ -14,6 +14,7 @@ import { iconPersonHiking, iconStore, } from "./svg-icons"; +import "./alpaca-map-marker"; export default class AlpacaMap extends LitElement { static properties = { @@ -185,98 +186,6 @@ export default class AlpacaMap extends LitElement { width: auto; background-color: var(--pale-blue); } - - /********* Farm styles in unhighlighted state *********/ - /* Ref: https://developers.google.com/maps/documentation/javascript/advanced-markers/html-markers#maps_advanced_markers_html-css */ - - .farm { - display: flex; - align-items: center; - justify-content: center; - - background-color: white; - border-radius: 1rem; - box-shadow: 10px 10px 5px #0003; - color: var(--almost-black); - - /* Override google map font to avoid flicker when load */ - font: - 400 1.5em Poppins, - Arial, - sans-serif; - padding: 0.75rem; - - width: auto; - max-width: 15rem; - } - - .farm::after { - border-left: 9px solid transparent; - border-right: 9px solid transparent; - content: ""; - height: 0; - left: 50%; - position: absolute; - top: 100%; - transform: translate(-50%); - width: 0; - z-index: 1; - } - - .farm .summary { - display: flex; - align-items: center; - justify-content: center; - - font-size: 1.5rem; - gap: 0.5rem; - } - - .farm .details { - display: none; - flex-direction: column; - flex: 1; - } - - /********* Farm styles in highlighted state *********/ - - /* .farm.highlight { - background-color: #ffffff; - border-radius: 8px; - box-shadow: 10px 10px 5px rgba(0, 0, 0, 0.2); - height: 80px; - padding: 8px 15px; - width: auto; - } */ - - .farm.highlight .details { - display: flex; - } - - /********* Farm category colours *********/ - .farm.private { - border: 0.2em solid var(--private-farm); - } - - .farm.public { - border: 0.2em solid var(--public-farm); - } - - .farm.private::after { - border-top: 9px solid var(--private-farm); - } - - .farm.public::after { - border-top: 9px solid var(--public-farm); - } - - .farm.private .icon svg { - fill: var(--private-farm); - } - - .farm.public .icon svg { - fill: var(--public-farm); - } `, ]; @@ -385,44 +294,27 @@ export default class AlpacaMap extends LitElement { this.map.mapTypes.set("styled_map", styledMapType); this.map.setMapTypeId("styled_map"); - // Add markers to the map - function toggleHighlight(markerView, farm) { - if (markerView.content.classList.contains("highlight")) { - markerView.content.classList.remove("highlight"); - markerView.zIndex = null; - } else { - markerView.content.classList.add("highlight"); - markerView.zIndex = 1; - } - } - - function buildContent(farm) { - const content = document.createElement("div"); - content.classList.add("farm"); - content.classList.add(farm?.category?.private ? "private" : "public"); - - content.innerHTML = ` -
-
${iconHouseFlag().svgString}
-
${farm?.count?.alpacas?.status?.active} 🦙
-
- -
-

${farm?.name}

- ${farm?.city} -
${farm?.location?.google?.formatted_address}
-
- Directions -
-
- `; - - return content; - } - const markers = this.farms.map((farm) => { + const content = document.createElement("alpaca-map-marker"); + content.setAttribute("name", farm?.name); + content.setAttribute( + "category", + farm?.category?.private ? "private" : "public" + ); + content.setAttribute("count", farm?.count?.alpacas?.status?.active); + content.setAttribute("city", farm?.city); + content.setAttribute( + "address", + farm?.location?.google?.formatted_address + ); + content.setAttribute( + "directions", + farm?.location?.google?.directions_url_href + ); + content.setAttribute("highlight", "false"); + const marker = new AdvancedMarkerElement({ - content: buildContent(farm), + content, position: farm.location.lat_lng, title: farm?.name, }); @@ -431,7 +323,12 @@ export default class AlpacaMap extends LitElement { // toggle marker summary/details when marker is clicked marker.addListener("click", () => { - toggleHighlight(marker, farm); + const highlighted = marker.content.getAttribute("highlight"); + if (highlighted === "true") { + marker.content.setAttribute("highlight", "false"); + } else { + marker.content.setAttribute("highlight", "true"); + } }); farm._marker = marker;