Search code examples
google-mapsgoogle-maps-api-3google-places-apigeojsoninfowindow

Google Places API Store Locator - Click Search Result Title to Show infoWindow


My map is functioning properly until I search for a nearest store location via zip code and try to click on a result's title in the generated panel to show the infoWindow of that corresponding title.

In other words, I want to be able to click the search result titles and when you do, it opens the infoWindow on the map marker associated with the title.

Click the map marker to show the infoWindow works fine. Click the search result in the list of results generated after searching, does not.

I'm using geoJSON to load the locations.

   function initMap() {
    // Create the map.
        const map = new google.maps.Map(document.getElementById('map'), {
            zoom: 7,
            center: { lat: 32.434521, lng: -86.333977 },
            styles: mapStyle,
        });

        // Load the stores GeoJSON onto the map.
        map.data.loadGeoJson('My geojson file', {idPropertyName: 'storeid'});

        // Define the custom marker icons, using the store's "category".
        map.data.setStyle((feature) => {
        return {
        icon: {
            url: 'my marker icon',
            scaledSize: new google.maps.Size(64, 64),
        },
        };
    });


        const apiKey = 'my key';
        const infoWindow = new google.maps.InfoWindow();

        // Show the information for a store when its marker is clicked.
        map.data.addListener('click', (event) => {
        const name = event.feature.getProperty('name');
        const address = event.feature.getProperty('address');
        const phone = event.feature.getProperty('phone');
        const position = event.feature.getGeometry().get(); 
        const content = `
            <h5>${name}</h5><p>${address}</p><p>${phone}</p>
        `;

        infoWindow.setContent(content);
        infoWindow.setPosition(position);
        infoWindow.setOptions({pixelOffset: new google.maps.Size(0, -30)});
        infoWindow.open(map);
        });

    // SEARCH BAR

    // Build and add the search bar
    const card = document.createElement('div');
    const titleBar = document.createElement('div');
    const title = document.createElement('div');
    const container = document.createElement('div');
    const magnify = document.createElement('div');
    const input = document.createElement('input');
    const options = {
        types: ['(regions)'],
        componentRestrictions: {country: 'us'},
    };

    card.setAttribute('id', 'pac-card');
    title.setAttribute('id', 'title');
    title.textContent = 'Find the nearest location';
    titleBar.appendChild(title);
    container.setAttribute('id', 'pac-container');
    magnify.setAttribute('id', 'magnify');
    input.setAttribute('id', 'pac-input');
    input.setAttribute('type', 'text');
    input.setAttribute('placeholder', 'ZIP CODE');
    container.appendChild(input);
    let parent = document.getElementById('map-hero');
    parent.appendChild(card);
    card.appendChild(titleBar);
    card.appendChild(container);
    let magnifyParent = document.getElementById('pac-container');
    magnifyParent.appendChild(magnify);
    // map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);


    // Make the search bar into a Places Autocomplete search bar and select
    // which detail fields should be returned about the place that
    // the user selects from the suggestions.
    const autocomplete = new google.maps.places.Autocomplete(input, options);

    autocomplete.setFields(
        ['address_components', 'geometry', 'name']);

    // END SEARCH BAR

    // Press Enter to Search Zip Code

    var pac_input = document.getElementById('pac-input');

    (function pacSelectFirst(input) {
        // store the original event binding function
        var _addEventListener = (input.addEventListener) ? input.addEventListener : input.attachEvent;

        function addEventListenerWrapper(type, listener) {
            // Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
            // and then trigger the original listener.
            if (type == "keydown") {
            var orig_listener = listener;
            listener = function(event) {
            var suggestion_selected = $(".pac-item-selected").length > 0;
            if (event.which == 13 && !suggestion_selected) {
            var simulated_downarrow = $.Event("keydown", {
                keyCode: 40,
                which: 40
            });
                orig_listener.apply(input, [simulated_downarrow]);
                }
                orig_listener.apply(input, [event]);
                };
            }
            _addEventListener.apply(input, [type, listener]);
        }
        input.addEventListener = addEventListenerWrapper;
        input.attachEvent = addEventListenerWrapper;

        var autoComplete = new google.maps.places.Autocomplete(input);
        autoComplete.setTypes(['regions'])
        // autoComplete.unbindAll();

    })(pac_input);
    //End Press Enter to Search Zip Code

    //Click magnifying glass to search

    document.getElementById('magnify').onclick = function () {
        var input = document.getElementById('pac-input');

        function no_op() {}

        google.maps.event.trigger(input, 'focus', {});
        google.maps.event.trigger(input, 'keydown', {
          keyCode: 40, // arrow down
          stopPropagation: no_op, // No-op function in order to prevent error
          preventDefault: no_op,
        });  
        google.maps.event.trigger(input, 'keydown', { keyCode: 13 });  // enter
        google.maps.event.trigger(this, 'focus', {});
      };
    //End Click magnifying glass to search

    // Set the origin point when the user selects an address
    const originMarker = new google.maps.Marker({map: map});
    originMarker.setVisible(false);
    let originLocation = map.getCenter();

    autocomplete.addListener('place_changed', async () => {
        originMarker.setVisible(false);
        originLocation = map.getCenter();
        const place = autocomplete.getPlace();

        if (!place.geometry) {
        // User entered the name of a Place that was not suggested and
        // pressed the Enter key, or the Place Details request failed.
        window.alert('No address available for input: \'' + place.name + '\'');
        return;
        }

        // Recenter the map to the selected address
        originLocation = place.geometry.location;
        map.setCenter(originLocation);
        map.setZoom(9);
        console.log(place);

        originMarker.setPosition(originLocation);
        originMarker.setVisible(true);

        // Use the selected address as the origin to calculate distances
        // to each of the store locations
        const rankedStores = await calculateDistances(map.data, originLocation);
        showStoresList(map.data, rankedStores);

        return;
    });

    }


    // Calculate Distance

    async function calculateDistances(data, origin) {
    const stores = [];
    const destinations = [];

    // Build parallel arrays for the store IDs and destinations
    data.forEach((store) => {
        const storeNum = store.getProperty('storeid');
        const storeLoc = store.getGeometry().get();

        stores.push(storeNum);
        destinations.push(storeLoc);
    });

    // Retrieve the distances of each store from the origin
    // The returned list will be in the same order as the destinations list
    const service = new google.maps.DistanceMatrixService();
    const getDistanceMatrix =
        (service, parameters) => new Promise((resolve, reject) => {
        service.getDistanceMatrix(parameters, (response, status) => {
            if (status != google.maps.DistanceMatrixStatus.OK) {
            reject(response);
            } else {
            const distances = [];
            const results = response.rows[0].elements;
            for (let j = 0; j < results.length; j++) {
                const element = results[j];
                const distanceText = element.distance.text;
                const distanceVal = element.distance.value;
                const distanceObject = {
                storeid: stores[j],
                distanceText: distanceText,
                distanceVal: distanceVal,
                };
                distances.push(distanceObject);
            }

            resolve(distances);
            }
        });
        });

    const distancesList = await getDistanceMatrix(service, {
        origins: [origin],
        destinations: destinations,
        travelMode: 'DRIVING',
        unitSystem: google.maps.UnitSystem.IMPERIAL,
    });

    distancesList.sort((first, second) => {
        return first.distanceVal - second.distanceVal;
    });

    return distancesList;
    }

    // End Calculate Distance

    //Show Closest Location List
    function showStoresList(data, stores) {
    if (stores.length == 0) {
        console.log('empty stores');
        return;
    }

    let panel = document.createElement('div');
    // If the panel already exists, use it. Else, create it and add to the page.
    if (document.getElementById('panel')) {
        panel = document.getElementById('panel');
        // If panel is already open, close it
        if (panel.classList.contains('open')) {
        panel.classList.remove('open');
        }
    } else {
        panel.setAttribute('id', 'panel');
        let parent = document.getElementById('map');
        parent.appendChild(panel);
    //  const body = document.body;
    //  body.insertBefore(panel, body.childNodes[0]);
    }


    // Clear the previous details
    while (panel.lastChild) {
        panel.removeChild(panel.lastChild);
    }

    stores.forEach((store) => {
        // Add store details with text formatting
        const name = document.createElement('p');
        name.setAttribute('id', 'locationName');
        name.classList.add('place');
        const currentStore = data.getFeatureById(store.storeid);
        name.textContent = currentStore.getProperty('name');
        panel.appendChild(name);
        const distanceText = document.createElement('p');
        distanceText.classList.add('distanceText');
        distanceText.textContent = store.distanceText;
        panel.appendChild(distanceText);

    });

    // Open the panel
    panel.classList.add('open');

    return;
    }

    //End Show Closest Location List

