Author: Sergey MatveyenkoOnce, an investor from a single project came to me and said: “Let's make a Google Travel Planner!” I agreed. Then the investor began to tell how the technical director imagined the architecture of this scheduler: he said something about communicating with the server, about the API key, about the requests to Google, about the money for the requests, which will be many, etc. Everything looked difficult and beautiful . But then we began to carefully read the Google API documentation and suddenly realized that in fact we did not need a server. At all! The entire scheduler can be done on the client. And the most interesting is that we can do without even an API key (provided that we use the JS API). In the end, in two days I was able to write such a scheduler, with client-side logic, based on the Google API, without using a server. Everything turned out to be very simple.
I'll tell you how you can make the simplest planner of this kind in just a couple of hours. Of course, during this time you can only assemble a prototype, but the main thing is that it will work! Its main function will be laying the optimal route between the sights in the city of interest to us; There may be a breakdown of the trip plan by day. Everything will be done on AngularJS using the Google Maps / Places API. I will talk about the features of working with this API and about some of its features that are not listed in the documentation. We will also talk about allocating logic to client applications.
So, how exactly will such a planner look like? It will be just a browser search string in which we will enter the name of the city or place of interest. In response to such a search request, we will be given this place on a Google map, a list of attractions in this place and the surrounding area with descriptions, photos and reviews. And, of course, between the sights will be laid the best route on Google maps with an indication of the approximate time to move between them. It will also be easy to add the ability to break the schedule of sightseeing by day.
')
What do we need?
First, we need the
Google Places library. This is the most important thing that will ensure the work of the scheduler:
<script src="https://maps.googleapis.com/maps/api/is?libraries=places&language=en"></script>
- This is
Autocomplete , a very useful project for AngularJS, which wraps the Google Places library and work with autocomplete. Rawgit is a binding around GitHub that also has a CDN.
<script src="https://rawgit.com/kuhnza/angular-google-places-autocomplete/0.2.7/src/autocomplete.js"></script>
- this is actually
AngularJS .
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
- this is
Bootstrap .
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
- this is
jQuery , which Bootstrap needs.
<link rel="stylesheet" href=https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href=https://rawgit.com/kuhnza/angular-google-places-autocomplete/master/dist/autocomplete.min.css">
- These are
style sheets from Autocomplete and Bootstrap.
That's all external that we have. All this is downloaded from the CDN - we don’t need a server at all!
We are looking for a place on the map
Now let's try to search for the city of interest on the map. Here is how we use Autocomplete:
<input type="text" class="form-control input-lg" g-places-autocomplete ng-model="destinationData" placeholder="Enter destination"> <button ng-click="showDestination = !showDestination" class="btn btn-block btn-default btn-xs">destinationData</button> <pre ng-show="showDestination">{{destination|json}}</pre> <div id="map" style="height: 200px;"></div>
As we can see, here we have one input:
<input type="text" class="form-control input-lg" g-places-autocomplete ng-model="destinationData" placeholder="Enter destination">
Thus, thanks to the Angular-project Google Places Autocomplete, we get a working autocomplete. This means that we can begin to enter the name of the place in the search form (even with errors), and we will be offered the appropriate options in the search:

As a result, we got a search for a place with its location on a Google map:

What's next?
Looking for nearest attractions
Previously (prior to version 3), Google API search for places was carried out by one method - there were a lot of parameters, and everything was very difficult. Now the search is divided into three methods. In particular, a dedicated radar search appeared - search for the nearest interesting places. Previously, such places had to be further filtered, because in the search results came across cities and countries. And now everything is simple.
How does he work?
Google usually offers to immediately show search results on a map. But, in fact, we do not need it now, because we just want to get a list of nearby places. Therefore, we use radar search (
service.radarSearch
) without a map within a radius of 50 km - this is the usual radius of the city and surrounding area. We are looking for regular tourist places like museums, churches, nightclubs, zoos, etc., which we list as Google
types
(
types
).
$scope.destinationOptions = { location : destination.geometry.location, radius : 50000 }; $scope.popularPoints = []; $scope.map = new google.maps.Map(document.getElementById('map'), { center : $scope.destinationOptions.location, zoom : 5 }); var service = new google.maps.places.PlacesService($scope.map); var radarOptions = { location : $scope.destinationOptions.location, radius : $scope.destinationOptions.radius, types : [ 'airport', 'amusement_park', 'aquarium', 'art_gallery', 'casino', 'church', 'city_hall', 'courthouse', 'hindu_temple', 'library', 'museum', 'night_club', 'park', 'stadium', 'synagogue', 'university', 'zoo' ] }; service.radarSearch(radarOptions, function(points) { points.slice(0, 8).forEach(function(point) { service.getDetails({ placeId : point.place_id }, function(details) { $scope.popularPoints.push(details); }); }); $scope.$digest(); });
So, we receive a request for a radar search, and instead of using the renderer and starting to work with the map, we take everything into Angular, and the search gives us eight first places (and it returns 200 results). Immediately, using the same service, we request details about the places and add to our scope in Angulyarovsky:
$scope.popularPoints.push(details)
.

