Skip to main content

Using Google Maps Places API and ColdFusion's CFMAP to render places of interests

Google announced the Places API recently at Google I/O (2011) and I was looking into this, to see how this API can be used in conjunction with ColdFusion maps created with CFMAP. The Places API can be used to retrieve place information which includes:
  • Places of interests such as parks, restaurants, hospitals which are nearby to the users location.
  • More detailed information on the place, such as the address, phone number etc,.
The API can also be used to perform check-in at a particular place and to add\delete a place. These check-ins can then be used to evaluate the popularity of the place. In this post I'll explain how to retrieve the places of interests and displaying the same on a ColdFusion map using CFMAP.


Place Search Requests - retrieving the places of interests near a user's location:
You can send a HTTP request to the URL of the form:

https://maps.googleapis.com/maps/api/place/search/output?parameters

Here the user has an option of specifying the output format as either json or xml and is required to pass a few parameters:
  • key (required): The application's API key. The Places API uses this information to identify your application.
  • location (required): This will be the latitude and longitude information of a particular place around which the places of interests are to be found.
  • radius (required): to specify the radius within which the places of interests are to be found. The value specified will be considered in meters.
  • sensor (required): to indicate whether the place request is from a device using the location sensor. It can be either true or false.
  • types (optional): the user might be interested in various types of businesses such as library, park, gym etc,. You can also specify multiple types which are separated by a '|' (type1|type2|type3).
  • name (optional): A term to be matched against the names of places. This will restrict the results to contain only those with the specified name.
  • language (optional): The language code to indicate the language in which the results are to be returned. 
With the above information, you can issue a HTTP request using ColdFusion's cfhttp tag:

 <cfhttp url="https://maps.googleapis.com/maps/api/place/search/json"  
         method="get"  
         result="gmapData">  

      <cfhttpparam type="url"  
                   name="location"  
                   value="-33.8670522,151.1957362">  
      <cfhttpparam type="url"  
                   name="types"  
                   value="doctor|book_store">  
      <cfhttpparam type="url"  
                   name="radius"  
                   value="2000">  
      <cfhttpparam type="url"  
                   name="sensor"  
                   value="false">  
      <cfhttpparam type="url"  
                   name="key"  
                   value="{API_Key}">  
 </cfhttp>  

