Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML5

HTML5 Geolocation

4.97/5 (36 votes)
15 Dec 2017CPOL11 min read 48.1K  
Explore geolocation with HTML5

Where on Earth am I?

Every one of us occupies a location on Earth. This location is specified by a geographic coordinate system of latitude, longitude, and altitude. With the proliferation of location-aware hardware and software, finding one’s location on the Earth has never been easier. There are many techniques available to identify the location of a user. A computer browser generally uses WIFI or IP based positioning techniques whereas a mobile browser may use cell triangulation that based on your relative proximity to the different cellular towers operated by the telcos, GPS, A-GPS, or WIFI. Today, location awareness is an ever-growing trend that finds its way into many applications like:

  • Showing one’s location on a map especially when you are in an unfamiliar area
  • Providing turn-by-turn navigation while driving on unfamiliar journey
  • Find out the points of interest in one’s vicinity
  • Getting the latest weather or news of one’s area
  • Tagging the location of picture
  • Location tracking of a fleet of delivery trucks

Thanks to HTML5 Geolocation API, you can now look up your own location on Earth using a browser, say Firefox. It is as easy as a piece of cake. Doing is believing. Let get your hands dirty.

Setting the Stage

Type the following code in Listing 1 using a text editor, save it as “finding_me.html”, and launch it on a browser.

HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Finding Me</title>
<script>
function getLocation()
{
    // Check whether browser supports Geolocation API or not
    if (navigator.geolocation) { // Supported
        navigator.geolocation.getCurrentPosition(getPosition);
    } else { // Not supported
        alert("Oop! This browser does not support HTML5 Geolocation.");
    }
}
function getPosition(position)
{
    document.getElementById("location").innerHTML = 
        "Latitude: " + position.coords.latitude + "<br>" +
        "Longitude: " + position.coords.longitude;
}
</script>
</head>
<body>
    <h1>Finding Me</h1>
    <button onclick="getLocation()">Where am I?</button>
    <p id="location"></p>
</body>
</html>

You should see a web page as shown in Figure 1. Note that this code will work on Firefox and Internet Explorer, but not on Google Chrome. Chrome does not allow running Geolocation API from a file:// URI, it will work if you deploy it on a web server like Apache.

Figure 1: finding_me.html on a Browser

Figure 1: finding_me.html on a Firefox Browser

Click on the “Where am I?” button, what do you see?

Figure 2: Seeking Permission to Share Location

Figure 2: Seeking Permission to Share Location

A dialog box as shown in Figure 2 pops up seeking permission to share location, click on “Share Location” to grant.

Figure 3: You are found!

Figure 3: You are found!

Voila, your location is revealed on the screen as shown in Figure 3. Isn’t that a piece of code, I mean cake.

How you wish you could show these location readings on a map so that you could view your location visually, right? Your wish will come true if you read on…

Diving Deeper…

The HTML5 geolocation API has only one object – the navigator.geolocation object. You may liken the navigator.geolocation to a compass on the browser. As browser support for this API is still dubious, it is a de facto practice to check for browser support before proceeding with any geolocation code, just wrap your code inside this if-else template as shown:

JavaScript
// Check whether browser supports Geolocation API or not
if (navigator.geolocation) // Supported
{
    // place the geolocation code here
}
else // Not supported
{
    alert("Oop! This browser does not support HTML5 Geolocation.");
}

The navigator.geolocation object exposes three methods – getCurrentPosition(), watchPosition(), and clearWatch().

getCurrentPosition()

The getCurrentPosition() method is used to obtain the current location of the user. You have already used this method in its simplest form in the code in Listing 1.

JavaScript
navigator.geolocation.getCurrentPosition(getPosition);

Recall in Figure 3 where a dialog has popped up seeking your permission to share your location with the web page. This is what happens whenever the getCurrentPosition() method is called. Users are given the choice to opt-in in order to allow the method to proceed to retrieve your current position. In other words, your privacy is well-respected and protected.

