Place Search Element

Select platform: Android iOS JavaScript

The PlaceSearchElement is an HTML element that renders the results of a place search in a list. There are two ways to configure the gmp-place-search element:

Search nearby request

Select a place type from the menu to see nearby search results for that place type.

The following example renders the Place Search element in response to a nearby search. For simplicity, only three place types are listed: cafe, restaurant, and EV charging station. When a result is selected, a marker and PlaceDetailsCompactElement are displayed for the selected place. To add the Place Search element to the map, add a gmp-place-search element containing a gmp-place-nearby-search-request element to the HTML page as shown in the following snippet:

<div class="list-container">
  <div id="map-container"></div>
  <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>
  </div>

<div class="list-container">
  <gmp-place-search orientation="vertical" selectable>
      <gmp-place-all-content> </gmp-place-all-content>
      <gmp-place-nearby-search-request
      ></gmp-place-nearby-search-request>
  </gmp-place-search>
</div>

<div id="details-container">
   <gmp-place-details-compact orientation="horizontal">
      <gmp-place-details-place-request></gmp-place-details-place-request>
      <gmp-place-all-content></gmp-place-all-content>
  </gmp-place-details-compact>
</div>

Several querySelector calls are used to select the page elements for interaction:

  
 const 
  
 mapContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "map-container" 
 ); 
  
 const 
  
 placeSearch 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-search" 
 ); 
  
 const 
  
 placeSearchQuery 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-nearby-search-request" 
 ); 
  
 const 
  
 detailsContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "details-container" 
 ); 
  
 const 
  
 placeDetails 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-compact" 
 ); 
  
 const 
  
 placeRequest 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-place-request" 
 ); 
  
 const 
  
 typeSelect 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 ".type-select" 
 ); 

When the user selects a place type from the menu, the gmp-place-nearby-search-request element is updated, and the Place Search element displays the results (markers are added in the addMarkers helper function):

  
 typeSelect 
 . 
 addEventListener 
 ( 
 'change' 
 , 
  
 ( 
 event 
 ) 
  
 => 
  
 { 
  
 event 
 . 
 preventDefault 
 (); 
  
 searchPlaces 
 (); 
 }); 
 function 
  
 searchPlaces 
 (){ 
  
 const 
  
 bounds 
  
 = 
  
 gMap 
 . 
 getBounds 
 (); 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 null 
 ; 
  
 if 
  
 ( 
 typeSelect 
 . 
 value 
 ) 
  
 { 
  
 placeSearch 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 placeSearchQuery 
 . 
 maxResultCount 
  
 = 
  
 10 
 ; 
  
 placeSearchQuery 
 . 
 locationRestriction 
  
 = 
  
 { 
  
 center 
 : 
  
 cent 
 , 
  
 radius 
 : 
  
 1000 
  
 }; 
  
 placeSearchQuery 
 . 
 includedTypes 
  
 = 
  
 [ 
 typeSelect 
 . 
 value 
 ]; 
  
 placeSearch 
 . 
 addEventListener 
 ( 
 'gmp-load' 
 , 
  
 addMarkers 
 , 
  
 { 
  
 once 
 : 
  
 true 
  
 }); 
  
 } 
 } 

See the complete code example

