|
4 | 4 | * SPDX-License-Identifier: Apache-2.0 |
5 | 5 | */ |
6 | 6 | /* [START maps_ui_kit_place_search_text] */ |
| 7 | + |
7 | 8 | /* [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( |
17 | 17 | 'gmp-place-details-place-request' |
18 | 18 | ) as any; |
19 | | - |
| 19 | +const queryInput = document.querySelector('.query-input') as HTMLInputElement; |
| 20 | +const searchButton = document.querySelector( |
| 21 | + '.search-button' |
| 22 | +) as HTMLButtonElement; |
20 | 23 | /* [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); |
46 | 24 |
|
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', |
50 | 45 | }); |
51 | 46 |
|
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, |
60 | 52 | }); |
61 | 53 |
|
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) => { |
67 | 58 | if (event.key === 'Enter') { |
68 | | - searchByTextRequest(); |
| 59 | + searchPlaces(); |
69 | 60 | } |
70 | 61 | }); |
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(); |
72 | 72 | } |
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; |
89 | 92 | } |
90 | 93 | } |
91 | | -/* [END maps_ui_kit_place_search_text_query] */ |
92 | 94 |
|
93 | | -/* [START maps_ui_kit_place_search_text_add_markers] */ |
| 95 | +// The addMarkers function is called when the place search element loads. |
94 | 96 | 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 | + ]); |
102 | 104 | const bounds = new LatLngBounds(); |
103 | 105 |
|
104 | | - // First remove all existing markers. |
105 | | - for (marker in markers) { |
106 | | - markers[marker].map = null; |
| 106 | + if (placeSearch.places.length === 0) { |
| 107 | + return; |
107 | 108 | } |
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); |
148 | 124 | }); |
149 | 125 | } |
| 126 | + |
| 127 | + map.innerMap.fitBounds(bounds); |
150 | 128 | } |
151 | | -/* [END maps_ui_kit_place_search_text_add_markers] */ |
152 | 129 |
|
153 | | -initMap(); |
| 130 | +init(); |
154 | 131 | /* [END maps_ui_kit_place_search_text] */ |
0 commit comments