The getCurrentPosition() method takes three parameters:

  • The first parameter is a callback function to be called when the call to getCurrentPosition() method is successful. The callback function will be called with a position object passed from the getCurrentPosition() method. This position object consists of 2 properties: coords and timestamp. In Listing 1, the callback function is “getPosition(position)” which takes a position object parameter and outputs the latitude and longitude through the coords property of this parameter. This is illustrated in the following code:
    JavaScript
    function getPosition(position)
    {
        document.getElementById("location").innerHTML =
            "Latitude: " + position.coords.latitude + "<br>" +
            "Longitude: " + position.coords.longitude;    
    }

    Table 1 shows the properties of the position object.

    Table 1: Position Object

    Property Description
    coords.latitude The coords.latitude property returns the latitude of the user’s current position in decimal degrees.
    coords.longitude The coords.longitude property returns the longitude of the user’s current position in decimal degrees.
    coords.altitude The coords.altitude property returns the height of the user’s current position in meters above the sea level. It will return null if this information is not available.
    coords.accuracy The coords.accuracy property returns the accuracy level of the latitude and longitude coordinates in meters.
    coords.altitudeAccuracy The coords.altitudeAccuracy property returns the accuracy level of the altitude in meters.
    coords.heading The coords.heading property returns the direction of travel of the location-aware device in degrees, where 0° starts from the north and counting clockwise. It will returns null if this information is not available.
    coords.speed The coords.speed property returns the speed of the location-aware device in meters per second. It will return null if this information is not available.
    timestamp The timestamp property returns the time when the position object was acquired.
  • The second parameter is an optional error handling callback function to be invoked when the call to getCurrentPosition() method encounters any one of the following circumstances:
    • Request timed out
    • Location information not available
    • User has denied permission to share the location information

    The callback function will be invoked with a position error object parameter passed from the getCurrentPosition() method. This position error object consists of one property – code. This code property takes one of three values corresponding to the error types as shown in Table 2.

    Table 2: Location Error Codes

    Property Description
    TIMEOUT Request for location information exceeds the timeout property set in the position options object (discussed later).
    POSITION_UNAVAILABLE The position of the location-aware device cannot be determined.
    PERMISSION_DENIED User has denied permission to share the location information.

    You will add a second callback function called “catchError(error)” to the <script> as shown in the following code and as highlighted in Figure 4:

    HTML
    function catchError(error) {
        switch(error.code)
        {
            case error.TIMEOUT:
                alert("The request to get user location has aborted as it has taken too long.");
                break;
    	case error.POSITION_UNAVAILABLE:
                alert("Location information is not available.");
                break;
    	case error.PERMISSION_DENIED:
                alert("Permission to share location information has been denied!");
                break;
    	default:
                alert("An unknown error occurred.");
        }
    }

    Figure 4: catchError() Function

    Figure 4: catchError() Function

    Next, attach the following function as the second parameter to the getCurrentPosition() method as shown:

    JavaScript
    navigator.geolocation.getCurrentPosition(getPosition, catchError);

    Save and launch it on a browser (Firefox), unplug your network cable (or turn off the wireless switch) to simulate the “no network connection” situation, grant the permission for sharing location information (Figure 2), and then click on the “Where am I?” button. What do you see?

    Figure 4: Simulating an Error Situation

    Figure 5: Simulating an Error Situation

    You should see a message box pops up saying “Location information is not available.” as shown in Figure 5. If you look back to the code in the catchError() function, you would notice that this is the error message specified under the case of error.POSITION_UNAVAILABLE. The cause is obviously due to the network cable being unplugged. The catchError() function was invoked by the getCurrentPosition() method as it is not able to obtain any location information due to the broken network connection. (You may recover the network connection to your computer.) Although this error handling parameter is optional, you should always include it as part of the geolocation code. This is one of the best practices to allow the program to fail gracefully as well as to keep the users informed of any run-time errors.

  • The third parameter is an optional position options object that can be used to fine tune the position object returned by the getCurrentPosition() method programmatically. It has three properties as shown in Table 3.
    Table 3: Position Options Object Properties
    Property Description
    timeout The timeout property denotes the number of milliseconds an application will wait for a position information to become available. The default value is infinity.
    maximumAge The maximumAge property denotes the number of milliseconds an application can keep using the cached (previously obtained) location data before trying to obtain new location data. A zero value indicates that the application must not use the cached location data while infinity value indicates that the cached location data must be used by the application. The default value is zero.
    enableHighAccuracy The enableHighAccuracy property denotes the condition of true or false. If it is true, the application will try to provide the most accurate position. However, this would result in slower response time and higher power consumption. The default value is false.

    You will define a position options object called “positionOptions” and add it as the third parameter to the getCurrentPosition() method as shown in the following code and as highlighted in Figure 6:

    JavaScript
    var positionOptions = {
       timeout : Infinity,
       maximumAge : 0,
       enableHighAccuracy : true
    };
    navigator.geolocation.getCurrentPosition(getPosition, catchError, positionOptions);

    Figure 5: Position Options Object

    Figure 6: Position Options Object

    In designing your location-aware application, you should choose the degree of accuracy as well as the retention period of old location data that are most appropriate for the purpose of the application by setting the enableHighAccuracy and the maximumAge properties of the position options object accordingly. For example, if your application is mainly for finding points of interest in your vicinity, you probably do not need high accuracy and the location information does not have to be updated so often. On the other hand, if your application is to provide turn by turn navigation direction for driver, then high accuracy and constant update of location become necessary.