JavaScript

  
 const 
  
 mapContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "map-container" 
 ); 
  
 const 
  
 placeSearch 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-search" 
 ); 
  
 const 
  
 placeSearchQuery 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-nearby-search-request" 
 ); 
  
 const 
  
 detailsContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "details-container" 
 ); 
  
 const 
  
 placeDetails 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-compact" 
 ); 
  
 const 
  
 placeRequest 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-place-request" 
 ); 
  
 const 
  
 typeSelect 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 ".type-select" 
 ); 
  
 let 
  
 markers 
  
 = 
  
 {}; 
  
 let 
  
 gMap 
 ; 
  
 let 
  
 placeDetailsPopup 
 ; 
  
 let 
  
 spherical 
 ; 
  
 let 
  
 AdvancedMarkerElement 
 ; 
  
 let 
  
 LatLngBounds 
 ; 
  
 let 
  
 LatLng 
 ; 
  
 async 
  
 function 
  
 init 
 () 
  
 { 
  
 console 
 . 
 log 
 ( 
 "init" 
 ); 
  
 ({ 
  
 spherical 
  
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 'geometry' 
 )); 
  
 const 
  
 { 
 Map 
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "maps" 
 ); 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "places" 
 ); 
  
 ({ 
 AdvancedMarkerElement 
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "marker" 
 )); 
  
 ({ 
 LatLngBounds 
 , 
  
 LatLng 
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "core" 
 )); 
  
 let 
  
 mapOptions 
  
 = 
  
 { 
  
 center 
 : 
  
 { 
 lat 
 : 
  
 - 
 37.813 
 , 
  
 lng 
 : 
  
 144.963 
 }, 
  
 zoom 
 : 
  
 16 
 , 
  
 mapTypeControl 
 : 
  
 false 
 , 
  
 clickableIcons 
 : 
  
 false 
 , 
  
 mapId 
 : 
  
 'DEMO_MAP_ID' 
  
 }; 
  
 gMap 
  
 = 
  
 new 
  
 Map 
 ( 
 mapContainer 
 , 
  
 mapOptions 
 ); 
  
 placeDetailsPopup 
  
 = 
  
 new 
  
 AdvancedMarkerElement 
 ({ 
  
 map 
 : 
  
 null 
 , 
  
 content 
 : 
  
 placeDetails 
 , 
  
 zIndex 
 : 
  
 100 
  
 }); 
  
 findCurrentLocation 
 (); 
  
 gMap 
 . 
 addListener 
 ( 
 'click' 
 , 
  
 ( 
 e 
 ) 
  
 => 
  
 { 
  
 hidePlaceDetailsPopup 
 (); 
  
 }); 
  
 typeSelect 
 . 
 addEventListener 
 ( 
 'change' 
 , 
  
 ( 
 event 
 ) 
  
 => 
  
 { 
  
 event 
 . 
 preventDefault 
 (); 
  
 searchPlaces 
 (); 
  
 }); 
  
 placeSearch 
 . 
 addEventListener 
 ( 
 "gmp-select" 
 , 
  
 ({ 
  
 place 
  
 }) 
  
 => 
  
 { 
  
 if 
  
 ( 
 markers 
 [ 
 place 
 . 
 id 
 ]) 
  
 { 
  
 markers 
 [ 
 place 
 . 
 id 
 ]. 
 click 
 (); 
  
 } 
  
 }); 
  
 } 
  
 function 
  
 searchPlaces 
 (){ 
  
 const 
  
 bounds 
  
 = 
  
 gMap 
 . 
 getBounds 
 (); 
  
 const 
  
 cent 
  
 = 
  
 gMap 
 . 
 getCenter 
 (); 
  
 const 
  
 ne 
  
 = 
  
 bounds 
 . 
 getNorthEast 
 (); 
  
 const 
  
 sw 
  
 = 
  
 bounds 
 . 
 getSouthWest 
 (); 
  
 const 
  
 diameter 
  
 = 
  
 spherical 
 . 
 computeDistanceBetween 
 ( 
 ne 
 , 
  
 sw 
 ); 
  
 const 
  
 cappedRadius 
  
 = 
  
 Math 
 . 
 min 
 (( 
 diameter 
  
 / 
  
 2 
  
 ), 
  
 50000 
 ); 
  
 // Radius cannot be more than 50000. 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 null 
 ; 
  
 for 
 ( 
 const 
  
 markerId 
  
 in 
  
 markers 
 ){ 
  
 if 
  
 ( 
 Object 
 . 
 prototype 
 . 
 hasOwnProperty 
 . 
 call 
 ( 
 markers 
 , 
  
 markerId 
 )) 
  
 { 
  
 markers 
 [ 
 markerId 
 ]. 
 map 
  
 = 
  
 null 
 ; 
  
 } 
  
 } 
  
 markers 
  
 = 
  
 {}; 
  
 if 
  
 ( 
 typeSelect 
 . 
 value 
 ) 
  
 { 
  
 mapContainer 
 . 
 style 
 . 
 height 
  
 = 
  
 '75vh' 
 ; 
  
 placeSearch 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 placeSearchQuery 
 . 
 maxResultCount 
  
 = 
  
 10 
 ; 
  
 placeSearchQuery 
 . 
 locationRestriction 
  
 = 
  
 { 
  
 center 
 : 
  
 cent 
 , 
  
 radius 
 : 
  
 cappedRadius 
  
 }; 
  
 placeSearchQuery 
 . 
 includedTypes 
  
 = 
  
 [ 
 typeSelect 
 . 
 value 
 ]; 
  
 placeSearch 
 . 
 addEventListener 
 ( 
 'gmp-load' 
 , 
  
 addMarkers 
 , 
  
 { 
  
 once 
 : 
  
 true 
  
 }); 
  
 console 
 . 
 log 
 ( 
 "selection!" 
 ); 
  
 console 
 . 
 log 
 ( 
 cappedRadius 
 ); 
  
 } 
  
 } 
  
 async 
  
 function 
  
 addMarkers 
 (){ 
  
 const 
  
 bounds 
  
 = 
  
 new 
  
 LatLngBounds 
 (); 
  
 placeSearch 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 if 
 ( 
 placeSearch 
 . 
 places 
 . 
 length 
  
 > 
  
 0 
 ){ 
  
 placeSearch 
 . 
 places 
 . 
 forEach 
 (( 
 place 
 ) 
  
 => 
  
 { 
  
 let 
  
 marker 
  
 = 
  
 new 
  
 AdvancedMarkerElement 
 ({ 
  
 map 
 : 
  
 gMap 
 , 
  
 position 
 : 
  
 place 
 . 
 location 
  
 }); 
  
 marker 
 . 
 metadata 
  
 = 
  
 { 
 id 
 : 
  
 place 
 . 
 id 
 }; 
  
 markers 
 [ 
 place 
 . 
 id 
 ] 
  
 = 
  
 marker 
 ; 
  
 bounds 
 . 
 extend 
 ( 
 place 
 . 
 location 
 ); 
  
 marker 
 . 
 addListener 
 ( 
 'click' 
 ,( 
 event 
 ) 
  
 => 
  
 { 
  
 placeRequest 
 . 
 place 
  
 = 
  
 place 
 ; 
  
 placeDetails 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 placeDetailsPopup 
 . 
 position 
  
 = 
  
 place 
 . 
 location 
 ; 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 gMap 
 ; 
  
 gMap 
 . 
 fitBounds 
 ( 
 place 
 . 
 viewport 
 , 
  
 { 
 top 
 : 
  
 0 
 , 
  
 left 
 : 
  
 400 
 }); 
  
 placeDetails 
 . 
 addEventListener 
 ( 
 'gmp-load' 
 ,() 
  
 => 
  
 { 
  
 gMap 
 . 
 fitBounds 
 ( 
 place 
 . 
 viewport 
 , 
  
 { 
 top 
 : 
  
 0 
 , 
  
 right 
 : 
  
 450 
 }); 
  
 }, 
  
 { 
  
 once 
 : 
  
 true 
  
 }); 
  
 }); 
  
 gMap 
 . 
 setCenter 
 ( 
 bounds 
 . 
 getCenter 
 ()); 
  
 gMap 
 . 
 fitBounds 
 ( 
 bounds 
 ); 
  
 }); 
  
 } 
  
 } 
  
 async 
  
 function 
  
 findCurrentLocation 
 (){ 
  
 const 
  
 { 
  
 LatLng 
  
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "core" 
 ); 
  
 if 
  
 ( 
 navigator 
 . 
 geolocation 
 ) 
  
 { 
  
 navigator 
 . 
 geolocation 
 . 
 getCurrentPosition 
 ( 
  
 ( 
 position 
 ) 
  
 => 
  
 { 
  
 const 
  
 pos 
  
 = 
  
 new 
  
 LatLng 
 ( 
 position 
 . 
 coords 
 . 
 latitude 
 , 
 position 
 . 
 coords 
 . 
 longitude 
 ); 
  
 gMap 
 . 
 panTo 
 ( 
 pos 
 ); 
  
 gMap 
 . 
 setZoom 
 ( 
 16 
 ); 
  
 }, 
  
 () 
  
 => 
  
 { 
  
 console 
 . 
 log 
 ( 
 'The Geolocation service failed.' 
 ); 
  
 gMap 
 . 
 setZoom 
 ( 
 16 
 ); 
  
 }, 
  
 ); 
  
 } 
  
 else 
  
 { 
  
 console 
 . 
 log 
 ( 
 "Your browser doesn't support geolocation" 
 ); 
  
 gMap 
 . 
 setZoom 
 ( 
 16 
 ); 
  
 } 
  
 } 
  
 function 
  
 hidePlaceDetailsPopup 
 () 
  
 { 
  
 if 
  
 ( 
 placeDetailsPopup 
 . 
 map 
 ) 
  
 { 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 null 
 ; 
  
 placeDetails 
 . 
 style 
 . 
 display 
  
 = 
  
 'none' 
 ; 
  
 } 
  
 } 
  
 init 
 (); 
  

