The next hurdle I ran into while creating the GeoLinx
application was creating a pop up that would display the attributes for more
than one feature in the same spatial location.
Each job post is geocoded to a city because very rarely is a full
address included in the post. So each
post is typically located at the centroid of the city (or sometimes a specific
place like a military base). Because of
this, the points stack on top of each other.
The basic pop up implemented with the Google Maps API will only get the
information for the point on top. To
overcome this I had to create by own code to select all of the points within a
radius of the user’s click.
First I created a Fusion Tables layer to display the points
on the map. I did this simply by following
the documentation. I did suppress the
default Info Window, otherwise two pop ups would appear when the user clicks on
the point. I also included a SQL query
to not show posts older than a specified date or that have expired. You can find many good examples of JavaScript
functions that will get the current data or a past date. Finally, I created a new Info Window that
would display the attributes for the selected postings. An Info Window is simply the normal pop up
you see in most Google Maps applications.
var ftLayer = new
google.maps.FusionTablesLayer({
suppressInfoWindows: true,
query: {
select: 'GeoCode',
from: table,
where: "PostDate > '" +
currentDate +
"' AND (ExpireDate > '" + todaysDate +
"' OR ExpireDate = '')"
"' OR ExpireDate = '')"
}
});
ftLayer.setMap(map);
var infoWindow = new
google.maps.InfoWindow();
The next step was to create a listener for click event of
the Fusion Tables layer. This simply
tells the application to “listen” for the user to click on a point in the layer
and then do something. Once again I followed
the documentation for this. I then built
a query to select the attributes I wanted to display. I used a spatial query to select the features
within a certain distance of the users click.
Next it is essential convert the query to a URL format. Then I completed the query string by
including the rest of the URL path and my key. Finally, I created a Google Visualization
query using the Google Visualization API.
google.maps.event.addListener(ftLayer, 'click', function
(event) {
var query = "SELECT
Title, GeoCode, Organization, " +
"PostDate, URL FROM " +
table +
"PostDate, URL FROM " +
table +
" WHERE ST_INTERSECTS(GeoCode,
CIRCLE(LATLNG" +
event.latLng + ", 5000)) ORDER BY PostDate DESC";
event.latLng + ", 5000)) ORDER BY PostDate DESC";
query = encodeURIComponent(query);
query = 'http://www.google.com/fusiontables/gvizdata?tq='
+
query + '&key=’ + key;
query + '&key=’ + key;
var gvizQuery = new
google.visualization.Query(query);
Once the query was created, I sent the query to the server
to get back the result. I also had to
create some HTML formatting to display the results in a tabular format. The Info Window will take straight HTML. I cut back some of the HTML formatting below
to reduce the length of this post but you can research tables for HTML if you
need to. Using the Google Visualization
API, I looped through each row of the returned query and build each row in the
table. I also had to do some formatting
on the dates. The final steps were to
set the position of the pop up to the user’s click, feed the HTML code for the
table to it, and the open the info window.
gvizQuery.send(function
(response) {
var content = ...//HTML here
var numRows =
response.getDataTable().getNumberOfRows();
for (var
i = 0; i < numRows; i++) {
var title = response.getDataTable().getValue(i, 0);
var loc = response.getDataTable().getValue(i, 1);
var org = response.getDataTable().getValue(i, 2);
var pDate = response.getDataTable().getValue(i, 3);
var url = response.getDataTable().getValue(i, 4);
pDate = postDate.toString();
pDate =
postDate.replace(
'00:00:00 GMT-0500 (Eastern Standard Time)',
'');
'00:00:00 GMT-0500 (Eastern Standard Time)',
'');
pDate =
postDate.substr(3, postDate.length);
content = content +
+ title + ...//HTML here
+ loc + ...//HTML here
+ org + ...//HTML here
+ pDate + ...//HTML here
}
}
content = content + ...//HTML here
infoWindow.setPosition(event.latLng);
infoWindow.setContent(content);
infoWindow.open(map);
});
});
Overall, I had a difficult time putting this together because
it uses code from three Google APIs, and I couldn’t find examples doing exactly
this. But I did learn a lot that I would
use in other parts of the application.
Just a note: I’m sure there are other and better ways to do this. Feel free to comment if you have better solutions. The next part of the project was to add
search functionality that would center and zoom the map to the address or zip
code that the user specifies.
No comments:
Post a Comment