I've been researching an answer to this but have ultimately only found ways to create a searchable map by creating an entirely new map without my KML data. I have a map with markers and simply want to add an autocomplete search bar to the map that I have.
Everything I've tried breaks the map (removing the map completely) and leaving me with a search bar that is non functional. I have added Places to my billing, and as mentioned, I have the map with the markers in place via an external KML file. How can I add a search functionality to what I already have?
Here is my map code:
<!DOCTYPE html>
<html>
<head>
<title>HCV Providers</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script
src="https://maps.googleapis.com/maps/api/js?key=&callback=initMap&libraries=&v=weekly"
defer
></script>
<style type="text/css">
/* 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;
}
</style>
<script>
"use strict";
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 11,
center: {
lat: 30.9843,
lng: 91.9623
}
});
const ctaLayer = new google.maps.KmlLayer({
url: "https://louisianahealthhub.org/HCVProviders.kml",
map: map
});
}
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
full page with errors:
<!DOCTYPE html>
<html>
<head>
<title>HCV Providers</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=&v=weekly" defer></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initAutocomplete&libraries=places&v=weekly" defer></script>
<style type="text/css">
/* 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;
}
</style>
<script>
"use strict";
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 11,
center: {
lat: 30.9843,
lng: 91.9623
}
});
const ctaLayer = new google.maps.KmlLayer({
url: "https://louisianahealthhub.org/HCVProviders.kml",
map: map
});
}
</script>
<script>
"use strict";
// This example adds a search box to a map, using the Google Place Autocomplete
// feature. People can enter geographical searches. The search box will return a
// pick list containing a mix of places and predicted search terms.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
function initAutocomplete() {}); // Create the search box and link it to the UI element.
const input = document.getElementById("pac-input");
const searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input); // Bias the SearchBox results towards current map's viewport.
map.addListener("bounds_changed", () => {
searchBox.setBounds(map.getBounds());
});
let markers = []; // Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener("places_changed", () => {
const places = searchBox.getPlaces();
if (places.length == 0) {
return;
} // Clear out the old markers.
markers.forEach(marker => {
marker.setMap(null);
});
markers = []; // For each place, get the icon, name and location.
const bounds = new google.maps.LatLngBounds();
places.forEach(place => {
if (!place.geometry) {
console.log("Returned place contains no geometry");
return;
}
const icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
}; // Create a marker for each place.
markers.push(
new google.maps.Marker({
map,
icon,
title: place.name,
position: place.geometry.location
})
);
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
}
</script>
</head>
<body>
<input id="pac-input" class="controls" type="text" placeholder="Search Box" />
<div id="map"></div>
</body>
</html>
In the updated code you posted, you have two "init" functions.
I get 3 javascript errors with that code:
Uncaught SyntaxError: Unexpected token ')'
You have included the Google Maps JavaScript API multiple times on this page. This may cause unexpected errors.
Uncaught (in promise) re {message: "initAutocomplete is not a function",
It is also a duplicate of Using initMap and initAutocomplete on same html page google maps
The simplest fix is add the Autocomplete constructor to the initMap
function existing code.
Relevant lines (from Google's autocomplete example):
var input = document.getElementById('pac-input');
var autocomplete = new google.maps.places.Autocomplete(input);
// Bind the map's bounds (viewport) property to the autocomplete object,
// so that the autocomplete requests use the current map bounds for the
// bounds option in the request.
autocomplete.bindTo('bounds', map);
// Set the data fields to return when the user selects a place.
autocomplete.setFields(
['address_components', 'geometry', 'icon', 'name']);
var infowindow = new google.maps.InfoWindow();
var infowindowContent = document.getElementById('infowindow-content');
infowindow.setContent(infowindowContent);
var marker = new google.maps.Marker({
map: map,
anchorPoint: new google.maps.Point(0, -29)
});
autocomplete.addListener('place_changed', function() {
infowindow.close();
marker.setVisible(false);
var 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 details available for input: '" + place.name + "'");
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
infowindowContent.children['place-icon'].src = place.icon;
infowindowContent.children['place-name'].textContent = place.name;
infowindowContent.children['place-address'].textContent = address;
infowindow.open(map, marker);
});
"use strict";
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 11,
center: {
lat: 30.9843,
lng: 91.9623
}
});
const ctaLayer = new google.maps.KmlLayer({
url: "https://louisianahealthhub.org/HCVProviders.kml",
map: map
});
var input = document.getElementById('pac-input');
var autocomplete = new google.maps.places.Autocomplete(input);
// Bind the map's bounds (viewport) property to the autocomplete object,
// so that the autocomplete requests use the current map bounds for the
// bounds option in the request.
autocomplete.bindTo('bounds', map);
// Set the data fields to return when the user selects a place.
autocomplete.setFields(
['address_components', 'geometry', 'icon', 'name']);
var infowindow = new google.maps.InfoWindow();
var infowindowContent = document.getElementById('infowindow-content');
infowindow.setContent(infowindowContent);
var marker = new google.maps.Marker({
map: map,
anchorPoint: new google.maps.Point(0, -29)
});
autocomplete.addListener('place_changed', function() {
infowindow.close();
marker.setVisible(false);
var 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 details available for input: '" + place.name + "'");
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setPosition(place.geometry.location);
marker.setVisible(true);
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
infowindowContent.children['place-icon'].src = place.icon;
infowindowContent.children['place-name'].textContent = place.name;
infowindowContent.children['place-address'].textContent = address;
infowindow.open(map, marker);
});
}
/* 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;
}
#description {
font-family: Roboto;
font-size: 15px;
font-weight: 300;
}
#infowindow-content .title {
font-weight: bold;
}
#infowindow-content {
display: none;
}
#map #infowindow-content {
display: inline;
}
.pac-card {
margin: 10px 10px 0 0;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
background-color: #fff;
font-family: Roboto;
}
#pac-container {
padding-bottom: 12px;
margin-right: 12px;
}
.pac-controls {
display: inline-block;
padding: 5px 11px;
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 400px;
}
#pac-input:focus {
border-color: #4d90fe;
}
#title {
color: #fff;
background-color: #4d90fe;
font-size: 25px;
font-weight: 500;
padding: 6px 12px;
}
<title>HCV Providers</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places" defer></script>
<div class="pac-card" id="pac-card">
<div id="pac-container">
<input id="pac-input" type="text" placeholder="Enter a location">
</div>
</div>
<div id="map"></div>
<div id="infowindow-content">
<img src="" width="16" height="16" id="place-icon">
<span id="place-name" class="title"></span><br>
<span id="place-address"></span>
</div>