CSS

  
 html 
 , 
  
 body 
  
 { 
  
 height 
 : 
  
 100 
 % 
 ; 
  
 margin 
 : 
  
 0 
 ; 
  
 } 
  
 body 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 flex-direction 
 : 
  
 column 
 ; 
  
 font-family 
 : 
  
 Arial 
 , 
  
 Helvetica 
 , 
  
 sans-serif 
 ; 
  
 } 
  
 h1 
  
 { 
  
 font-size 
 : 
  
 large 
 ; 
  
 text-align 
 : 
  
 center 
 ; 
  
 } 
  
 # 
 map-container 
  
 { 
  
 flex-grow 
 : 
  
 1 
 ; 
  
 max-height 
 : 
 600 
 px 
 ; 
  
 box-sizing 
 : 
  
 border-box 
 ; 
  
 width 
 : 
  
 100 
 % 
 ; 
  
 height 
 : 
  
 100 
 vh 
 ; 
  
 } 
  
 . 
 controls 
  
 { 
  
 position 
 : 
  
 absolute 
 ; 
  
 top 
 : 
  
 40 
 px 
 ; 
  
 right 
 : 
  
 40 
 px 
 ; 
  
 } 
  
 . 
 list-container 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 position 
 : 
  
 absolute 
 ; 
  
 max-height 
 : 
  
 500 
 px 
 ; 
  
 top 
 : 
  
 80 
 px 
 ; 
  
 right 
 : 
  
 40 
 px 
 ; 
  
 overflow-y 
 : 
  
 none 
 ; 
  
 } 
  
 . 
 type-select 
  
 { 
  
 width 
 : 
  
 400 
 px 
 ; 
  
 height 
 : 
  
 32 
 px 
 ; 
  
 border 
 : 
  
 1 
 px 
  
 solid 
  
 #000 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 flex-grow 
 : 
  
 1 
 ; 
  
 padding 
 : 
  
 0 
  
 10 
 px 
 ; 
  
 } 
  
 gmp-place-search 
  
 { 
  
 width 
 : 
  
 400 
 px 
 ; 
  
 margin 
 : 
  
 0 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 display 
 : 
  
 none 
 ; 
  
 border 
 : 
  
 none 
 ; 
  
 } 
  
 gmp-place-details-compact 
  
 { 
  
 width 
 : 
  
 350 
 px 
 ; 
  
 max-height 
 : 
  
 800 
 px 
 ; 
  
 margin-right 
 : 
  
 20 
 px 
 ; 
  
 display 
 : 
  
 none 
 ; 
  
 border 
 : 
  
 none 
 ; 
  
 } 
  
 gmp-place-details-compact 
 :: 
 after 
  
 { 
  
 content 
 : 
  
 '' 
 ; 
  
 position 
 : 
  
 absolute 
 ; 
  
 bottom 
 : 
  
 -18 
 px 
 ; 
  
 left 
 : 
  
 50 
 % 
 ; 
  
 transform 
 : 
  
 translateX 
 ( 
 -50 
 % 
 ); 
  
 width 
 : 
  
 20 
 px 
 ; 
  
 height 
 : 
  
 20 
 px 
 ; 
  
 background-color 
 : 
  
 white 
 ; 
  
 box-shadow 
 : 
  
 2 
 px 
  
 2 
 px 
  
 5 
 px 
  
 0 
  
 rgba 
 ( 
 0 
 , 
 0 
 , 
 0 
 , 
 0.2 
 ); 
  
 z-index 
 : 
  
 1 
 ; 
  
 clip-path 
 : 
  
 polygon 
 ( 
 0 
 % 
  
 0 
 % 
 , 
  
 100 
 % 
  
 0 
 % 
 , 
  
 50 
 % 
  
 100 
 % 
 ); 
  
 transform-origin 
 : 
  
 center 
  
 center 
 ; 
  
 } 
  
 @ 
 media 
  
 ( 
 prefers-color-scheme 
 : 
  
 dark 
 ) 
  
 { 
  
 /* Style for Dark mode */ 
  
 gmp-place-details-compact 
 :: 
 after 
  
 { 
  
 background-color 
 : 
  
 #131314 
 ; 
  
 } 
  
 } 
  

