Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions samples/localities-geocode/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,30 @@
</button>
</div>

<div id="instructions">
Enter an address to geocode or click on the map to reverse geocode.
</div>
<aside id="response-panel" data-empty="true">
<div class="panel-header">
<div class="panel-title">Geocode response</div>
<div class="panel-hint">
Enter an address to geocode or click on the map to reverse geocode.
</div>
</div>
<div class="summary"></div>
<div class="address-components"></div>
<details class="raw-json-details">
<summary>
<span>Raw JSON</span>
<button id="copy-raw-json" class="copy-btn" type="button" title="Copy" aria-label="Copy raw JSON">
<svg class="icon-copy" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor" d="m18.6 7.494-.625-.112a20.62 20.62 0 0 0-2.261-.264V4.982A2.328 2.328 0 0 0 13.8 2.688l-.626-.113a20.28 20.28 0 0 0-7.188 0l-.624.113A2.327 2.327 0 0 0 3.44 4.982v8.885a2.331 2.331 0 0 0 2.742 2.295 19.243 19.243 0 0 1 2.065-.244v2.756a2.329 2.329 0 0 0 2.742 2.294 19.142 19.142 0 0 1 6.793 0 2.33 2.33 0 0 0 2.742-2.294V9.789A2.33 2.33 0 0 0 18.6 7.494zM5.985 15.059a1.211 1.211 0 0 1-1.425-1.192V4.982a1.209 1.209 0 0 1 1-1.192l.624-.112a19.142 19.142 0 0 1 6.793 0l.625.112a1.211 1.211 0 0 1 1 1.192v8.885a1.213 1.213 0 0 1-1.426 1.192 20.358 20.358 0 0 0-4.293-.29.54.54 0 0 0-.072-.014.54.54 0 0 0-.113.023 20.3 20.3 0 0 0-2.713.281zM19.4 18.674a1.211 1.211 0 0 1-1.425 1.192 20.275 20.275 0 0 0-7.187 0A1.222 1.222 0 0 1 9.8 19.6a1.209 1.209 0 0 1-.434-.929v-2.803a19.126 19.126 0 0 1 3.608.294 2.409 2.409 0 0 0 .413.036 2.332 2.332 0 0 0 2.33-2.331V8.24a19.561 19.561 0 0 1 2.064.245l.625.112a1.209 1.209 0 0 1 1 1.192z"></path>
</svg>
<svg class="icon-check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 9" width="14" height="10" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.026 0.188287C12.2771 0.439342 12.2771 0.846374 12.026 1.09743L4.31172 8.81172C4.06067 9.06276 3.65363 9.06276 3.40258 8.81172L0.188287 5.59743C-0.0627622 5.3464 -0.0627622 4.93934 0.188287 4.6883C0.439342 4.43726 0.846374 4.43726 1.09743 4.6883L3.85715 7.44803L11.1169 0.188287C11.3679 -0.0627622 11.775 -0.0627622 12.026 0.188287Z" fill="currentColor"></path>
</svg>
</button>
</summary>
<pre><code id="raw-json"></code></pre>
</details>
</aside>

<div id="map"></div>
</div>
Expand Down
117 changes: 116 additions & 1 deletion samples/localities-geocode/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ clearSearchBtn.addEventListener("click", () => {
marker.setMap(null);
infoWindow.close();
}
clearResponse();
inputElement.focus();
});

Expand Down Expand Up @@ -92,10 +93,124 @@ function displayLocality(
infoWindow.setContent(`<span>${locality.formatted_address}</span>`);
infoWindow.open(map, marker);
map.setCenter(locality.geometry.location);
map.setZoom(14);
renderResponse(locality);
}
}

function escapeHtml(value: string): string {
return value
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}

function formatNameValue(value: string | string[]): string {
return Array.isArray(value) ? value.join(", ") : value;
}

function renderResponse(
locality: woosmap.map.localities.LocalitiesGeocodeResult,
) {
const panel = document.getElementById("response-panel");
const summaryEl = panel?.querySelector(".summary") as HTMLElement | null;
const componentsEl = panel?.querySelector(
".address-components",
) as HTMLElement | null;
const rawEl = document.getElementById("raw-json");
if (!panel || !summaryEl || !componentsEl || !rawEl) return;

panel.dataset.empty = "false";

const summaryRows: string[] = [];
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Formatted address:</span><span class='bold'>${escapeHtml(locality.formatted_address)}</span></p>`,
);
if (locality.types && locality.types.length) {
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Types:</span><span class='bold'>${escapeHtml(locality.types.join(", "))}</span></p>`,
);
}
if (locality.public_id) {
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Public ID:</span><span class='bold'>${escapeHtml(locality.public_id)}</span></p>`,
);
}
if (typeof locality.distance === "number") {
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Distance (m):</span><span class='bold'>${locality.distance}</span></p>`,
);
}
if (locality.geometry) {
const { geometry } = locality;
if (geometry.location_type) {
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Location type:</span><span class='bold'>${escapeHtml(geometry.location_type)}</span></p>`,
);
}
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Latitude:</span><span class='bold'>${geometry.location.lat}</span></p>`,
`<p class='option-detail'><span class='option-detail-label'>Longitude:</span><span class='bold'>${geometry.location.lng}</span></p>`,
);
if (geometry.viewport) {
const { viewport } = geometry;
summaryRows.push(
`<p class='option-detail'><span class='option-detail-label'>Viewport NE:</span><span class='bold'>${viewport.northeast.lat}, ${viewport.northeast.lng}</span></p>`,
`<p class='option-detail'><span class='option-detail-label'>Viewport SW:</span><span class='bold'>${viewport.southwest.lat}, ${viewport.southwest.lng}</span></p>`,
);
}
}
summaryEl.innerHTML = `<div class='section-title'>Summary</div>${summaryRows.join("")}`;

