Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
105 changes: 72 additions & 33 deletions samples/ui-kit-place-search-nearby/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,79 @@
<!--[START maps_ui_kit_place_search_nearby] -->
<!DOCTYPE html>
<html>
<head>
<title>Place List Nearby Search with Google Maps</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script type="module" src="./index.js"></script>
</head>
<body>
<!--[START maps_ui_kit_place_search_nearby_map] -->
<gmp-map center="-37.813,144.963" zoom="10" map-id="DEMO_MAP_ID">
<div class="overlay" slot="control-inline-start-block-start">
<div class="controls">
<select name="types" class="type-select">
<option value="">Select a place type</option>
<option value="cafe">Cafe</option>
<option value="restaurant">Restaurant</option>
<option value="electric_vehicle_charging_station">
EV charging station
</option>
</select>
<head>
<title>Place Search Nearby with Google Maps</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="module" src="./index.js" defer></script>
<!-- prettier-ignore -->
<script>
(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly", internalUsageAttributionIds: "gmp_mcp_codeassist_v0.1_github"});
</script>
</head>
<body>
<!--[START maps_ui_kit_place_search_nearby_map] -->
<div class="container">
<gmp-map
center="-37.813,144.963"
zoom="16"
map-id="DEMO_MAP_ID"
disable-default-ui>
<!--
The gmp-place-details-compact element is styled inline because it is
conditionally rendered and moved into the info window, which is
part of the map's shadow DOM.
-->
<gmp-place-details-compact
orientation="horizontal"
truncation-preferred
style="
width: 400px;
padding: 0;
margin: 0;
border: none;
background-color: transparent;
color-scheme: light;
">
<gmp-place-details-place-request></gmp-place-details-place-request>
<gmp-place-content-config>
<gmp-place-media></gmp-place-media>
<gmp-place-rating></gmp-place-rating>
<gmp-place-price></gmp-place-price>
<gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
<gmp-place-open-now-status></gmp-place-open-now-status>
<gmp-place-attribution
light-scheme-color="gray"
dark-scheme-color="white"></gmp-place-attribution>
</gmp-place-content-config>
</gmp-place-details-compact>
</gmp-map>
<div class="ui-panel">
<div class="controls">
<label for="type-select">
Select a place type:
<select id="type-select" class="type-select">
<option value="restaurant">Restaurant</option>
<option value="cafe" selected>Cafe</option>
<option value="electric_vehicle_charging_station">
EV charging station
</option>
</select>
</label>
</div>
<div class="list-container">
<gmp-place-search orientation="vertical" selectable>
<gmp-place-all-content></gmp-place-all-content>
<gmp-place-nearby-search-request
location-restriction="50000@-37.813, 144.963">
</gmp-place-nearby-search-request>
</gmp-place-search>
</div>
</div>
</div>
<div class="list-container">
<gmp-place-list selectable style="display: none;"></gmp-place-list>
</div>
</div>
</gmp-map>

<gmp-place-details style="display: none;">
<gmp-place-details-place-request></gmp-place-details-place-request>
<gmp-place-all-content></gmp-place-all-content>
</gmp-place-details>

<!--[END maps_ui_kit_place_search_nearby_map] -->
<script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "alpha"});</script>
</body>
<!--[END maps_ui_kit_place_search_nearby_map] -->
</body>
</html>
<!--[END maps_ui_kit_place_search_nearby] -->
231 changes: 118 additions & 113 deletions samples/ui-kit-place-search-nearby/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,132 +6,137 @@
/* [START maps_ui_kit_place_search_nearby] */

/* [START maps_ui_kit_place_search_nearby_query_selectors] */
const map = document.querySelector("gmp-map") as any;
const placeList = document.querySelector("gmp-place-list") as any;
const typeSelect = document.querySelector(".type-select") as any;
const placeDetails = document.querySelector("gmp-place-details") as any;
const placeDetailsRequest = document.querySelector('gmp-place-details-place-request') as any;
// Query selectors for various elements in the HTML file.
const map = document.querySelector('gmp-map') as google.maps.MapElement
const placeSearch = document.querySelector('gmp-place-search') as any
const placeSearchQuery = document.querySelector(
'gmp-place-nearby-search-request'
) as any
const placeDetails = document.querySelector('gmp-place-details-compact') as any
const placeRequest = document.querySelector(
'gmp-place-details-place-request'
) as any
const typeSelect = document.querySelector('.type-select') as HTMLSelectElement
/* [END maps_ui_kit_place_search_nearby_query_selectors] */
let markers = {};
let infoWindow;

async function initMap(): Promise<void> {
await google.maps.importLibrary('places');
const { LatLngBounds } = await google.maps.importLibrary('core') as google.maps.CoreLibrary;
const { InfoWindow } = await google.maps.importLibrary('maps') as google.maps.MapsLibrary;
const { spherical } = await google.maps.importLibrary('geometry') as google.maps.GeometryLibrary;

infoWindow = new InfoWindow;
let marker;

function getContainingCircle(bounds) {
const diameter = spherical.computeDistanceBetween(
bounds.getNorthEast(),
bounds.getSouthWest()
);
const calculatedRadius = diameter / 2;
const cappedRadius = Math.min(calculatedRadius, 50000); // Radius cannot be more than 50000.
return { center: bounds.getCenter(), radius: cappedRadius };
}

findCurrentLocation();

// Global variables for the map, markers, and info window.
const markers: Map<string, google.maps.marker.AdvancedMarkerElement> = new Map()
let infoWindow: google.maps.InfoWindow
let AdvancedMarkerElement: typeof google.maps.marker.AdvancedMarkerElement
let LatLngBounds: typeof google.maps.LatLngBounds

// The init function is called when the page loads.
async function init(): Promise<void> {
// Import the necessary libraries from the Google Maps API.
const [{ InfoWindow }, { Place }, markerLib, coreLib] = await Promise.all([
google.maps.importLibrary('maps') as Promise<google.maps.MapsLibrary>,
google.maps.importLibrary(
'places'
) as Promise<google.maps.PlacesLibrary>,
google.maps.importLibrary(
'marker'
) as Promise<google.maps.MarkerLibrary>,
google.maps.importLibrary('core') as Promise<google.maps.CoreLibrary>,
])

AdvancedMarkerElement = markerLib.AdvancedMarkerElement
LatLngBounds = coreLib.LatLngBounds

// Create a new info window and set its content to the place details element.
infoWindow = new InfoWindow({
content: placeDetails,
ariaLabel: 'Place Details',
headerDisabled: true,
pixelOffset: new google.maps.Size(0, -40),
})

// Set the map options.
map.innerMap.setOptions({
mapTypeControl: false,
clickableIcons: false,
});
mapTypeControl: false,
streetViewControl: false,
})

