Localities Nearby POI
Sample code for Woosmap Map JavaScript API
author(s):
Woosmap
HTML
<!DOCTYPE html>
<html>
<head>
<title>Localities Nearby POI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="utf-8" />
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="container">
<div id="sidebar">
<div id="innerWrapper">
<div class="sectionHeader"><span>Types</span></div>
<div class="typesOptions__list"></div>
<div class="sectionHeader"><span>Radius</span></div>
<div class="radius__container">
<input
type="range"
id="radius"
min="100"
max="10000"
value="1000"
step="100"
/><label id="radius-label" contenteditable="true"
>1 km</label
>
</div>
<div class="sectionHeader">
<span>Results</span>
<span is="pagination"
><button id="page-previous" disabled>‹</button
><button id="page-next" disabled>›</button></span
>
</div>
<ol id="results"></ol>
</div>
</div>
<div id="mapContainer">
<div id="autocomplete-container">
<svg class="search-icon" viewBox="0 0 16 16">
<path
d="M3.617 7.083a4.338 4.338 0 1 1 8.676 0 4.338 4.338 0 0 1-8.676 0m4.338-5.838a5.838 5.838 0 1 0 2.162 11.262l2.278 2.279a1 1 0 0 0 1.415-1.414l-1.95-1.95A5.838 5.838 0 0 0 7.955 1.245"
fill-rule="evenodd"
clip-rule="evenodd"
></path>
</svg>
<input
type="text"
id="autocomplete-input"
placeholder="Search Localities..."
autocomplete="off"
/>
<button aria-label="Clear" class="clear-searchButton" type="button">
<svg class="clear-icon" viewBox="0 0 24 24">
<path
d="M7.074 5.754a.933.933...
CSS
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
#container {
height: 100%;
display: flex;
}
#sidebar {
flex-basis: 12rem;
flex-grow: 1;
max-width: 30rem;
height: 100%;
box-sizing: border-box;
overflow: auto;
}
#map {
flex-basis: 70vw;
flex-grow: 5;
height: 100%;
}
/*
* Always set the map height explicitly to define the size of the div element
* that contains the map.
*/
#map {
height: 100%;
}
/*
* Optional: Makes the sample page fill the window.
*/
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
#autocomplete-container {
display: flex;
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 -1px 0px rgba(0, 0, 0, 0.02);
background: #fff;
border-radius: 12px;
padding: 0 12px;
max-width: 320px;
width: 100%;
height: 42px;
border: none;
box-sizing: border-box;
align-items: center;
cursor: text;
font-size: 15px;
}
#autocomplete-container .search-icon, #autocomplete-container .clear-icon {
color: inherit;
flex-shrink: 0;
height: 16px;
width: 16px;
}
#autocomplete-container .clear-icon {
transform: scale(1.3);
}
#autocomplete-input {
box-sizing: border-box;
padding: 0;
height: 40px;
line-height: 24px;
vertical-align: top;
transition-property: color;
transition-duration: 0.3s;
width: 100%;
text-overflow: ellipsis;
background: transparent;
border-radius: 0;
border: 0;
margin: 0 8px;
outline: 0;
overflow: visible;
appearance: textfield;
font-size: 100%;
}
.clear-searchButton {
...
JavaScript
const availableTypes = [
"transit.station",
"transit.station.airport",
"transit.station.rail",
"business",
"business.cinema",
"business.theatre",
"business.nightclub",
"business.finance",
"business.finance.bank",
"business.fuel",
"business.parking",
"business.mall",
"business.food_and_drinks",
"business.food_and_drinks.bar",
"business.food_and_drinks.biergarten",
"business.food_and_drinks.cafe",
"business.food_and_drinks.fast_food",
"business.food_and_drinks.pub",
"business.food_and_drinks.restaurant",
"business.food_and_drinks.food_court",
"business.shop",
"business.shop.mall",
"business.shop.bakery",
"business.shop.butcher",
"business.shop.library",
"business.shop.grocery",
"business.shop.sports",
"business.shop.toys",
"business.shop.clothes",
"business.shop.furniture",
"business.shop.electronics",
"education",
"education.school",
"education.kindergarten",
"education.university",
"education.college",
"education.library",
"hospitality",
"hospitality.hotel",
"hospitality.hostel",
"hospitality.guest_house",
"hospitality.bed_and_breakfast",
"hospitality.motel",
"medical",
"medical.hospital",
"medical.pharmacy",
"medical.clinic",
"tourism",
"tourism.attraction",
"tourism.attraction.amusement_park",
"tourism.attraction.zoo",
"tourism.attraction.aquarium",
"tourism.monument",
"tourism.monument.castle",
"tourism.museum",
"government",
"park",
"place_of_worship",
"police",
"post_office",
"sports",
];
const types = new Set();
let map;
let results;
let nearbyCircle;
let marker;
let localitiesService;
let autocompleteRequest;
let nearbyRequest;
const buildTree = (availableTypes) => {
const tree = {};
availableTypes.forEach((type) => {
const parts = type.split(".");
let node = tree;
parts.forEach((part) => {
node[part] = node[part] || {};
node = node[part];
});
});
return tree;
};
const createList = (node, prefix =...