geoJSON layout

{
    "type": "FeatureCollection",
    "features": [{
            "geometry": {
                "type": "Point",
                "coordinates": [-86.192867, 
                    32.346155
                ]
            },
            "type": "Feature",
            "properties": {
                "name": "Place 1",
                "address": "The Address",
                "phone": "The Number",
                "storeid": "01"
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [-86.305915,
                    32.366245 
                ]
            },
            "type": "Feature",
            "properties": {
                "name": "Place 2",
                "address": "The Address",
                "phone": "The Number",
                "storeid": "02"
            }
        },

HTML

<div id="map-hero" class="map-hero">
        <h1 class="white center">GET STARTED BY ENTERING YOUR ZIP CODE</h1>
        <h4 class="white center">You can also zoom and drag to find a location nearest you</h4>
    </div>
    <div class="center-info-bar">
        <div id="map"></div>
        <script src="my script source"></script>
        <script async defer src="https://maps.googleapis.com/maps/api/js?key=MY API KEY &libraries=places&callback=initMap"></script>
    </div>

CSS

  #map {
            height: 400px;
            width: 100%; 
        }
        .map-hero{
            background-image: url('my url');
            background-size: cover;
            background-position: center;
            min-height: 355px;
            display: flex;
            flex-direction: column;
            justify-content: center;
        }
        .center-info-bar{
            margin-bottom: 0;
        }
        .sidebar{
            display: none;
        }
        .content{
            width: 100%;
        }
        .gm-style-iw-c{
            padding: 25px;
            width: 300px;
        }
        .gm-style-iw-d{
            height: auto;
        }
        .map-loc-name{
            font-size: 15px;
            font-weight: bold;
            width: 100%;
            margin-bottom: 15px;
        } 
        #pac-card {
            background-color: #fff;
            border-radius: 2px 0 0 2px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
            box-sizing: border-box;
            font-family: Roboto;
            margin: 10px 10px 0 0;
            -moz-box-sizing: border-box;
            outline: none;
            // custom
            max-width: 300px;
            background: transparent;
            box-shadow: none;
            margin: 0 auto;
          }

          #pac-container {
            padding-top: 12px;
            padding-bottom: 12px;
            margin-right: 12px;
            display: flex;
            align-items: center;
          }

          #pac-input {
            text-overflow: ellipsis;
            // custom
            width: 100%;
            padding: 15px;
            border: 3px solid #C11589;
            border-radius: 10px 0 0 10px;
            background: transparent;
            color: #fff; 
            font-size: 18px;
            font-weight: bold;
            font-family: 'Cachet-Bold', Verdana, sans-serif;
          }

          #pac-input::placeholder{
              color: #fff;
              font-family: 'Cachet-Bold', Verdana, sans-serif;
              font-weight: bold;
              font-size: 18px;
          }

          input:focus{
            box-shadow: none;
        }
          #magnify{
              width: 50px;
              height: 58px;
              border-radius: 0 10px 10px 0;
              background-color: #C11589;
              background-image: url('my url');
              background-size: 80%;
              background-position: center;
              background-repeat: no-repeat;
          }

          #magnify:hover{
              cursor: pointer;
          }

          #title {
            color: #fff;
            background-color: #acbcc9;
            font-size: 18px;
            font-weight: 400;
            padding: 6px 12px;
            // custom
            display: none;
          }

          .hidden {
            display: none;
          }

          /* Styling for an info pane that slides out from the left. 
           * Hidden by default. */
          #panel {
            height: 100%;
            width: null;
            background-color: white;
            position: absolute;
            z-index: 1;
            overflow-x: hidden;
            transition: all .2s ease-out;
          }

          .open {
            width: 250px;
          }

          .place {
            font-family: 'open sans', arial, sans-serif;
            font-size: 1.2em;
            font-weight: 500;
            margin-block-end: 0px;
            padding-left: 18px;
            padding-right: 18px;
          }

          .distanceText {
            color: silver;
            font-family: 'open sans', arial, sans-serif;
            font-size: 1em;
            font-weight: 400;
            margin-block-start: 0.25em;
            padding-left: 18px;
            padding-right: 18px;
          }