The getCurrentPosition() method is most suitable for obtaining a one-off location information. However, for finding location information that is changing continuously, such as the turn by turn navigation that I mentioned above, you will have to call the getCurrentPosition() method repeatedly which is obviously very cumbersome and inefficient. Fret not! HTML5 Geolocation API has provided another method to handle this kind of situation – watchPosition().

watchPosition()

The watchPosition() method is almost identical to the getCurrentPosition() method. They both return the current location information and have the same method signature – one success callback function, one error callback function, and one position options object. The only difference lies in that the getCurrentPosition() method only returns location information once upon activation such as a button click, whereas The watchPosition() method will continue to obtain location information every time the location of the user’s device changes after the initial activation.

The watchPosition() method returns a watch ID that can be used to stop obtaining location information by passing it to the third method of the navigator.geolocation object – clearWatch(), such as when a car that uses it for navigation has arrived at the destination.

clearWatch()

The clearWatch() method takes the watch ID of a watchPosition() method as a parameter and stop the execution of that watchPosition() method.

Location Tracking

As the watchPosition() method is similar to the getCurrentPosition() method, if you are familiar with the later, creating the watchPosition() method will be much easier – it is mostly a matter of, believe it or not, “copy and paste”.

Open “finding_me.html” in a text editor, save it as “watching_me.html”. Then, in “watching_me.html”,

  • Change “geolocation.getCurrentPosition(getPosition, catchError, positionOptions)” to “navigator.geolocation.watchPosition(getPosition, catchError, positionOptions)”.
  • Store the watch ID returned from the watchPosition() method to a variable watchID.
    JavaScript
    watchID = navigator.geolocation.watchPosition(getPosition, catchError, positionOptions);

That’s all that you need to create a web page that constantly monitors and updates a browser’s current location.

However, to stop the monitoring and updating at some point in time, you will add another piece of code and a button to deactivate it. In the <script> section of “watching_me.html”, create a function called “stopWatch()” that calls the clearWatch() method by passing it the watchID of the watchPosition() method:

JavaScript
function stopWatch() 
{
    navigator.geolocation.clearWatch(watchID);
}

Lastly, replace the HTML code in the <body> of “watching_me.html” with:

HTML
<body>
<h1>Watching Me</h1>
<button onclick="getLocation()">Start Watching</button>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<button onclick="stopWatch()">Stop Watching</button>
<p id="location"></p>
</body>

The complete source code of "watching_me.html" is given below:

HTML
<!DOCTYPE html>
<html>
<head>
<title>Watching Me</title>
<script>
function getLocation()
{
   // Check whether browser supports Geolocation API or not
   if (navigator.geolocation) // Supported
   {
       var positionOptions = {
       timeout : Infinity,
       maximumAge : 0,
       enableHighAccuracy : true
   };
   // Set the watchID
       watchID = navigator.geolocation.watchPosition(getPosition, catchError, positionOptions);
   }
       else // Not supported
   {
       alert("Oop! This browser does not support HTML5 Geolocation.");
   }
}
function stopWatch() 
{
   navigator.geolocation.clearWatch(watchID);
   watchID = null;
}
function getPosition(position)
{
   document.getElementById("location").innerHTML =
        "Latitude: " + position.coords.latitude + "<br>" +
        "Longitude: " + position.coords.longitude; 
}
function catchError(error) {
   switch(error.code) 
   {
       case error.TIMEOUT:
           alert("The request to get user location has aborted as it has taken too long.");
           break;
       case error.POSITION_UNAVAILABLE:
           alert("Location information is not available.");
           break;
       case error.PERMISSION_DENIED:
           alert("Permission to share location information has been denied!");
           break; 
       default:
           alert("An unknown error occurred.");
 }
}
</script>
</head>
<body>
<h1>Watching Me</h1>
<button onclick="getLocation()">Start Watching</button>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<button onclick="stopWatch()">Stop Watching</button>
<p id="location"></p>
</body>
</html>

Save and launch “watching_me.html” on a WIFI connected laptop (Firefox) browser, click the “Start Watching” button, grant the permission to share location, then move around with the laptop. What do you see?