So we did a search - when we find a place on the map, a list of all attractions within 50 km radius is immediately displayed. Also, if necessary, we will be able to open this list and see images of this place, as well as various details and comments of users with a rating.

Plot a route
But if I just showed the best sights in the search results, the investor would be unhappy, because I still want to plan the best route to these places. Therefore, under the search results we will have a button that can show us this route. How does she work?
It turns out that here, too, Google did everything for us - it provides a complete interface to the Google Maps mechanisms for planning and laying routes - down to intermediate points. But, as some of my friends like to say, the API here is made "alien to predators." Because if I have a list of points, I just want to pass them along and say that I am going to ride them. But it turns out that this does not happen, but it happens that we start only in one place and end in some other specific place, and inside we need to pull out intermediate points with a slice.
$scope.tripCalc = function() { var directionsService = new google.maps.DirectionsService(); directionsService.route({ origin : $scope.points[0].geometry.location, destination : $scope.points[$scope.points.length - 1].geometry.location, waypoints : $scope.points.slice(1, $scope.points.length - 1).map(function(point) { return { location : point.geometry.location }; }), travelMode: google.maps.TravelMode.DRIVING }, function(result) { $scope.route = result; $scope.$digest(); }); }
However, we found a way out - we closed the points of origin (
origin
) and end (
destination
) of the route to the hotel where the person rests. We also did a breakdown by day, taking into account that we can spend the night in different hotels. T. h. Can be done so, for example, that the starting point is the airport, the second is the point of renting cars, and the final point is the hotel of the first night. We can also make a route to look for restaurants in the middle of the day for lunch. All these points can be obtained by specifying the appropriate types in the request to the Google Maps API (
types
parameter). In fact, this is a simple programming task - to build an array of objects and reflect it in
waypoints
. So we get the finished route.
The most interesting and the most pleasant is the ability to show the distance and time that will be spent on moving between two points of the route. This means that if we, for example, drive between the points for six hours, this is a hint to find a restaurant along the way, and if we go through the night, it would be good to suggest a hotel. All this is done on the client.
Do I need a server?
And here we come to an interesting discussion that arose with us when we did this travel planner. Do we really want to keep it all on the server? Do we need to know what the user was looking for?
In fact, we are only interested in one thing: for the user to order from us what we want to sell. I will not say that we wanted to sell to the user, but, let's say, it could be rooms in hotels that he chose in this planner. By and large, this scheduler is just an added value, the added value is just a convenient service on the site that sells rooms in hotels. Because we do not need to save anything on the server - everything can be done on the client. Thus, we can simply fasten the buttons for booking hotel rooms where these hotels are displayed when planning a route.
Of course, we still need some kind of analytics, but even here we can do without a server if we use Google Analytics. So, for example, if we need to know which sites were most searched by users, the search text can easily jump through the HTML5 API in the URL, and Google Analytics will pick it up.
Everything else does not really bother us. We can now advertise the page, and let Google cope with the load - it will only be limited to the number of requests from a single IP, that is, from the user. We can lay out a page on Amazon S3 and then we can not even think about the load and the fact that our advertising campaign can put our servers. If we add more testimonials from users, the user will start being tied up on some kind of interactivity on the site, which, in fact, is completely loaded outside.
So we practically did the planner - a little more, and it can be sold.
In fact, these are the ways to organize the interface most effectively. Now the big suppliers really did everything so that we didn't have to worry about anything. For example, the last two years, when my friends asked me how to make a website for them, I could not answer them anything better than: “Go to blogspot”. After all, everything is there! So Google Maps provides everything you need. But under what conditions?
Terms of Use for GoogleMaps API
If you read the official instructions for the Google Maps API fluently, it may seem that everything must happen somewhere on Google maps - we have to draw something and not do anything about it. But, if you read carefully, it turns out that, under the terms of Google, all we have to do is, roughly speaking, draw the Google logo in the bottom corner and links to all sorts of terms of use. It turns out that Google has given us all the necessary data, and based on them we can even draw our own map and even stuff this data as we please, just to remember to write that the data was received from Google. Therefore, you can do anything on the site, anything in JavaScript, and without any server.
Project source
Gist