HTML

<!DOCTYPE html>
  <html>
    <head>
      <title>Place Search with Compact Place Details Element</title>
      <meta charset="utf-8">
      <link rel="stylesheet" href="style.css">
      <script type="module" src="./index.js"></script>
    </head>
    <body>
      <div id="map-container"></div>
      <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>
      </div>
      <div class="list-container">
          <gmp-place-search orientation="vertical" selectable>
              <gmp-place-all-content> </gmp-place-all-content>
              <gmp-place-nearby-search-request
              ></gmp-place-nearby-search-request>
          </gmp-place-search>
      </div>
      <div id="details-container">
          <gmp-place-details-compact orientation="horizontal">
            <gmp-place-details-place-request></gmp-place-details-place-request>
            <gmp-place-all-content></gmp-place-all-content>
          </gmp-place-details-compact>
      </div>
      <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: "YOUR_API_KEY", v: "weekly"});
      </script>
    </body>
  </html>

Search by text request

Enter a search term in the input field and click the Search button to get a list of places that match the term.

This example renders the Place Search element in response to a user text search. When a result is selected, a marker and PlaceDetailsCompactElement are displayed for the selected place. To add the Place Search element to the map, add a gmp-place-search element containing a gmp-place-search-text-search-request element to the HTML page as shown in the following snippet:

