Right now I’m building a mobile app using Intel’s AppFramework for a single page site, and Apigility for the API.

In the app, there is an autosuggest for towns and postcodes, however I thought it would be nice to have a “Locate Me” button, able to pinpoint your visitor (hopefully with a decent degree of accuracy!), so I Googled away and found the following:


In your site go into your js folder and clone the repo:

cd js
git clone git@github.com:estebanav/javascript-mobile-desktop-geolocation.git

In your page you’ll include the scripts and add your functionality as required:

<script src="js/javascript-mobile-desktop-geolocation/js/geoPosition.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/javascript-mobile-desktop-geolocation/js/geoPositionSimulator.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
    // Geolocation Initialisation
    geoPosition.getCurrentPosition(success_callback,error_callback,    {enableHighAccuracy:true});
    // You cannot use Geolocation in this device
// p : geolocation object
 function success_callback(p)
    // p.latitude : latitude value
    // p.longitude : longitude value
function error_callback(p)
    // p.message : error message

Now if you load your page and go into the web inspector, hopefully you should have some coordinates!

The next part of the puzzle is where it gets interesting: How to find the closest match in your table of areas, postcodes, and lat longs!

I would never have figured this out, but there is an equation called the Haversine formula, which uses spherical trigonometry to calculate areas within a certain distance! It looks like this:

R = earths radius (mean radius = 6,371km)
Δlat = lat2 lat1
Δlong = long2 long1
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1a))
d = R.c
Angles need to be in radians to pass to Trigonometric functions


Here’s my actual query itself:

 ( 3959 * acos( cos( radians(55.864237) ) * cos( radians( latitude ) ) 
 * cos( radians( longitude ) - radians(-4.251806) ) + sin( radians(55.864237) ) 
 * sin( radians( latitude ) ) ) ) AS distance 
FROM postcodes HAVING distance < 20 
ORDER BY distance LIMIT 1;

Here I check for any area within 20 miles, but you can make this as short or long as you want.  The 3959 figure at the start of the query is the number used for miles, if you are using kilometres you should change this number to 6371.  I have limited it to 1 row, as I only want the closest match, however you may want to change this in other situations!

So there we have it! NSA-like spying on your visitors! (With their permission of course!)