Skip to content

Commit 00c3c08

Browse files
committed
Updated UI Kit Place Text Search
1 parent 5e7933c commit 00c3c08

File tree

3 files changed

+197
-223
lines changed

3 files changed

+197
-223
lines changed

samples/ui-kit-place-search-text/index.html

Lines changed: 58 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,81 +4,78 @@
44
SPDX-License-Identifier: Apache-2.0
55
-->
66
<!--[START maps_ui_kit_place_search_text] -->
7-
<!doctype html>
7+
<!DOCTYPE html>
88
<html>
99
<head>
10-
<title>Place List Text Search with Google Maps</title>
10+
<title>Place Text Search with Google Maps</title>
1111
<meta charset="utf-8" />
1212
<link rel="stylesheet" type="text/css" href="style.css" />
13-
<script type="module" src="./index.js"></script>
13+
<script type="module" src="./index.js" defer></script>
14+
<!-- prettier-ignore -->
15+
<script>
16+
(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))})
17+
({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});
18+
</script>
1419
</head>
1520
<body>
1621
<!--[START maps_ui_kit_place_search_text_map] -->
17-
<gmp-map center="37.395641,-122.077627" zoom="10" map-id="DEMO_MAP_ID">
18-
<div class="overlay" slot="control-inline-start-block-start">
19-
<div class="text-search-container">
22+
23+
<div class="container">
24+
<div class="ui-panel">
25+
<div class="controls">
2026
<input
2127
type="text"
22-
id="textSearchInput"
23-
placeholder="Enter text search..." />
24-
<button id="textSearchButton">Search</button>
28+
id="query-input"
29+
class="query-input"
30+
placeholder="Search for a place"
31+
value="cafe" />
32+
<button id="search-button" class="search-button">
33+
Search
34+
</button>
2535
</div>
2636
<div class="list-container">
27-
<gmp-place-list
28-
selectable
29-
style="display: none"></gmp-place-list>
37+
<gmp-place-search selectable>
38+
<gmp-place-all-content></gmp-place-all-content>
39+
<gmp-place-text-search-request
40+
max-result-count="5"></gmp-place-text-search-request>
41+
</gmp-place-search>
3042
</div>
3143
</div>
32-
<gmp-place-details style="display: none">
33-
<gmp-place-details-place-request></gmp-place-details-place-request>
34-
<gmp-place-all-content></gmp-place-all-content>
35-
</gmp-place-details>
36-
</gmp-map>
44+
<!-- map-id is required to use advanced markers. See https://developers.google.com/maps/documentation/javascript/map-ids/mapid-over. -->
45+
<gmp-map center="-37.813,144.963" zoom="16" map-id="DEMO_MAP_ID">
46+
</gmp-map>
47+
</div>
48+
49+
<!--
50+
The gmp-place-details-compact element is styled inline because it is
51+
conditionally rendered and moved into the info window, which is
52+
part of the map's shadow DOM.
53+
-->
54+
<gmp-place-details-compact
55+
orientation="horizontal"
56+
truncation-preferred
57+
style="
58+
width: 400px;
59+
padding: 0;
60+
margin: 0;
61+
border: none;
62+
background-color: transparent;
63+
color-scheme: light;
64+
">
65+
<gmp-place-details-place-request></gmp-place-details-place-request>
66+
<gmp-place-content-config>
67+
<gmp-place-media></gmp-place-media>
68+
<gmp-place-rating></gmp-place-rating>
69+
<gmp-place-price></gmp-place-price>
70+
<gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon>
71+
<gmp-place-open-now-status></gmp-place-open-now-status>
72+
<gmp-place-attribution
73+
light-scheme-color="gray"
74+
dark-scheme-color="white"></gmp-place-attribution>
75+
</gmp-place-content-config>
76+
</gmp-place-details-compact>
77+
3778
<!--[END maps_ui_kit_place_search_text_map] -->
38-
<script>
39-
((g) => {
40-
var h,
41-
a,
42-
k,
43-
p = 'The Google Maps JavaScript API',
44-
c = 'google',
45-
l = 'importLibrary',
46-
q = '__ib__',
47-
m = document,
48-
b = window;
49-
b = b[c] || (b[c] = {});
50-
var d = b.maps || (b.maps = {}),
51-
r = new Set(),
52-
e = new URLSearchParams(),
53-
u = () =>
54-
h ||
55-
(h = new Promise(async (f, n) => {
56-
await (a = m.createElement('script'));
57-
e.set('libraries', [...r] + '');
58-
for (k in g)
59-
e.set(
60-
k.replace(
61-
/[A-Z]/g,
62-
(t) => '_' + t[0].toLowerCase()
63-
),
64-
g[k]
65-
);
66-
e.set('callback', c + '.maps.' + q);
67-
a.src =
68-
`https://maps.${c}apis.com/maps/api/js?` + e;
69-
d[q] = f;
70-
a.onerror = () =>
71-
(h = n(Error(p + ' could not load.')));
72-
a.nonce =
73-
m.querySelector('script[nonce]')?.nonce || '';
74-
m.head.append(a);
75-
}));
76-
d[l]
77-
? console.warn(p + ' only loads once. Ignoring:', g)
78-
: (d[l] = (f, ...n) =>
79-
r.add(f) && u().then(() => d[l](f, ...n)));
80-
})({ key: 'AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8', v: 'alpha' });
81-
</script>
8279
</body>
8380
</html>
8481
<!--[END maps_ui_kit_place_search_text] -->

