Blog on hold: This blog is currently on hold. Please visit thoughts.keranmckenzie.com for new blog posts

Watch Keran's YouTube Channel #theRandomnessProject


HTML5, GeoLocation and Google

Tweet UPDATED ZIP file of code now available here It seems now it’s all the rage to start leveraging some of the new HTML5 spec in your designs, especially now that Firefox 3.5, Chrome & Safari on iPhone 3.0 all support many of the new HTML5 tags. I started looking into geolocation for html5 recently [...]

UPDATED ZIP file of code now available here

It seems now it’s all the rage to start leveraging some of the new HTML5 spec in your designs, especially now that Firefox 3.5, Chrome & Safari on iPhone 3.0 all support many of the new HTML5 tags.

I started looking into geolocation for html5 recently and most of the blog posts I found relate to grabbing the geolocation from the browser (which by the way is the Lat & Long) and popping it on the map using Google or Yahoo maps.

However the reality is that while that’s a nice novel factor, you often don’t want a Lat & Long, what you want is an area, where is this user & what features are around them. I personally wanted to avoid Google Maps like the plague as their terms & conditions are nasty when it comes to corporate applications.

So, I set about trying to find out how I could get the area where a user is, without using Google Maps API. And it turns out it’s not really all that hard. Due to privacy reasons I can’t show you the actual application where this is used, but I can give you some code and a sample file and you can knock yourself out having fun with it. Here is a demo of what we are doing

The idea:
1) Does the users browser support geolocation?
2) Get the geoocation using either navigator.geolocation.getCurrentPosition or navigator.geolocation.watchPosition
3) Hand the Lat & Long off to a reverse geocode service
4) Get a result back allowing me to say “You are in: (area)”

The code
Is really pretty straight forward for the geolocation data from the browser. First up, check to see if the browser supports geolocation and if so then ask the browser for the geolocation.

  if (navigator.geolocation) {
            // YES
            // snapshot of position:
            navigator.geolocation.getCurrentPosition(renderPosition, renderError);
            // updating position:
            // navigator.geolocation.watchPosition(renderPosition, renderError);
        } else {
            // NO
            // PUT ERROR MESSAGE HERE - OR SIMPLY DO NOTHING
        }
    }

You’ll see above that I have both getCurrentPosition and watchPosition, just uncomment the one you want. Note that watchPosition will continually poll the browser for updated positions, if you are feeding that to Google Maps, apparently it’s against their API rules to send continually updating data (you need to check that for yourself).

At this point we now have a Lat & Long (note: you also get other data around accuracy, altitude etc – more on that in the attached zip file) … but I don’t want that, I want an area. So I use a WebService from GeoNames to do the reverse lookup. This is a nice service that can return XML or JSON for you, and includes a bunch of details about that area.

Now this is where I got caught out. I use JQuery to handle my javascript to get the updated location and write it to my page. Of course javascript is limited in what it can do from one domain to another. A lovely friend of mine kindly pointed out that I’d need some form of proxy to grab the data. He threw together a very simple PHP one for me. So at this point you need jQuery and PHP to get the data.

The PHP file looks like – note you could use readfile(), however many servers have that disabled so I wrote up a simple function using CURL to get the file:

< ?php if ($_GET['type'] == 'JSON') { 
    CURL_file_get_contents('http://ws.geonames.org/findNearbyPlaceNameJSON?lat='.$_GET['lat'].'&lng='.$_GET['lon']); 
} 

if ($_GET['type'] == 'XML') {
    CURL_file_get_contents('http://ws.geonames.org/findNearbyPlaceName?lat='.$_GET['lat'].'&lng='.$_GET['lon']); 
}

function CURL_file_get_contents( $url ) {
           $open_file = curl_init();
             // Tell CURL the url to open.
           curl_setopt($open_file, CURLOPT_URL, $url); 
            // Tell CURL to return the file in a string.
           curl_setopt($open_file, CURLOPT_RETURNTRANSFER, 1); 
            // Execute the CURL command and retrun the page in a string. 
          $return_var = curl_exec($open_file);
          curl_close($open_file);
           echo $return_var; 
} ?>

Right, so now we just need some javascript to tie it all together (oh it’s assumed you have jQuery installed).

//jQuery to render the output
        function renderPosition(position) {

            if (!window.count) window.count = 0;
            var urlJSON ='';

            count ++;
            // var urlJSON = 'http://ws.geonames.org/findNearbyPlaceNameJSON?lat=-36.9104718&lng=174.9133483';
            var urlJSON = 'geonames.php?type=JSON&lat='+position.coords.latitude+'&lon='+position.coords.longitude;
            var urlXML  = 'geonames.php?type=XML&lat=' +position.coords.latitude+'&lon='+position.coords.longitude;

            $('#d').html( 'Latitude: ' + position.coords.latitude + '
'+ 'Longitude: ' + position.coords.longitude + '
' + 'Accuracy: ' + position.coords.accuracy + '
'+ 'Update number: ' + count + '
'+ 'Altitude: ' + position.coords.altitude + '
'+ 'Altitude accuracy: ' + position.coords.altitudeAccuracy + '
'+ 'Heading: ' + position.coords.heading + '
'+ 'Speed:' + position.coords.speed + '
');
            // now get the XML reverse geo data
            $.getJSON(urlJSON, function(json) {

                /* Parse JSON objects */
                $.each(json.geonames,function(i,item) {
                    // get the name - which is the suburb - and update the page
                    // alert('name: ' + item.name);
                    $('#jsonResults').html(You live in: ' + item.name );
                });

            });
        }

        function renderError() {
            $('#georesults').html('Err houston, we have a problem');
        }

This is kind of overkill, but it shows you all the data we get back from the geolocation service within HTML5.

Now you have results, and as you can see from $(‘#jsonResults’).html(‘You live in: ‘ + item.name); I simply output the name element from the JSON back to the html.

From here you can do anything with this, write it into a form, mimic iPhone apps etc. I’ve not tried this, but someone did tell me that this also works fine on Android.

Download the zip file and have a look or take a look at the demo (note you need Firefox 3.5, mobile Safari etc)

Links

Support Studiowhiz.com

3 Responses

07.17.09

I’d love to see the code here but the zip file doesn’t seem to be there . . .

07.17.09

ahh yeah, sorry, it was there but wasn’t very clear as to where to download from – so I changed the link. Grab it from here now

[...] learn how to add the geolocation code to your web pages and connect it with a web service, check this excellent tutorial from Studiowhiz. [...]