Generated panel with titles and distance that's created via JS after search. These are the titles I want to be able to click to show the info window (while still being able to click the marker to show the info window) enter image description here


Solution

  • You have all the data needed to open the InfoWindow on click of the sidebar.

    Do the same thing done when the marker is clicked:

    function openInfoWindowOnMarker(feature) {
       console.log(feature);
       const name = feature.getProperty('name');
       const address = feature.getProperty('address');
       const phone = feature.getProperty('phone');
       const position = feature.getGeometry().get();
       const content = `<h5>${name}</h5><p>${address}</p><p>${phone}</p>`;
    
       infoWindow.setContent(content);
       infoWindow.setPosition(position);
       infoWindow.setOptions({
         pixelOffset: new google.maps.Size(0, -30)
       });
       infoWindow.open(map);
     }
    
     infoWindow = new google.maps.InfoWindow();
     // Show the information for a store when its marker is clicked.
     map.data.addListener('click', (event) => {
       openInfoWindowOnMarker(event.feature)
     });
    

    Then where the sidebar is created, call the same function when the sidebar entry is clicked.

     stores.forEach((store) => {
       console.log(store);
       // Add store details with text formatting
       const name = document.createElement('p');
       name.setAttribute('id', 'locationName');
       name.classList.add('place');
       const currentStore = data.getFeatureById(store.storeid);
       name.addEventListener('click', (function(currentStore) {
         return function() {
         openInfoWindowOnMarker(currentStore);
       }})(currentStore));
       name.textContent = currentStore.getProperty('name');
       panel.appendChild(name);
       const distanceText = document.createElement('p');
       distanceText.classList.add('distanceText');
       distanceText.textContent = store.distanceText;
       panel.appendChild(distanceText);
     });
    

    A few other changes were needed to make the map and the infoWindow available to the code.

    proof of concept fiddle

    code snippet:

    var infoWindow;
    var map;
    function initMap() {
       // Create the map.
       map = new google.maps.Map(document.getElementById('map'), {
         zoom: 7,
         center: {
           lat: 32.434521,
           lng: -86.333977
         },
         // styles: mapStyle,
       });
    
       // Load the stores GeoJSON onto the map.
       map.data.addGeoJson(geoJsonData, {
         idPropertyName: 'storeid'
       });
    
       // Define the custom marker icons, using the store's "category".
       map.data.setStyle((feature) => {
         return {
           icon: {
             url: 'https://staging.ymcamontgomery.org/wp-content/uploads/2020/02/map-marker-1.svg',
             scaledSize: new google.maps.Size(64, 64),
           },
         };
       });
    
    
       const apiKey = 'AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk';
       infoWindow = new google.maps.InfoWindow();
       // Show the information for a store when its marker is clicked.
       map.data.addListener('click', (event) => {
         openInfoWindowOnMarker(event.feature)
       });
    
       // SEARCH BAR
    
       // Build and add the search bar
       const card = document.createElement('div');
       const titleBar = document.createElement('div');
       const title = document.createElement('div');
       const container = document.createElement('div');
       const magnify = document.createElement('div');
       const input = document.createElement('input');
       const options = {
         types: ['(regions)'],
         componentRestrictions: {
           country: 'us'
         },
       };
    
       card.setAttribute('id', 'pac-card');
       title.setAttribute('id', 'title');
       title.textContent = 'Find the nearest location';
       titleBar.appendChild(title);
       container.setAttribute('id', 'pac-container');
       magnify.setAttribute('id', 'magnify');
       input.setAttribute('id', 'pac-input');
       input.setAttribute('type', 'text');
       input.setAttribute('placeholder', 'ZIP CODE');
       input.setAttribute('value', 'Montgomery');
       container.appendChild(input);
       let parent = document.getElementById('map-hero');
       parent.appendChild(card);
       card.appendChild(titleBar);
       card.appendChild(container);
       let magnifyParent = document.getElementById('pac-container');
       magnifyParent.appendChild(magnify);
       // map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);
    
    
       // Make the search bar into a Places Autocomplete search bar and select
       // which detail fields should be returned about the place that
       // the user selects from the suggestions.
       const autocomplete = new google.maps.places.Autocomplete(input, options);
    
       autocomplete.setFields(
         ['address_components', 'geometry', 'name']);
    
       // END SEARCH BAR
    
       // Press Enter to Search Zip Code
    
       var pac_input = document.getElementById('pac-input');
    
       (function pacSelectFirst(input) {
         // store the original event binding function
         var _addEventListener = (input.addEventListener) ? input.addEventListener : input.attachEvent;
    
         function addEventListenerWrapper(type, listener) {
           // Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
           // and then trigger the original listener.
           if (type == "keydown") {
             var orig_listener = listener;
             listener = function(event) {
               var suggestion_selected = $(".pac-item-selected").length > 0;
               if (event.which == 13 && !suggestion_selected) {
                 var simulated_downarrow = $.Event("keydown", {
                   keyCode: 40,
                   which: 40
                 });
                 orig_listener.apply(input, [simulated_downarrow]);
               }
               orig_listener.apply(input, [event]);
             };
           }
           _addEventListener.apply(input, [type, listener]);
         }
         input.addEventListener = addEventListenerWrapper;
         input.attachEvent = addEventListenerWrapper;
    
         var autoComplete = new google.maps.places.Autocomplete(input);
         autoComplete.setTypes(['regions'])
         // autoComplete.unbindAll();
    
       })(pac_input);
       //End Press Enter to Search Zip Code
    
       //Click magnifying glass to search
    
       document.getElementById('magnify').onclick = function() {
         var input = document.getElementById('pac-input');
    
         function no_op() {}
    
         google.maps.event.trigger(input, 'focus', {});
         google.maps.event.trigger(input, 'keydown', {
           keyCode: 40, // arrow down
           stopPropagation: no_op, // No-op function in order to prevent error
           preventDefault: no_op,
         });
         google.maps.event.trigger(input, 'keydown', {
           keyCode: 13
         }); // enter
         google.maps.event.trigger(this, 'focus', {});
       };
       //End Click magnifying glass to search
    
       // Set the origin point when the user selects an address
       const originMarker = new google.maps.Marker({
         map: map
       });
       originMarker.setVisible(false);
       let originLocation = map.getCenter();
    
       autocomplete.addListener('place_changed', async () => {
         originMarker.setVisible(false);
         originLocation = map.getCenter();
         const place = autocomplete.getPlace();
    
         if (!place.geometry) {
           // User entered the name of a Place that was not suggested and
           // pressed the Enter key, or the Place Details request failed.
           window.alert('No address available for input: \'' + place.name + '\'');
           return;
         }
    
         // Recenter the map to the selected address
         originLocation = place.geometry.location;
         map.setCenter(originLocation);
         map.setZoom(9);
         console.log(place);
    
         originMarker.setPosition(originLocation);
         originMarker.setVisible(true);
    
         // Use the selected address as the origin to calculate distances
         // to each of the store locations
         const rankedStores = await calculateDistances(map.data, originLocation);
         showStoresList(map.data, rankedStores);
    
         return;
       });
    
     }
    
     function openInfoWindowOnMarker(feature) {
       console.log(feature);
       const name = feature.getProperty('name');
       const address = feature.getProperty('address');
       const phone = feature.getProperty('phone');
       const position = feature.getGeometry().get();
       const content = `<h5>${name}</h5><p>${address}</p><p>${phone}</p>`;
    
       infoWindow.setContent(content);
       infoWindow.setPosition(position);
       infoWindow.setOptions({
         pixelOffset: new google.maps.Size(0, -30)
       });
       infoWindow.open(map);
     }
     // Calculate Distance
    
     async function calculateDistances(data, origin) {
       const stores = [];
       const destinations = [];
    
       // Build parallel arrays for the store IDs and destinations
       data.forEach((store) => {
         const storeNum = store.getProperty('storeid');
         const storeLoc = store.getGeometry().get();
    
         stores.push(storeNum);
         destinations.push(storeLoc);
       });
    
       // Retrieve the distances of each store from the origin
       // The returned list will be in the same order as the destinations list
       const service = new google.maps.DistanceMatrixService();
       const getDistanceMatrix =
         (service, parameters) => new Promise((resolve, reject) => {
           service.getDistanceMatrix(parameters, (response, status) => {
             if (status != google.maps.DistanceMatrixStatus.OK) {
               reject(response);
             } else {
               const distances = [];
               const results = response.rows[0].elements;
               for (let j = 0; j < results.length; j++) {
                 const element = results[j];
                 if (element.status == "OK") {
                   const distanceText = element.distance.text;
                   const distanceVal = element.distance.value;
                   const distanceObject = {
                     storeid: stores[j],
                     storeLoc: destinations[j],
                     distanceText: distanceText,
                     distanceVal: distanceVal,
                   };
                   distances.push(distanceObject);
                 }
               }
    
               resolve(distances);
             }
           });
         });
    
       const distancesList = await getDistanceMatrix(service, {
         origins: [origin],
         destinations: destinations,
         travelMode: 'DRIVING',
         unitSystem: google.maps.UnitSystem.IMPERIAL,
       });
    
       distancesList.sort((first, second) => {
         return first.distanceVal - second.distanceVal;
       });
    
       return distancesList;
     }
    
     // End Calculate Distance
    
     //Show Closest Location List
     function showStoresList(data, stores) {
       if (stores.length == 0) {
         console.log('empty stores');
         return;
       }
    
       let panel = document.createElement('div');
       // If the panel already exists, use it. Else, create it and add to the page.
       if (document.getElementById('panel')) {
         panel = document.getElementById('panel');
         // If panel is already open, close it
         if (panel.classList.contains('open')) {
           panel.classList.remove('open');
         }
       } else {
         panel.setAttribute('id', 'panel');
         let parent = document.getElementById('map');
         parent.appendChild(panel);
         //  const body = document.body;
         //  body.insertBefore(panel, body.childNodes[0]);
       }
    
    
       // Clear the previous details
       while (panel.lastChild) {
         panel.removeChild(panel.lastChild);
       }
    
       stores.forEach((store) => {
         console.log(store);
         // Add store details with text formatting
         const name = document.createElement('p');
         name.setAttribute('id', 'locationName');
         name.classList.add('place');
         const currentStore = data.getFeatureById(store.storeid);
         name.addEventListener('click', (function(currentStore) {
           return function() {
           openInfoWindowOnMarker(currentStore);
         }})(currentStore));
         name.textContent = currentStore.getProperty('name');
         panel.appendChild(name);
         const distanceText = document.createElement('p');
         distanceText.classList.add('distanceText');
         distanceText.textContent = store.distanceText;
         panel.appendChild(distanceText);
    
       });
    
       // Open the panel
       panel.classList.add('open');
    
       return;
     }
    
     //End Show Closest Location List
    
     var geoJsonData = {
       "type": "FeatureCollection",
       "features": [{
           "geometry": {
             "type": "Point",
             "coordinates": [-86.192867,
               32.346155
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "Place 1",
             "address": "The Address",
             "phone": "The Number",
             "storeid": "01"
           }
         },
         {
           "geometry": {
             "type": "Point",
             "coordinates": [-86.305915,
               32.366245
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "Place 2",
             "address": "The Address",
             "phone": "The Number",
             "storeid": "02"
           }
         },
         {
           "geometry": {
             "type": "Point",
             "coordinates": [-85.7077266,
               32.430237
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "Tuskegee",
             "address": "Tuskegee",
             "phone": "The Number",
             "storeid": "03"
           }
         },
         {
           "geometry": {
             "type": "Point",
             "coordinates": [151.2092955,
               -33.8688197 
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "Sydney",
             "address": "Sydney NSW",
             "phone": "The Number",
             "storeid": "04"
           }
         },
         {
           "geometry": {
             "type": "Point",
             "coordinates": [-74.0059728 ,
               40.7127753
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "New York",
             "address": "New York, NY",
             "phone": "The Number",
             "storeid": "05"
           }
         },
         {
           "geometry": {
             "type": "Point",
             "coordinates": [-71.05888 ,
               42.3600825
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "Boston",
             "address": "Boston, MA",
             "phone": "The Number",
             "storeid": "06"
           }
         },
         {
           "geometry": {
             "type": "Point",
             "coordinates": [-80.1917902,
               25.7616798
             ]
           },
           "type": "Feature",
           "properties": {
             "name": "Miami",
             "address": "Miami, FL",
             "phone": "The Number",
             "storeid": "07"
           }
         },
       ]
     }
    /* Always set the map height explicitly to define the size of the div
     * element that contains the map. */
    /* #map {
      height: 100%;
    } */
    /* Optional: Makes the sample page fill the window. */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    #map {
      height: 400px;
      width: 100%;
    }
    
    .map-hero {
      /* background-image: url('my url'); */
      background-size: cover;
      background-position: center;
      min-height: 355px;
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    
    .center-info-bar {
      margin-bottom: 0;
    }
    
    .sidebar {
      display: none;
    }
    
    .content {
      width: 100%;
    }
    
    .gm-style-iw-c {
      padding: 25px;
      width: 300px;
    }
    
    .gm-style-iw-d {
      height: auto;
    }
    
    .map-loc-name {
      font-size: 15px;
      font-weight: bold;
      width: 100%;
      margin-bottom: 15px;
    }
    
    #pac-card {
      background-color: #fff;
      border-radius: 2px 0 0 2px;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
      box-sizing: border-box;
      font-family: Roboto;
      margin: 10px 10px 0 0;
      -moz-box-sizing: border-box;
      outline: none;
      // custom
      max-width: 300px;
      background: transparent;
      box-shadow: none;
      margin: 0 auto;
    }
    
    #pac-container {
      padding-top: 12px;
      padding-bottom: 12px;
      margin-right: 12px;
      display: flex;
      align-items: center;
    }
    
    #pac-input {
      text-overflow: ellipsis;
      // custom
      width: 100%;
      padding: 15px;
      border: 3px solid #C11589;
      border-radius: 10px 0 0 10px;
      background: transparent;
      color: #000;
      font-size: 18px;
      font-weight: bold;
      font-family: 'Cachet-Bold', Verdana, sans-serif;
    }
    
    #pac-input::placeholder {
      color: #fff;
      font-family: 'Cachet-Bold', Verdana, sans-serif;
      font-weight: bold;
      font-size: 18px;
    }
    
    input:focus {
      box-shadow: none;
    }
    
    #magnify {
      width: 50px;
      height: 58px;
      border-radius: 0 10px 10px 0;
      background-color: #C11589;
      /*  background-image: url('my url'); */
      background-size: 80%;
      background-position: center;
      background-repeat: no-repeat;
    }
    
    #magnify:hover {
      cursor: pointer;
    }
    
    #title {
      color: #fff;
      background-color: #acbcc9;
      font-size: 18px;
      font-weight: 400;
      padding: 6px 12px;
      // custom
      display: none;
    }
    
    .hidden {
      display: none;
    }
    
    /* Styling for an info pane that slides out from the left. 
               * Hidden by default. */
    #panel {
      height: 100%;
      width: null;
      background-color: white;
      position: absolute;
      z-index: 1;
      overflow-x: hidden;
      transition: all .2s ease-out;
    }
    
    .open {
      width: 250px;
    }
    
    .place {
      font-family: 'open sans', arial, sans-serif;
      font-size: 1.2em;
      font-weight: 500;
      margin-block-end: 0px;
      padding-left: 18px;
      padding-right: 18px;
    }
    
    .distanceText {
      color: silver;
      font-family: 'open sans', arial, sans-serif;
      font-size: 1em;
      font-weight: 400;
      margin-block-start: 0.25em;
      padding-left: 18px;
      padding-right: 18px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="map-hero" class="map-hero">
            <h1 class="white center">GET STARTED BY ENTERING YOUR ZIP CODE</h1>
            <h4 class="white center">You can also zoom and drag to find a location nearest you</h4>
        </div>
        <div class="center-info-bar">
            <div id="map"></div>
        </div>
    <!-- Replace the value of the key parameter with your own API key. -->
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places" async defer></script>