samples/ui-kit-place-search-text/index.ts

Lines changed: 100 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -4,151 +4,128 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66
/* [START maps_ui_kit_place_search_text] */
7+
78
/* [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-
const textSearchInput = document.getElementById('textSearchInput') as any;
13-
const textSearchButton = document.getElementById(
14-
'textSearchButton'
15-
) as HTMLButtonElement;
16-
const placeDetailsRequest = document.querySelector(
9+
// Query selectors for various elements in the HTML file.
10+
const map = document.querySelector('gmp-map') as google.maps.MapElement;
11+
const placeSearch = document.querySelector('gmp-place-search') as any;
12+
const placeSearchQuery = document.querySelector(
13+
'gmp-place-text-search-request'
14+
) as any;
15+
const placeDetails = document.querySelector('gmp-place-details-compact') as any;
16+
const placeRequest = document.querySelector(
1717
'gmp-place-details-place-request'
1818
) as any;
19-
19+
const queryInput = document.querySelector('.query-input') as HTMLInputElement;
20+
const searchButton = document.querySelector(
21+
'.search-button'
22+
) as HTMLButtonElement;
2023
/* [END maps_ui_kit_place_search_text_query_selectors] */
21-
/* [START maps_ui_kit_place_search_text_init_map] */
22-
let markers = {};
23-
let infoWindow;
24-
let center = { lat: 37.395641, lng: -122.077627 }; // Mountain View, CA.
25-
let bounds;
26-
27-
async function initMap(): Promise<void> {
28-
const { Map, InfoWindow } = (await google.maps.importLibrary(
29-
'maps'
30-
)) as google.maps.MapsLibrary;
31-
const { Place } = (await google.maps.importLibrary(
32-
'places'
33-
)) as google.maps.PlacesLibrary;
34-
35-
// Set bounds for location restriction.
36-
bounds = new google.maps.LatLngBounds(
37-
{ lat: 37.37808200917261, lng: -122.13741583377849 },
38-
{ lat: 37.416676154341324, lng: -122.02261728794109 }
39-
);
40-
41-
infoWindow = new google.maps.InfoWindow();
42-
43-
// Center the map
44-
map.innerMap.panTo(center);
45-
map.innerMap.setZoom(14);
4624

47-
map.innerMap.setOptions({
48-
mapTypeControl: false,
49-
clickableIcons: false,
25+
// Global variables for the map, markers, and info window.
26+
const markers: Map<string, google.maps.marker.AdvancedMarkerElement> =
27+
new Map();
28+
let infoWindow: google.maps.InfoWindow;
29+
30+
// The init function is called when the page loads.
31+
async function init(): Promise<void> {
32+
// Import the necessary libraries from the Google Maps API.
33+
const [{ InfoWindow }, { Place }] = await Promise.all([
34+
google.maps.importLibrary('maps') as Promise<google.maps.MapsLibrary>,
35+
google.maps.importLibrary(
36+
'places'
37+
) as Promise<google.maps.PlacesLibrary>,
38+
]);
39+
40+
// Create a new info window and set its content to the place details element.
41+
placeDetails.remove(); // Hide the place details element because it is not needed until the info window opens
42+
infoWindow = new InfoWindow({
43+
content: placeDetails,
44+
ariaLabel: 'Place Details',
5045
});
5146

52-
/* [START maps_ui_kit_place_search_tex_event_handlers] */
53-
// Fire when the Place Details Element is loaded.
54-
placeDetails.addEventListener('gmp-load', (event) => {
55-
// Center the info window on the map.
56-
map.innerMap.fitBounds(placeDetails.place.viewport, {
57-
top: 500,
58-
left: 400,
59-
});
47+
// Set the map options.
48+
map.innerMap.setOptions({
49+
clickableIcons: false,
50+
mapTypeControl: false,
51+
streetViewControl: false,
6052
});
6153

62-
// Handle clicks on the search button.
63-
textSearchButton.addEventListener('click', searchByTextRequest);
64-
65-
// Handle enter key on text input.
66-
textSearchInput.addEventListener('keydown', (event) => {
54+
/* [START maps_ui_kit_place_search_text_event] */
55+
// Add event listeners to the query input and place search elements.
56+
searchButton.addEventListener('click', () => searchPlaces());
57+
queryInput.addEventListener('keydown', (event) => {
6758
if (event.key === 'Enter') {
68-
searchByTextRequest();
59+
searchPlaces();
6960
}
7061
});
71-
/* [END maps_ui_kit_place_search_tex_event_handlers] */
62+
63+
placeSearch.addEventListener('gmp-select', (event: Event) => {
64+
const { place } = event as any;
65+
markers.get(place.id)?.click();
66+
});
67+
placeSearch.addEventListener('gmp-load', () => {
68+
addMarkers();
69+
});
70+
71+
searchPlaces();
7272
}
73-
/* [END maps_ui_kit_place_search_text_init_map] */
74-
75-
/* [START maps_ui_kit_place_search_text_query] */
76-
async function searchByTextRequest() {
77-
if (textSearchInput.value !== '') {
78-
placeList.style.display = 'block';
79-
placeList
80-
.configureFromSearchByTextRequest({
81-
locationRestriction: bounds,
82-
textQuery: textSearchInput.value,
83-
})
84-
.then(addMarkers);
85-
// Handle user selection in Place Details.
86-
placeList.addEventListener('gmp-placeselect', ({ place }) => {
87-
markers[place.id].click();
88-
});
73+
/* [END maps_ui_kit_place_search_text_event] */
74+
// The searchPlaces function is called when the user changes the query input or when the page loads.
75+
async function searchPlaces() {
76+
// Close the info window and clear the markers.
77+
infoWindow.close();
78+
for (const marker of markers.values()) {
79+
marker.remove();
80+
}
81+
markers.clear();
82+
83+
// Set the place search query and add an event listener to the place search element.
84+
if (queryInput.value) {
85+
const center = map.center;
86+
if (center) {
87+
placeSearchQuery.locationBias = center;
88+
}
89+
// The textQuery property is required for the search element to load.
90+
// Any other configured properties will be ignored if textQuery is not set.
91+
placeSearchQuery.textQuery = queryInput.value;
8992
}
9093
}
91-
/* [END maps_ui_kit_place_search_text_query] */
9294

93-
/* [START maps_ui_kit_place_search_text_add_markers] */
95+
// The addMarkers function is called when the place search element loads.
9496
async function addMarkers() {
95-
const { AdvancedMarkerElement } = (await google.maps.importLibrary(
96-
'marker'
97-
)) as google.maps.MarkerLibrary;
98-
const { LatLngBounds } = (await google.maps.importLibrary(
99-
'core'
100-
)) as google.maps.CoreLibrary;
101-
97+
// Import the necessary libraries from the Google Maps API.
98+
const [{ AdvancedMarkerElement }, { LatLngBounds }] = await Promise.all([
99+
google.maps.importLibrary(
100+
'marker'
101+
) as Promise<google.maps.MarkerLibrary>,
102+
google.maps.importLibrary('core') as Promise<google.maps.CoreLibrary>,
103+
]);
102104
const bounds = new LatLngBounds();
103105

104-
// First remove all existing markers.
105-
for (marker in markers) {
106-
markers[marker].map = null;
106+
if (placeSearch.places.length === 0) {
107+
return;
107108
}
108-
markers = {};
109-
110-
if (placeList.places.length > 0) {
111-
placeList.places.forEach((place) => {
112-
let marker = new AdvancedMarkerElement({
113-
map: map.innerMap,
114-
position: place.location,
115-
});
116-
117-
markers[place.id] = marker;
118-
bounds.extend(place.location);
119-
marker.collisionBehavior =
120-
google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL;
121-
122-
/* [START maps_ui_kit_place_search_text_click_event] */
123-
marker.addListener('gmp-click', (event) => {
124-
if (infoWindow.isOpen) {
125-
infoWindow.close();
126-
}
127-
// Set the Place Details request to the selected place.
128-
placeDetailsRequest.place = place.id;
129-
placeDetails.style.display = 'block';
130-
placeDetails.style.width = '350px';
131-
infoWindow.setOptions({
132-
content: placeDetails,
133-
});
134-
infoWindow.open({
135-
anchor: marker,
136-
map: map.innerMap,
137-
});
138-
placeDetails.addEventListener('gmp-load', () => {
139-
map.innerMap.fitBounds(place.viewport, {
140-
top: 400,
141-
left: 400,
142-
});
143-
});
144-
});
145-
/* [END maps_ui_kit_place_search_text_click_event] */
146-
map.innerMap.setCenter(bounds.getCenter());
147-
map.innerMap.fitBounds(bounds);
109+
110+
for (const place of placeSearch.places) {
111+
const marker = new AdvancedMarkerElement({
112+
map: map.innerMap,
113+
position: place.location,
114+
collisionBehavior:
115+
google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL,
116+
});
117+
118+
markers.set(place.id, marker);
119+
bounds.extend(place.location);
120+
121+
marker.addListener('click', () => {
122+
placeRequest.place = place;
123+
infoWindow.open(map.innerMap, marker);
148124
});
149125
}
126+
127+
map.innerMap.fitBounds(bounds);
150128
}
151-
/* [END maps_ui_kit_place_search_text_add_markers] */
152129

153-
initMap();
130+
init();
154131
/* [END maps_ui_kit_place_search_text] */

0 commit comments

Comments
 (0)