// Add a click listener to the map to hide the info window when the map is clicked.
map.innerMap.addListener('click', () => infoWindow.close())
/* [START maps_ui_kit_place_search_nearby_event] */
placeDetails.addEventListener('gmp-load', (event) => {
// Center the info window on the map.
map.innerMap.fitBounds(placeDetails.place.viewport, { top: 500, left: 400 });
});

typeSelect.addEventListener('change', (event) => {
// First remove all existing markers.
for(marker in markers){
markers[marker].map = null;
// Add event listeners to the type select and place search elements.
typeSelect.addEventListener('change', searchPlaces)

placeSearch.addEventListener('gmp-select', (event: Event) => {
const { place } = event as any
if (markers.has(place.id)) {
markers.get(place.id)!.click()
}
markers = {};

if (typeSelect.value) {
placeList.style.display = 'block';
placeList.configureFromSearchNearbyRequest({
locationRestriction: getContainingCircle(
map.innerMap.getBounds()
),
includedPrimaryTypes: [typeSelect.value],
}).then(addMarkers);
// Handle user selection in Place Details.
placeList.addEventListener('gmp-placeselect', ({ place }) => {
markers[place.id].click();
});
if (place.location) {
map.innerMap.setCenter(place.location)
}
});
/* [END maps_ui_kit_place_search_nearby_event] */
})
placeSearch.addEventListener(
'gmp-load',
() => {
searchPlaces()
},
{ once: true }
)
}

async function addMarkers(){
const { AdvancedMarkerElement } = await google.maps.importLibrary('marker') as google.maps.MarkerLibrary;
const { LatLngBounds } = await google.maps.importLibrary('core') as google.maps.CoreLibrary;

const bounds = new LatLngBounds();

if(placeList.places.length > 0){
placeList.places.forEach((place) => {
let marker = new AdvancedMarkerElement({
map: map.innerMap,
position: place.location
});

markers[place.id] = marker;
bounds.extend(place.location);

/* [START maps_ui_kit_place_search_nearby_click_event] */
marker.addListener('gmp-click', (event) => {
if(infoWindow.isOpen){
infoWindow.close();
}

placeDetailsRequest.place = place.id;
placeDetails.style.display = 'block';
placeDetails.style.width = '350px';
infoWindow.setOptions({
content: placeDetails,
});
infoWindow.open({
anchor: marker,
map: map.innerMap
});
});
/* [END maps_ui_kit_place_search_nearby_click_event] */

map.innerMap.setCenter(bounds.getCenter());
map.innerMap.fitBounds(bounds);
});
/* [END maps_ui_kit_place_search_nearby_event] */
// The searchPlaces function is called when the user changes the type select or when the page loads.
function searchPlaces() {
// Close the info window and clear the markers.
infoWindow.close()
for (const marker of markers.values()) {
marker.map = null
}
markers.clear()

// Set the place search query and add an event listener to the place search element.
if (typeSelect.value) {
const center = map.innerMap.getCenter()!
placeSearchQuery.maxResultCount = 5
placeSearchQuery.locationRestriction = {
center: { lat: center.lat(), lng: center.lng() },
radius: 50000, // 50km radius
}
placeSearchQuery.locationBias = {
center: { lat: center.lat(), lng: center.lng() },
}
placeSearchQuery.includedTypes = [typeSelect.value]
placeSearch.addEventListener('gmp-load', addMarkers, { once: true })
}
}

async function findCurrentLocation(){
const { LatLng } = await google.maps.importLibrary('core') as google.maps.CoreLibrary;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const pos = new LatLng(position.coords.latitude,position.coords.longitude);
map.innerMap.panTo(pos);
map.innerMap.setZoom(14);
},
() => {
console.log('The Geolocation service failed.');
map.innerMap.setZoom(14);
},
);
} else {
console.log('Your browser doesn\'t support geolocation');
map.innerMap.setZoom(14);
}
// The addMarkers function is called when the place search element loads.
async function addMarkers() {
const bounds = new LatLngBounds()

if (placeSearch.places.length === 0) {
return
}

placeSearch.places.forEach((place) => {
const marker = new AdvancedMarkerElement({
map: map.innerMap,
position: place.location,
collisionBehavior:
google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL,
})

markers.set(place.id, marker)
bounds.extend(place.location)

marker.addListener('click', () => {
if (place.location) {
map.innerMap.setCenter(place.location)
}
placeRequest.place = place
infoWindow.setPosition(place.location)
infoWindow.open(map.innerMap)
})
})

map.innerMap.fitBounds(bounds)
}

initMap();
init()
/* [END maps_ui_kit_place_search_nearby] */
Loading