Figure 6: You are being watched!

Figure 7: You are being watched!

You should see your position being updated on the browser at a regular interval as shown in an example in Figure 7.

If you copy and paste the latitude and longitude values to the search box of a Google Map on your browser, Google Map will mark your approximate location with a marker. The location is approximate and may differ on different browsers and devices as the accuracy of which is dependent on a number of factors, such as your public IP address, the nearer cellular towers, GPS availability, WIFI access points, and the type of browser that you are using.

Location Tracking on Map

Let’s put the watch on a map as shown in an example in Figure 8.

Figure 7: You are on the map!

Figure 8: You are on Google map!

The file is called “watching_on_map.html” as shown below and is available for download.

HTML
<!DOCTYPE html>
<html>
<head>
<title>Watching on Map</title>
<style>
html,body {
    height: 100%;
    margin: 0;
    padding: 0;
}
#map-holder {
    height: 350px;
    width: 500px;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
var watchID; 
function getLocation()
{
    // Check whether browser supports Geolocation API or not
    if (navigator.geolocation)  // Supported
    {
        var positionOptions = {
            timeout : Infinity,
            maximumAge : 0,
            enableHighAccuracy : true,
        };
        // Obtain the initial location one-off
        navigator.geolocation.getCurrentPosition(getPosition, catchError, positionOptions);
    }
    else  // Not supported
    {
        alert("Oop! This browser does not support HTML5 Geolocation.");
    }
}    
function watchLocation()
{
    // Check whether browser supports Geolocation API or not
    if (navigator.geolocation)  // Supported
    {
        var positionOptions = {
            timeout : Infinity,
            maximumAge : 0,
            enableHighAccuracy : true,
        };
        // Obtain the location at regularly interval
        watchID = navigator.geolocation.watchPosition(getPosition, catchError, positionOptions);
    }
    else  // Not supported
    {
        alert("Oop! This browser does not support HTML5 Geolocation.");
    }
}
function stopWatch() 
{
    // Discontinue obtaining location
    navigator.geolocation.clearWatch(watchID);
}
function getPosition(position)
{
    var location = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
    var mapOptions = {
        zoom : 12,
        center : location,
        mapTypeId : google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById('map-holder'), mapOptions);
    var marker = new google.maps.Marker({
        position: location,
        title: 'Here I am!',
        map: map,
        animation: google.maps.Animation.DROP
    });
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'latLng' : location
        }, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                if (results[1]) {
                    var options = {
                        content : results[1].formatted_address,
                        position : location
                    };
                    var popup = new google.maps.InfoWindow(options);
                    google.maps.event.addListener(marker, 'click', function() {
                        popup.open(map);
                    });
                } 
                else 
                {
                    alert('No results found');
                }
            } 
            else 
            {
                alert('Geocoder failed due to: ' + status);
            }
        });
}
function catchError(error) {
    switch(error.code) 
    {
        case error.TIMEOUT:
            alert("The request to get user location has aborted as it has taken too long.");
            break;
        case error.POSITION_UNAVAILABLE:
            alert("Location information is not available.");
            break;
        case error.PERMISSION_DENIED:
            alert("Permission to share location information has been denied!");
            break;    
        default:
            alert("An unknown error occurred.");
    }
}
</script>
</head>
<body onload="getLocation()">
<div id="map-holder"></div>
<button onclick="watchLocation()">Start Watching</button>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<button onclick="stopWatch()">Stop Watching</button>
</body>
</html>

The logic of the code works as follows:

  • When the page is first loaded, the onload event will be triggered and calls the getLocation() function which in turn calls the getCurrentPosition() method of the navigator.geolocation object to obtain the user’s current location.
  • If the getCurrentPosition() method is successful, it will trigger the callback function getPosition() passing it the position object.
  • What the getPosition() function does is to render a Google Map that is centered on the user’s location shown as marker.
  • Clicking the “Start Watching” button will call the watchLocation() function which in turn calls the watchPosition() method of the navigator.geolocation object to obtain the user’s current location at a regular interval.
  • If the watchPosition() method is successful, it will trigger the callback function getPosition() passing it the position object.
  • What the getPosition() function does has been described above.
  • Clicking the “Stop Watching” button will stop the watch activity.

If you move around with your WIFI connected laptop while keeping this web page opened, you should see your location being updated on the browser regularly as you move. Have fun!

Download

The post HTML5 Geolocation appeared first on Peter Leow's Code Blog.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)