<div id="map-container"></div>
  <div class="controls">
  <input type="text" class="query-input" />
  <button class="search-button">Search</button>
  </div>

  <div class="list-container">
    <gmp-place-search orientation="vertical" selectable>
        <gmp-place-all-content> </gmp-place-all-content>
        <gmp-place-text-search-request></gmp-place-text-search-request>
    </gmp-place-search>
  </div>

  <div id="details-container">
      <gmp-place-details-compact orientation="horizontal">
          <gmp-place-details-place-request></gmp-place-details-place-request>
          <gmp-place-all-content></gmp-place-all-content>
      </gmp-place-details-compact>
  </div>

Several querySelector calls are used to select the page elements for interaction:

  
 const 
  
 mapContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "map-container" 
 ); 
  
 const 
  
 placeSearch 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-search" 
 ); 
  
 const 
  
 placeSearchQuery 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-text-search-request" 
 ); 
  
 const 
  
 queryInput 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 ".query-input" 
 ); 
  
 const 
  
 searchButton 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 ".search-button" 
 ); 
  
 const 
  
 detailsContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "details-container" 
 ); 
  
 const 
  
 placeDetails 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-compact" 
 ); 
  
 const 
  
 placeRequest 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-place-request" 
 ); 

When the search function is run after the user enters a search query, the gmp-place-text-search-request element is updated, and the Place Search element displays the results (markers are added in the addMarkers helper function):

 searchButton 
 . 
 addEventListener 
 ( 
 "click" 
 , 
  
 searchPlaces 
 ); 
 queryInput 
 . 
 addEventListener 
 ( 
 "keydown" 
 , 
  
 ( 
 event 
 ) 
  
 => 
  
 { 
  
 if 
  
 ( 
 event 
 . 
 key 
  
 == 
  
 'Enter' 
 ) 
  
 { 
  
 event 
 . 
 preventDefault 
 (); 
  
 searchPlaces 
 (); 
  
 } 
  
 }); 
 function 
  
 searchPlaces 
 (){ 
  
 if 
  
 ( 
 queryInput 
 . 
 value 
 ) 
  
 { 
  
 placeSearch 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 placeSearchQuery 
 . 
 textQuery 
  
 = 
  
 queryInput 
 . 
 value 
 ; 
  
 placeSearchQuery 
 . 
 locationBias 
  
 = 
  
 gMap 
 . 
 getBounds 
 (); 
  
 placeSearch 
 . 
 addEventListener 
 ( 
 'gmp-load' 
 , 
  
 addMarkers 
 , 
  
 { 
  
 once 
 : 
  
 true 
  
 }); 
  
 } 
 } 

See the complete code example