if (locality.address_components && locality.address_components.length) {
const rows = locality.address_components
.map((compo) => {
const label = escapeHtml((compo.types[0] ?? "").replace(/_/g, " "));
const longName = escapeHtml(formatNameValue(compo.long_name));
return `<p class='option-detail'><span class='option-detail-label'>${label}:</span><span class='bold'>${longName}</span></p>`;
})
.join("");
componentsEl.innerHTML = `<div class='section-title'>Address components</div>${rows}`;
} else {
componentsEl.innerHTML = "";
}

rawEl.textContent = JSON.stringify(locality, null, 2);
}

const copyBtn = document.getElementById("copy-raw-json");
if (copyBtn) {
copyBtn.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
const rawEl = document.getElementById("raw-json");
const text = rawEl?.textContent ?? "";
if (!text) return;
navigator.clipboard
.writeText(text)
.then(() => {
copyBtn.classList.add("copied");
window.setTimeout(() => copyBtn.classList.remove("copied"), 1500);
})
.catch((err) => console.error("Failed to copy raw JSON:", err));
});
}

function clearResponse() {
const panel = document.getElementById("response-panel");
if (!panel) return;
panel.dataset.empty = "true";
const summaryEl = panel.querySelector(".summary") as HTMLElement | null;
const componentsEl = panel.querySelector(
".address-components",
) as HTMLElement | null;
const rawEl = document.getElementById("raw-json");
if (summaryEl) summaryEl.innerHTML = "";
if (componentsEl) componentsEl.innerHTML = "";
if (rawEl) rawEl.textContent = "";
}

declare global {
interface Window {
initMap: () => void;
Expand Down
107 changes: 102 additions & 5 deletions samples/localities-geocode/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,108 @@
@include actionText($color: #fff);
}

#instructions {
max-width: 300px;
font-size: 17px;
padding: 10px;
@include map-panel($bottom: 50px, $left: 0);
#response-panel {
@include map-panel($bottom: 25px, $right: 10px);
width: 360px;
max-width: calc(100vw - 40px);
max-height: calc(40vh - 25px);
overflow-y: auto;
padding: 0;
font-size: 13px;

.panel-header {
padding: 12px 14px;
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.panel-title {
font-weight: 700;
font-size: 14px;
margin-bottom: 4px;
}

.panel-hint {
color: rgba(0, 0, 0, 0.6);
font-size: 12px;
}

.section-title {
color: rgba(0, 0, 0, 0.5);
font-size: 10px;
text-transform: uppercase;
letter-spacing: 1px;
padding: 14px 12px 8px 12px;
}

.summary,
.address-components {
background-color: #fff;
}

.address-components {
background-color: rgba(0, 0, 0, 0.03);
}

.option-detail {
display: flex;
flex-wrap: wrap;
padding: 0 12px 8px 12px;
margin: 0;
overflow-wrap: anywhere;
word-break: break-word;

&-label {
color: rgba(0, 0, 0, 0.5);
margin-right: 4px;
flex-shrink: 0;
}
}

.bold {
font-weight: 700;
}

.raw-json-details {
border-top: 1px solid rgba(0, 0, 0, 0.08);

summary {
cursor: pointer;
padding: 10px 14px;
font-weight: 600;
user-select: none;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}

.copy-btn {
@include copy-button;
}

pre {
margin: 0 10px 10px 10px;
padding: 10px;
border: 1px solid #e0e0e0;
background-color: #fafafa;
border-radius: 6px;
white-space: pre-wrap;
overflow-x: auto;
font-size: 12px;
font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console",
"Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono",
"Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier,
monospace;
}
}

&[data-empty="true"] {
.summary,
.address-components,
.raw-json-details {
display: none;
}
}
}

/* [END woosmap_localities_geocode] */
39 changes: 39 additions & 0 deletions shared/scss/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,45 @@
}
}

@mixin copy-button(
$color: rgba(0, 0, 0, 0.5),
$hover-color: #3d5afe,
$success-color: #2e7d32,
$padding: 2px 4px
) {
background: transparent;
border: 0;
padding: $padding;
cursor: pointer;
color: $color;
display: inline-flex;
align-items: center;
transition: color 0.2s ease-in-out;

&:hover,
&:focus {
color: $hover-color;
outline: none;
}

.icon-check {
display: none;
color: $success-color;
}

&.copied {
color: $success-color;

.icon-copy {
display: none;
}

.icon-check {
display: inline-block;
}
}
}

@mixin progress($width: 70px, $height:70px, $borderColor: #f3f3f3, $borderTopColor: #444444) {
position: fixed;
top: 0;
Expand Down
Loading