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;