

Today we are going to load JSON data thats being served from our Ruby on Rails scaffold. For this lesson I'll just concentrate on reading from JSON and display it on the map. In another lesson we'll show how to setup the scaffold. Then we'll go over how to make the markers and client list clickable. For an example on what this will look like, visit http://www.ccexperts.com/dev/json-map.html or view the image below.

Every web designer has at one point or another been asked, "How can I get weather on my site?" The old answer was to have a giant ugly weather channel gadget. Something that looked very nasty and you couldn't un-brand it no matter what. Some used an iframe to display external data and have it appear to be on their site. Lastly you could always just have a link that says 'click here for weather'. My goal was to get weather data from an external source and be able to customize how it looks. Fortunately now there are some great resources out there. I'm going with one that is my favorite, something extremely easy to use and customize - Google's Weather API.
I wanted to talk about some new trends that have been rising in popularity now. Then we'll go over how to use each of these resources to help your web site. Using these new techologies you can really add some amazing things to your sites. Its not always easy to see how these techologies can be used to increase visits - that's what we'll be going over. So lets get started.
Hey everyone! Sorry for the delay in posting this. It’s been a busy time lately. I’m spending half my time in
In this tutorial I wanted to go over how to take raw data from just about any source and then plot the points on a Google map. This process can be done in any number of ways, I know myself I have done a little differently each time - mainly due to constraints or a customers request. In this particular request I had very limited time. I was asked to take data from their client management system and then place it on a Google map. Let's see how we should start such a process.
Planning (Feel free to skip this part)
Yes that's right, even if you don't do much of it you have to start with some sort of planning. Lack of doing so will no doubt cause you trouble down the road. In this case I already had the data exported into CSV format. I know from there somehow we must geocode (convert the addresses into mapable latitude / longitude coordinates). First things first, I put my CSV into Excel then into an Access (Yea I know) database. So now what? Well once we have our data we must then geocode the addresses then plot them on a map. In this case I used a PHP file to output all my addresses in XML. The JavaScript calls that using GDownloadURL then geocodes each address and outputs it to the browser. Then you just have to save that in a file for your map program to plot it. In my particular case I already had another JavaScript page already written that could accept an XML file and plot the points so I used that. I really should have just one JavaScript app to both request the data, geocode then display the points on the map. I just didn't have the time to do all that. I suppose the right way would have PHP comunicate with JavaScript by having JavaScript query PHP for all addresses. Once each one is geocoded send it back to PHP using XML or JSON. PHP would then write the latitude longitude to the database. Next time the script is ran JavaScript would query PHP and this time find all the addresses geocoded and just skip that step and plot them. Anyway in my example we are just mass geocoding.
What is the best way to geocode a bunch of addresses?
Short answer: I put all the address in a XML file then loop over using JavaScript
Long answer:
You'll note that I decided to loop over using the GClientGeocoder class. However lets take a note from Google's reference page about that class.
This class is used to communicate directly with Google servers to obtain geocodes for user specified addresses. In addition, a geocoder maintains its own cache of addresses, which allows repeated queries to be answered without a round trip to the server. As a general best practice, it is not recommended to use GClientGeocoder functions in a loop. Developers that have multiple addresses to geocode should probably use our HTTP Geocoder instead.
Google says in not recommended to use this class to loop over? There are limits on both the JavaScript class and the HTTP geocoder. Its true that the HTTP geocoder has less strict limits. In my particular case I needed 2000 addresses geocoded. Simply put using HTTP just wasn't an option because PHP and my web server would both time out. Yes, I increased the timeout on both however I still get the error because I use a custom http wrapper. So in my experience the JavaScript class is faster so that's what we'll use in this tutorial.
So we are using XML data to feed into the following JavaScript file. If your source is CSV you would simply change into XML format. Here is what my XML looks like
My source XML file:
<choices xml:lang="EN">
<client address="4 kent town market,chester,md,21619"/>
</choices>
In my case my XML file is actually generated dynamically by http://www.ccexperts.com/dev/listClientsXML.php
View it live
Stepping through the source line by lineHere is our source. I'll heavily comment it so you can get a good understand on what everything does.
// nextAddress function is called once Google is loaded and ready to go
// that'll get everything started
<body onunload="GUnload()" onload="nextAddress()">
// Outputs basic XML header
<div id="message"><?xml version="1.0" encoding="UTF-8"?><br /><markers><br /></div>
<script type="text/javascript">
// delay between geocode requests 100 miliseconds seems to work well
// this is used because if you make too many geocodes too often Google
// will throw an error. You also have a daily limit on geocodes as well
var delay = 100;
// checks is browser is compatible - note: isn't it nice how Google does
// this for us? In the past a special function would have to
//check for the browser etc,etc it was such a pain. Google has another nice // function that we'll get to very soon
if (GBrowserIsCompatible()) {
// Creates an instance of the GClientGeocoder class
var geo = new GClientGeocoder();
// Geocode function getAddress is defined - it takes an address and a
// callback function as a argument
function getAddress(search, next) {
// uses GClientGeocoder method getLocations to search for the given
// address then immediate defines the callback with the result given
geo.getLocations(search, function (result)
{
// If that was successful
if (result.Status.code == G_GEO_SUCCESS) {
// Here we retrieve the values from the result that is in JSON format, for
// a clear idea on what the output looks like take a look at this page
// http://code.google.com/apis/maps/documentation
// services.html#Geocoding_Structured
var p = result.Placemark[0].Point.coordinates;
var lat=p[1];
var lng=p[0];
// Outputs in XML
var xml = ' <marker address="'
+ search + '" lat="' +lat+ '" lng="' +lng+ '"><br>';
// outputs the xml in our <div>
document.getElementById("message").innerHTML += xml;
}
else {
// If we got here then we got some sort of error. If the error means
// we are requesting too fast then lets increase the delay and try again
if (result.Status.code == G_GEO_TOO_MANY_QUERIES) {
nextAddress--;
delay++;
} else {
// it wasnt because of a delay so just output the error
var reason="Code "+result.Status.code;
var xml = ' <marker address="'
+ search + '" error="' +reason+ '"><br>';
document.getElementById("message").innerHTML += xml;
}
}
//runs our callback function nextAddress
next();
}
);
}
// Here we use another great time saving Google function
// GDownloadUrl is just like XmlHttpRequest but does not require
// readState checking - very nice! The file we want to open is passed
// we then say we want the results to follow and passed as doc variable
// note: this is a global variable because its called with var
var addresses = new Array();
GDownloadUrl("listClientsXML.php", function(doc,responseCode) {
// GXml is a XML parser. We take our results and place it into a instance
// of the GXml class
if(responseCode == 200) {
var xmlDoc = GXml.parse(doc);
// The data we are viewing looks like this from our PHP script
// <client address="3524 ROCKDALE CT,21244">
// gets all the elements named 'client'
var markers = xmlDoc.documentElement.getElementsByTagName("client");
// for until we get to the end of the client elements
for (var i = 0; i < markers.length; i++) {
// now lets get the address attributes from each one
var address = markers[i].getAttribute("address");
// add it to our array
addresses[i] = address;
// the continue
}
// Ok now we actually call nextAddress for the first time, we call it
// here because now our XML is done and loaded
nextAddress();
} else {
alert('Can't open file');
}
});
var nextAddress = 0;
// The function that gets it all started (after the XML)
function nextAddress() {
// starts one at a time ..
if (nextAddress < addresses.length) {
//setTimeout creates our delay, then getAddress with first address
// from our address array, pass our callback function (this func) and
// also tell setTimeout our delay then move to next address
setTimeout('getAddress("'+addresses[nextAddress]+'",nextAddress)', delay);
nextAddress++;
} else {
// we're done, close the xml
document.getElementById("message").innerHTML += "</markers>";
}
}
}
// display a warning if the browser was not compatible
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
</script>
That's it! It also should be noted I got some of this source from http://www.commchurch.freeserve.co.uk the tutorials there are really great and I suggest everyone take a look at them.
Ok so now we have our JavaScript source. I'm pretty tired now so I'm going to call it a night. Stay tuned and I'll show you the PHP file used for the XML and also the final step - the map program.