Skip to content

Commit bba8e0f

Browse files
authored
feat: Adds Places UI Kit Text Search example. (#299)
1 parent f783e04 commit bba8e0f

File tree

6 files changed

+275
-0
lines changed

6 files changed

+275
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Google Maps JavaScript Sample
2+
3+
This sample is generated from @googlemaps/js-samples located at
4+
https://github.com/googlemaps-samples/js-api-samples.
5+
6+
## Setup
7+
8+
### Before starting run:
9+
10+
`$npm i`
11+
12+
### Run an example on a local web server
13+
14+
First `cd` to the folder for the sample to run, then:
15+
16+
`$npm start`
17+
18+
### Build an individual example
19+
20+
From `samples/`:
21+
22+
`$npm run build --workspace=sample-name/`
23+
24+
### Build all of the examples.
25+
26+
From `samples/`:
27+
`$npm run build-all`
28+
29+
## Feedback
30+
31+
For feedback related to this sample, please open a new issue on
32+
[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues).
33+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!--
2+
@license
3+
Copyright 2025 Google LLC. All Rights Reserved.
4+
SPDX-License-Identifier: Apache-2.0
5+
-->
6+
<!--[START maps_ui_kit_place_search_text] -->
7+
<!DOCTYPE html>
8+
<html>
9+
<head>
10+
<title>Place List Text Search with Google Maps</title>
11+
<meta charset="utf-8">
12+
<link rel="stylesheet" type="text/css" href="style.css">
13+
<script type="module" src="./index.js"></script>
14+
</head>
15+
<body>
16+
<!--[START maps_ui_kit_place_search_text_map] -->
17+
<gmp-map center="-37.813,144.963" zoom="10" map-id="DEMO_MAP_ID">
18+
<div class="overlay" slot="control-inline-start-block-start">
19+
<div class="list-container">
20+
<gmp-place-list selectable></gmp-place-list>
21+
</div>
22+
</div>
23+
<gmp-place-details size="large"></gmp-place-details>
24+
</gmp-map>
25+
<!--[END maps_ui_kit_place_search_text_map] -->
26+
<script
27+
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8&libraries=maps&callback=initMap&v=alpha"
28+
defer
29+
></script>
30+
</body>
31+
</html>
32+
<!--[END maps_ui_kit_place_search_text] -->
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* @license
3+
* Copyright 2025 Google LLC. All Rights Reserved.
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/* [START maps_ui_kit_place_search_text] */
7+
/* [START maps_ui_kit_place_search_text_query_selectors] */
8+
const map = document.querySelector("gmp-map") as any;
9+
const placeList = document.querySelector("gmp-place-list") as any;
10+
const placeDetails = document.querySelector("gmp-place-details") as any;
11+
let marker = document.querySelector('gmp-advanced-marker') as any;
12+
/* [END maps_ui_kit_place_search_text_query_selectors] */
13+
/* [START maps_ui_kit_place_search_text_init_map] */
14+
let markers = {};
15+
let infoWindow;
16+
let center = { lat: 37.395641, lng: -122.077627 };
17+
18+
async function initMap(): Promise<void> {
19+
await google.maps.importLibrary("places");
20+
const { InfoWindow } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
21+
const { Place } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary;
22+
23+
infoWindow = new google.maps.InfoWindow;
24+
25+
// Center the map
26+
let adjustedCenter = offsetLatLngRight(center, -0.005);
27+
map.innerMap.panTo(adjustedCenter);
28+
map.innerMap.setZoom(14);
29+
30+
map.innerMap.setOptions({
31+
mapTypeControl: false,
32+
clickableIcons: false,
33+
});
34+
35+
searchByTextRequest('tacos near me');
36+
}
37+
/* [END maps_ui_kit_place_search_text_init_map] */
38+
39+
/* [START maps_ui_kit_place_search_text_query] */
40+
async function searchByTextRequest(textQuery) {
41+
if (textQuery) {
42+
placeList.configureFromSearchByTextRequest({
43+
locationRestriction: map.innerMap.getBounds(),
44+
includedType: "restaurant",
45+
textQuery: textQuery,
46+
}).then(addMarkers);
47+
// Handle user selection in Place Details.
48+
placeList.addEventListener("gmp-placeselect", ({ place }) => {
49+
markers[place.id].click();
50+
});
51+
}
52+
}
53+
/* [END maps_ui_kit_place_search_text_query] */
54+
/* [START maps_ui_kit_place_search_text_add_markers] */
55+
async function addMarkers(){
56+
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
57+
const { LatLngBounds } = await google.maps.importLibrary("core") as google.maps.CoreLibrary;
58+
59+
const bounds = new LatLngBounds();
60+
61+
if(placeList.places.length > 0){
62+
placeList.places.forEach((place) => {
63+
let marker = new AdvancedMarkerElement({
64+
map: map.innerMap,
65+
position: place.location,
66+
});
67+
68+
markers[place.id] = marker;
69+
bounds.extend(place.location);
70+
marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;
71+
72+
marker.addListener('gmp-click',(event) => {
73+
if(infoWindow.isOpen){
74+
infoWindow.close();
75+
}
76+
placeDetails.configureFromPlace(place);
77+
placeDetails.style.width = "350px";
78+
infoWindow.setOptions({
79+
content: placeDetails
80+
});
81+
infoWindow.open({
82+
anchor: marker,
83+
map: map.innerMap
84+
});
85+
placeDetails.addEventListener('gmp-load',() => {
86+
map.innerMap.fitBounds(place.viewport, { top: 400, left: 400 });
87+
});
88+
89+
});
90+
map.innerMap.setCenter(bounds.getCenter());
91+
map.innerMap.fitBounds(bounds);
92+
});
93+
}
94+
}
95+
/* [END maps_ui_kit_place_search_text_add_markers] */
96+
97+
// Helper function to offset the map center.
98+
function offsetLatLngRight(latLng, longitudeOffset) {
99+
const newLng = latLng.lng + longitudeOffset;
100+
return new google.maps.LatLng(latLng.lat, newLng);
101+
}
102+
103+
declare global {
104+
interface Window {
105+
initMap: () => void;
106+
}
107+
}
108+
window.initMap = initMap;
109+
/* [END maps_ui_kit_place_search_text] */
110+
export{};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "@js-api-samples/ui-kit-place-search-text",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"build": "tsc && bash ../jsfiddle.sh ui-kit-place-search-text && bash ../app.sh ui-kit-place-search-text && bash ../docs.sh ui-kit-place-search-text && npm run build:vite --workspace=. && bash ../dist.sh ui-kit-place-search-text",
6+
"test": "tsc && npm run build:vite --workspace=.",
7+
"start": "tsc && vite build --base './' && vite",
8+
"build:vite": "vite build --base './'",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
13+
}
14+
}
15+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* @license
3+
* Copyright 2025 Google LLC. All Rights Reserved.
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/* [START maps_ui_kit_place_search] */
7+
html,
8+
body {
9+
height: 100%;
10+
margin: 0;
11+
}
12+
13+
body {
14+
display: flex;
15+
flex-direction: column;
16+
font-family: Arial, Helvetica, sans-serif;
17+
}
18+
19+
h1 {
20+
font-size: 16px;
21+
text-align: center;
22+
}
23+
24+
gmp-map {
25+
box-sizing: border-box;
26+
height: 500px;
27+
}
28+
29+
.overlay {
30+
position: relative;
31+
top: 20px;
32+
margin: 20px;
33+
width: 400px;
34+
}
35+
36+
.controls {
37+
display: flex;
38+
gap: 10px;
39+
margin-bottom: 10px;
40+
height: 32px;
41+
}
42+
43+
.search-button {
44+
background-color: #5491f5;
45+
color: #fff;
46+
border: 1px solid #ccc;
47+
border-radius: 5px;
48+
width: 100px;
49+
cursor: pointer;
50+
}
51+
52+
.type-select {
53+
border: 1px solid #ccc;
54+
border-radius: 5px;
55+
flex-grow: 1;
56+
padding: 0 10px;
57+
}
58+
59+
.list-container {
60+
height: 400px;
61+
overflow: auto;
62+
border-radius: 10px;
63+
}
64+
65+
gmp-place-list {
66+
background-color: #fff;
67+
}
68+
/* [END maps_ui_kit_place_search] */
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"compilerOptions": {
3+
"module": "esnext",
4+
"target": "esnext",
5+
"strict": true,
6+
"noImplicitAny": false,
7+
"lib": [
8+
"es2015",
9+
"esnext",
10+
"es6",
11+
"dom",
12+
"dom.iterable"
13+
],
14+
"moduleResolution": "Node",
15+
"jsx": "preserve"
16+
}
17+
}

0 commit comments

Comments
 (0)