JavaScript

  
 const 
  
 mapContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "map-container" 
 ); 
  
 const 
  
 placeSearch 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-search" 
 ); 
  
 const 
  
 placeSearchQuery 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-text-search-request" 
 ); 
  
 const 
  
 queryInput 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 ".query-input" 
 ); 
  
 const 
  
 searchButton 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 ".search-button" 
 ); 
  
 const 
  
 detailsContainer 
  
 = 
  
 document 
 . 
 getElementById 
 ( 
 "details-container" 
 ); 
  
 const 
  
 placeDetails 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-compact" 
 ); 
  
 const 
  
 placeRequest 
  
 = 
  
 document 
 . 
 querySelector 
 ( 
 "gmp-place-details-place-request" 
 ); 
  
 let 
  
 markers 
  
 = 
  
 {}; 
  
 let 
  
 previousSearchQuery 
  
 = 
  
 '' 
 ; 
  
 let 
  
 gMap 
 ; 
  
 let 
  
 placeDetailsPopup 
 ; 
  
 let 
  
 AdvancedMarkerElement 
 ; 
  
 let 
  
 LatLngBounds 
 ; 
  
 let 
  
 LatLng 
 ; 
  
 async 
  
 function 
  
 init 
 () 
  
 { 
  
 const 
  
 { 
 Map 
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "maps" 
 ); 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "places" 
 ); 
  
 ({ 
 AdvancedMarkerElement 
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "marker" 
 )); 
  
 ({ 
 LatLngBounds 
 , 
  
 LatLng 
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "core" 
 )); 
  
 let 
  
 mapOptions 
  
 = 
  
 { 
  
 center 
 : 
  
 { 
 lat 
 : 
  
 37.422 
 , 
  
 lng 
 : 
  
 - 
 122.085 
 }, 
  
 zoom 
 : 
  
 2 
 , 
  
 mapTypeControl 
 : 
  
 false 
 , 
  
 clickableIcons 
 : 
  
 false 
 , 
  
 mapId 
 : 
  
 'DEMO_MAP_ID' 
  
 }; 
  
 gMap 
  
 = 
  
 new 
  
 Map 
 ( 
 mapContainer 
 , 
  
 mapOptions 
 ); 
  
 placeDetailsPopup 
  
 = 
  
 new 
  
 AdvancedMarkerElement 
 ({ 
  
 map 
 : 
  
 null 
 , 
  
 content 
 : 
  
 placeDetails 
 , 
  
 zIndex 
 : 
  
 100 
  
 }); 
  
 findCurrentLocation 
 (); 
  
 gMap 
 . 
 addListener 
 ( 
 'click' 
 , 
  
 ( 
 e 
 ) 
  
 => 
  
 { 
  
 hidePlaceDetailsPopup 
 (); 
  
 }); 
  
 searchButton 
 . 
 addEventListener 
 ( 
 "click" 
 , 
  
 searchPlaces 
 ); 
  
 queryInput 
 . 
 addEventListener 
 ( 
 "keydown" 
 , 
  
 ( 
 event 
 ) 
  
 => 
  
 { 
  
 if 
  
 ( 
 event 
 . 
 key 
  
 == 
  
 'Enter' 
 ) 
  
 { 
  
 event 
 . 
 preventDefault 
 (); 
  
 searchPlaces 
 (); 
  
 } 
  
 }); 
  
 placeSearch 
 . 
 addEventListener 
 ( 
 "gmp-select" 
 , 
  
 ({ 
  
 place 
  
 }) 
  
 => 
  
 { 
  
 if 
  
 ( 
 markers 
 [ 
 place 
 . 
 id 
 ]) 
  
 { 
  
 markers 
 [ 
 place 
 . 
 id 
 ]. 
 click 
 (); 
  
 } 
  
 }); 
  
 } 
  
 function 
  
 searchPlaces 
 (){ 
  
 if 
  
 ( 
 queryInput 
 . 
 value 
 . 
 trim 
 () 
  
 === 
  
 previousSearchQuery 
 ) 
  
 { 
  
 return 
 ; 
  
 } 
  
 previousSearchQuery 
  
 = 
  
 queryInput 
 . 
 value 
 . 
 trim 
 (); 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 null 
 ; 
  
 for 
 ( 
 const 
  
 markerId 
  
 in 
  
 markers 
 ){ 
  
 if 
  
 ( 
 Object 
 . 
 prototype 
 . 
 hasOwnProperty 
 . 
 call 
 ( 
 markers 
 , 
  
 markerId 
 )) 
  
 { 
  
 markers 
 [ 
 markerId 
 ]. 
 map 
  
 = 
  
 null 
 ; 
  
 } 
  
 } 
  
 markers 
  
 = 
  
 {}; 
  
 if 
  
 ( 
 queryInput 
 . 
 value 
 ) 
  
 { 
  
 // mapContainer.style.height = '75vh'; 
  
 placeSearch 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 placeSearchQuery 
 . 
 textQuery 
  
 = 
  
 queryInput 
 . 
 value 
 ; 
  
 placeSearchQuery 
 . 
 locationBias 
  
 = 
  
 gMap 
 . 
 getBounds 
 (); 
  
 placeSearch 
 . 
 addEventListener 
 ( 
 'gmp-load' 
 , 
  
 addMarkers 
 , 
  
 { 
  
 once 
 : 
  
 true 
  
 }); 
  
 } 
  
 } 
  
 async 
  
 function 
  
 addMarkers 
 (){ 
  
 const 
  
 bounds 
  
 = 
  
 new 
  
 LatLngBounds 
 (); 
  
 if 
 ( 
 placeSearch 
 . 
 places 
 . 
 length 
  
 > 
  
 0 
 ){ 
  
 placeSearch 
 . 
 places 
 . 
 forEach 
 (( 
 place 
 ) 
  
 => 
  
 { 
  
 let 
  
 marker 
  
 = 
  
 new 
  
 AdvancedMarkerElement 
 ({ 
  
 map 
 : 
  
 gMap 
 , 
  
 position 
 : 
  
 place 
 . 
 location 
  
 }); 
  
 marker 
 . 
 metadata 
  
 = 
  
 { 
 id 
 : 
  
 place 
 . 
 id 
 }; 
  
 markers 
 [ 
 place 
 . 
 id 
 ] 
  
 = 
  
 marker 
 ; 
  
 bounds 
 . 
 extend 
 ( 
 place 
 . 
 location 
 ); 
  
 marker 
 . 
 addListener 
 ( 
 'click' 
 ,( 
 event 
 ) 
  
 => 
  
 { 
  
 placeRequest 
 . 
 place 
  
 = 
  
 place 
 ; 
  
 placeDetails 
 . 
 style 
 . 
 display 
  
 = 
  
 'block' 
 ; 
  
 placeDetailsPopup 
 . 
 position 
  
 = 
  
 place 
 . 
 location 
 ; 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 gMap 
 ; 
  
 gMap 
 . 
 fitBounds 
 ( 
 place 
 . 
 viewport 
 , 
  
 { 
 top 
 : 
  
 200 
 , 
  
 right 
 : 
  
 450 
 }); 
  
 }); 
  
 gMap 
 . 
 setCenter 
 ( 
 bounds 
 . 
 getCenter 
 ()); 
  
 gMap 
 . 
 fitBounds 
 ( 
 bounds 
 ); 
  
 }); 
  
 } 
  
 } 
  
 async 
  
 function 
  
 findCurrentLocation 
 (){ 
  
 const 
  
 { 
  
 LatLng 
  
 } 
  
 = 
  
 await 
  
 google 
 . 
 maps 
 . 
 importLibrary 
 ( 
 "core" 
 ); 
  
 if 
  
 ( 
 navigator 
 . 
 geolocation 
 ) 
  
 { 
  
 navigator 
 . 
 geolocation 
 . 
 getCurrentPosition 
 ( 
  
 ( 
 position 
 ) 
  
 => 
  
 { 
  
 const 
  
 pos 
  
 = 
  
 new 
  
 LatLng 
 ( 
 position 
 . 
 coords 
 . 
 latitude 
 , 
 position 
 . 
 coords 
 . 
 longitude 
 ); 
  
 gMap 
 . 
 panTo 
 ( 
 pos 
 ); 
  
 gMap 
 . 
 setZoom 
 ( 
 16 
 ); 
  
 }, 
  
 () 
  
 => 
  
 { 
  
 console 
 . 
 log 
 ( 
 'The Geolocation service failed.' 
 ); 
  
 gMap 
 . 
 setZoom 
 ( 
 16 
 ); 
  
 }, 
  
 ); 
  
 } 
  
 else 
  
 { 
  
 console 
 . 
 log 
 ( 
 "Your browser doesn't support geolocation" 
 ); 
  
 gMap 
 . 
 setZoom 
 ( 
 16 
 ); 
  
 } 
  
 } 
  
 function 
  
 hidePlaceDetailsPopup 
 () 
  
 { 
  
 if 
  
 ( 
 placeDetailsPopup 
 . 
 map 
 ) 
  
 { 
  
 placeDetailsPopup 
 . 
 map 
  
 = 
  
 null 
 ; 
  
 placeDetails 
 . 
 style 
 . 
 display 
  
 = 
  
 'none' 
 ; 
  
 } 
  
 } 
  
 init 
 (); 