For the purpose of this example, I have specified the latitude and longitude values for 'Sydney, Australia' (I've lived here!!) and have specified the type of business as doctor and book_store. The radius is specified as 2000 meters (2 Kms) and the sensor is set to false. The output format is specified as json.

The json response would contain three root elements: status, results and html_attributions. If there were no errors in performing the request operation and the response contained at least one result then the response status is set to "OK". The result element is an array of places sent in response to a request, this would include the place name, its geometry (latitude and longitude information), place id, reference, icon, types, vicinity.

The results array in the response can then be used to add places to the ColdFusion's map. However, on a Google Map when a user clicks on a location a popup is shown which includes the Address and the Phone number of the selected location. To get more details on a particular location, another request should be made to retrieve the place details such as address, phone number, rating.

Place Detail requests - retrieve place details:

Similar to the previous one, the HTTP request to retrieve the place details is:

https://maps.googleapis.com/maps/api/place/details/output?parameters

As mentioned earlier, output can be either json or xml. The reference value obtained from the previous HTTP call (Place Search request) is then passed as a parameter to retrieve the place details. Other required parameters include the sensor and the key. The cfhttp request to get the details is of the form:

 <cfloop array="#arrayResults#"  
         index="placesObject">  
      <cfhttp url="https://maps.googleapis.com/maps/api/place/details/json"  
              method="get"  
              result="placeDetails">  
           <cfhttpparam type="url"  
                        name="reference"  
                        value="#placesObject.reference#">  
           <cfhttpparam type="url"  
                        name="sensor"  
                        value="false">  
           <cfhttpparam type="url"  
                        name="key"  
                        value="{API_Key}">  
      </cfhttp>  
      <cfset placeDetails = #deserializeJSON(placeDetails.fileContent).result#>  
      <cfset arrayAppend(windowContent,   
                "<h3>" & placeDetails.name & "</h3><br><h5>" & placeDetails.formatted_address &   
 "<br>Phone: " & placeDetails.formatted_phone_number & "</h5>")/>  
 </cfloop>  

As seen in the above code, the arrayResults containing the results of the place search request is iterated in the cfloop tag. The reference value in the arrayResults is then used in each iteration to get the place details. The place details are then used populate the windowContent array, which contains the html markup to show when the user clicks on any of the map item.

The CFMAP and CFMAPITEM tag can then be used to render a Google map and add places of interests to the map:

 <cfmap name="myMap"  
        centerlatitude="-33.8670522"  
        centerlongitude="151.1957362"  
        tip="Sydney"  
        width="800"  
        height="700"  
        zoomlevel="16">  
      <cfloop array="#arrayResults#"  
             index="mapObject">  
           <cfmapitem name="#mapObject.name#"  
                      latitude="#mapObject.geometry.location.lat#"  
                      longitude="#mapObject.geometry.location.lng#"  
                      tip="#mapObject.name#"  
                      markerwindowcontent="#windowContent[count++]#"  
                      markericon="#mapObject.icon#">  
      </cfloop>  
 </cfmap>  

The CFMAPITEM tag is used to add places of interests on the map using the latitude and longitude information obtained from the place search request. The markerwindowcontent attribute would contain the address and the phone number information obtained from place detail request. The map rendered would look similar to the one shown below:



Comments

  1. I'm struggling with getting this to work.  I have tried to use the exact code above (except substituting API_Key for my Google Maps API key) and I get an error - "Variable ARRAYRESULTS is undefined."  Granted, I'm a novice at ColdFusion (and brand new to CFMAP), so I apologize in advance if this is a stupid rookie mistake...

    ReplyDelete
  2. John, the response that you receive from the HTTP request has to be de-serialized. Try putting  before the cfloop tag. I think that would fix it. Let me know if it doesn't I'll send you the cfm file.

    ReplyDelete
  3. Thanks so much, but now I get an error with this CFSET that says "Complex object types cannot be converted to simple values."

    ReplyDelete
  4. Let me know your email id, I'll send the cfm file to you. You can send me your email id through the 'Contact Me' page as well.

    ReplyDelete

Post a Comment

Popular posts from this blog

File upload and Progress events with HTML5 XmlHttpRequest Level 2

The XmlHttpRequest Level 2 specification adds several enhancements to the XmlHttpRequest object. Last week I had blogged about cross-origin-requests and how it is different from Flash\Silverlight's approach .  With Level 2 specification one can upload the file to the server by passing the file object to the send method. In this post I'll try to explore uploading file using XmlHttpRequest 2 in conjunction with the progress events. I'll also provide a description on the new HTML5 tag -  progress which can be updated while the file is being uploaded to the server. And of course, some ColdFusion code that will show how the file is accepted and stored on the server directory.

Server sent events with HTML5 and ColdFusion

There are several ways to interact with the server apart from the traditional request\response and refresh all protocol. They are polling, long polling, Ajax and Websockets ( pusherapp ). Of all these Ajax and Websockets have been very popular. There is another way to interact with the server such that the server can send notifications to the client using Server Sent Events (SSE) . SSE is a part of HTML5 spec:  http://dev.w3.org/html5/eventsource/

Adding beforeRender and afterRender functions to a Backbone View

I was working on a Backbone application that updated the DOM when a response was received from the server. In a Backbone View, the initialize method would perform some operations and then call the render method to update the view. This worked fine, however there was scenario where in I wanted to perform some tasks before and after rendering the view. This can be considered as firing an event before and after the function had completed its execution. I found a very simple way to do this with Underscore's wrap method.