Each waypoint is an object that contains two properties:
location: The address of the place
stopover: This is a Boolean. If set to true, Google creates an intermediate point on the map. If set to false, Google plots a route that passes through this point.
The request we need to travel to the three places I mentioned is:
const request = {
origin: 'The Singapore Zoo',
destination: 'Sentosa',
waypoints: [{
location: 'Gardens by the bay',
stopover: true
}],
travelMode: 'DRIVING'
}
// Draw the directions
getDirections(request)
.then(/*...*/)
.catch(/*...*/)
Next, we want to add search boxes so users can search for directions with waypoints.
Adding search boxes
We want to let users decide whether they want to travel to more locations. To do this, we’ll add a <button> that says “Add new endpoint” in the search panel.
When a user clicks on “add new endpoint”, we want to add a search box to the search panel. To do this, we add an event listener to the “add new endpoint” button.
One way to add a search box is to write the HTML in JavaScript. You already know how to do this from the previous components, so we’re going to do something different.
We’re going to clone a search box since there are already two of them in the HTML.
To clone an element, we first need to find the element from the HTML. We can use any search box (but we’ll use the last one because it’s more convenient).
We want to limit the number of search boxes so we don’t hit the WAYPOINT LIMIT EXCEEDED error. Here, we’ll limit search boxes to 10.
To do this, we stop the user from creating extra search boxes once there are 10 search boxes in the DOM.
addSearchboxButton.addEventListener('click', event => {
let searchBoxes = [...searchPanel.querySelectorAll('.search-box')]
if (searchBoxes.length >= 10) return
// ...
})
Deleting search boxes
Users may want to reduce the number of waypoints, so we need to give them a way to delete search boxes. To let them delete search boxes, we need to add a delete button to each search box.
We have two search boxes when the page loads. One for the origin, one for the destination. These search boxes are compulsory.
We don’t want to let users delete any search boxes when there are only two search boxes left, so we’ll add a hidden attribute to the delete buttons.
There are more than 2 search boxes once we add a search box. When this happens, we want to let users delete search boxes.
We can do this by removing the hidden attribute of all delete buttons.
Note: After adding a search box into the DOM, we have to use querySelectorAll again to get the search boxes (because the DOM has changed). querySelectorAll doesn’t update automatically.
To delete a search box, we remove the search box from the DOM. Here, we can add an event listener to the search panel. (Using the event delegation pattern).
Each input element comes with their own Google Autocomplete predictions. As you can see in this GIF below, when you add a search box, the number of .pac-container increases by one.
The first .pac-container is for the first search box
The second .pac-container is for the second search box
And so on
We can remove the .pac-container if we know the index of the search box.
If you delete the first search box, you’ll end up with two endpoints. This isn’t ideal.
We always want the first search box to be “Starting Point”. And the last search box to be “Ending Point”. Here we have to use querySelectorAll to get the search boxes again since the DOM was changed.
If you want to, try making the middle search boxes say “Waypoints” as an exercise.
Ensuring there are two search boxes.
We need to have two search boxes for the Google Maps clone. We don’t want to let users delete search boxes if there are only two in the search panel.
We’ll hide the delete buttons if there are only two search boxes left.