CSS

  
 html 
 , 
  
 body 
  
 { 
  
 height 
 : 
  
 100 
 % 
 ; 
  
 margin 
 : 
  
 0 
 ; 
  
 } 
  
 body 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 flex-direction 
 : 
  
 column 
 ; 
  
 font-family 
 : 
  
 Arial 
 , 
  
 Helvetica 
 , 
  
 sans-serif 
 ; 
  
 } 
  
 h1 
  
 { 
  
 font-size 
 : 
  
 large 
 ; 
  
 text-align 
 : 
  
 center 
 ; 
  
 } 
  
 # 
 map-container 
  
 { 
  
 flex-grow 
 : 
  
 1 
 ; 
  
 max-height 
 : 
 600 
 px 
 ; 
  
 box-sizing 
 : 
  
 border-box 
 ; 
  
 width 
 : 
  
 100 
 % 
 ; 
  
 height 
 : 
  
 100 
 vh 
 ; 
  
 } 
  
 . 
 controls 
  
 { 
  
 border-radius 
 : 
  
 5 
 px 
 ; 
  
 position 
 : 
  
 absolute 
 ; 
  
 top 
 : 
  
 40 
 px 
 ; 
  
 right 
 : 
  
 40 
 px 
 ; 
  
 } 
  
 . 
 search-button 
  
 { 
  
 background-color 
 : 
  
 #4b4b4b 
 ; 
  
 color 
 : 
  
 #fff 
 ; 
  
 border 
 : 
  
 1 
 px 
  
 solid 
  
 #000 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 width 
 : 
  
 80 
 px 
 ; 
  
 height 
 : 
  
 40 
 px 
 ; 
  
 box-shadow 
 : 
  
 0 
  
 4 
 px 
  
 8 
 px 
  
 rgba 
 ( 
 0 
 , 
  
 0 
 , 
  
 0 
 , 
  
 0.35 
 ); 
  
 } 
  
 . 
 query-input 
  
 { 
  
 border 
 : 
  
 1 
 px 
  
 solid 
  
 #ccc 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 width 
 : 
  
 315 
 px 
 ; 
  
 height 
 : 
  
 40 
 px 
 ; 
  
 box-shadow 
 : 
  
 0 
  
 4 
 px 
  
 8 
 px 
  
 rgba 
 ( 
 0 
 , 
  
 0 
 , 
  
 0 
 , 
  
 0.35 
 ); 
  
 } 
  
 . 
 list-container 
  
 { 
  
 display 
 : 
  
 flex 
 ; 
  
 position 
 : 
  
 absolute 
 ; 
  
 max-height 
 : 
  
 500 
 px 
 ; 
  
 top 
 : 
  
 100 
 px 
 ; 
  
 right 
 : 
  
 40 
 px 
 ; 
  
 overflow-y 
 : 
  
 none 
 ; 
  
 } 
  
 gmp-place-search 
  
 { 
  
 width 
 : 
  
 400 
 px 
 ; 
  
 margin 
 : 
  
 0 
 ; 
  
 border-radius 
 : 
  
 10 
 px 
 ; 
  
 display 
 : 
  
 none 
 ; 
  
 border 
 : 
  
 none 
 ; 
  
 } 
  
 gmp-place-details-compact 
  
 { 
  
 width 
 : 
  
 350 
 px 
 ; 
  
 max-height 
 : 
  
 800 
 px 
 ; 
  
 display 
 : 
  
 none 
 ; 
  
 border 
 : 
  
 none 
 ; 
  
 transform 
 : 
  
 translateY 
 ( 
 calc 
 ( 
 -40 
 % 
 )); 
  
 } 
  
 gmp-place-details-compact 
 :: 
 after 
  
 { 
  
 content 
 : 
  
 '' 
 ; 
  
 position 
 : 
  
 absolute 
 ; 
  
 bottom 
 : 
  
 -18 
 px 
 ; 
  
 left 
 : 
  
 50 
 % 
 ; 
  
 transform 
 : 
  
 translateX 
 ( 
 -50 
 % 
 ); 
  
 width 
 : 
  
 20 
 px 
 ; 
  
 height 
 : 
  
 20 
 px 
 ; 
  
 background-color 
 : 
  
 white 
 ; 
  
 box-shadow 
 : 
  
 2 
 px 
  
 2 
 px 
  
 5 
 px 
  
 0 
  
 rgba 
 ( 
 0 
 , 
 0 
 , 
 0 
 , 
 0.2 
 ); 
  
 z-index 
 : 
  
 1 
 ; 
  
 clip-path 
 : 
  
 polygon 
 ( 
 0 
 % 
  
 0 
 % 
 , 
  
 100 
 % 
  
 0 
 % 
 , 
  
 50 
 % 
  
 100 
 % 
 ); 
  
 transform-origin 
 : 
  
 center 
  
 center 
 ; 
  
 } 
  
 @ 
 media 
  
 ( 
 prefers-color-scheme 
 : 
  
 dark 
 ) 
  
 { 
  
 /* Style for Dark mode */ 
  
 gmp-place-details-compact 
 :: 
 after 
  
 { 
  
 background-color 
 : 
  
 #131314 
 ; 
  
 } 
  
 } 

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Place Search with a Details Popup</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="style.css">
    <script type="module" src="./index.js"></script>
  </head>

  <body>
    <div id="map-container"></div>
    <div class="controls">
    <input type="text" class="query-input" />
    <button class="search-button">Search</button>
    </div>

    <div class="list-container">
      <gmp-place-search orientation="vertical" selectable>
          <gmp-place-all-content> </gmp-place-all-content>
          <gmp-place-text-search-request></gmp-place-text-search-request>
      </gmp-place-search>
    </div>

    <div id="details-container">
        <gmp-place-details-compact orientation="horizontal">
            <gmp-place-details-place-request></gmp-place-details-place-request>
            <gmp-place-all-content></gmp-place-all-content>
        </gmp-place-details-compact>
    </div>

    <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: "YOUR_API_KEY", v: "weekly"});
    </script>

  </body>
</html>
Create a Mobile Website
View Site in Mobile | Classic
Share by: