Saturday 4 August 2012

Demo/About/Documentation geolocation API , IP address based Geolocation


Demo/About/Documentation geolocation API

The geolocation-feature implements the navigator.geolocation API. The following methods are available:

    navigator.getCurrentPosition: successCallback, errorCallback and options ({timeout: number}) are supported
    navigator.watchPosition: in shim identical to getCurrentPosition, except it returns an useless ID
    navigator.clearWatch: is noop in shim

The shim uses the geolocation information provided by http://freegeoip.net and/or googles API-Loader
Options for geolocation

    confirmText (string): confirm text for requesting access to geo data.

$.webshims.setOptions('geolocation', { confirmText: '{location} wants to know your position. It is Ok to press Ok.' }); navigator.geolocation.getCurrentPosition(function(pos){ alert("Thx, you are @ latitude: "+ pos.coords.latitude +"/longitude: " + pos.coords.longitude); });

The following code extracts illustrate how to obtain basic location information:

Example of a "one-shot" position request.

    function showMap(position) {
      // Show a map centered at (position.coords.latitude, position.coords.longitude).
    }

    // One-shot position request.
    navigator.geolocation.getCurrentPosition(showMap);
   

Example of requesting repeated position updates.

    function scrollMap(position) {
      // Scrolls the map so that it is centered at (position.coords.latitude, position.coords.longitude).
    }

    // Request repeated updates.
    var watchId = navigator.geolocation.watchPosition(scrollMap);

    function buttonClickHandler() {
      // Cancel the updates when the user clicks a button.
      navigator.geolocation.clearWatch(watchId);
    }
   

Example of requesting repeated position updates and handling errors.

    function scrollMap(position) {
      // Scrolls the map so that it is centered at (position.coords.latitude, position.coords.longitude).
    }

    function handleError(error) {
      // Update a div element with error.message.
    }

    // Request repeated updates.
    var watchId = navigator.geolocation.watchPosition(scrollMap, handleError);

    function buttonClickHandler() {
      // Cancel the updates when the user clicks a button.
      navigator.geolocation.clearWatch(watchId);
    }
   

Example of requesting a potentially cached position.

    // Request a position. We accept positions whose age is not
    // greater than 10 minutes. If the user agent does not have a
    // fresh enough cached position object, it will automatically
    // acquire a new one.
    navigator.geolocation.getCurrentPosition(successCallback,
                                             errorCallback,
                                             {maximumAge:600000});

    function successCallback(position) {
      // By using the 'maximumAge' option above, the position
      // object is guaranteed to be at most 10 minutes old.
    }

    function errorCallback(error) {
      // Update a div element with error.message.
    }

   

Forcing the user agent to return a fresh cached position.

    // Request a position. We only accept cached positions whose age is not
    // greater than 10 minutes. If the user agent does not have a fresh
    // enough cached position object, it will immediately invoke the error
    // callback.
    navigator.geolocation.getCurrentPosition(successCallback,
                                             errorCallback,
                                             {maximumAge:600000, timeout:0});

    function successCallback(position) {
      // By using the 'maximumAge' option above, the position
      // object is guaranteed to be at most 10 minutes old.
      // By using a 'timeout' of 0 milliseconds, if there is
      // no suitable cached position available, the user agent
      // will asynchronously invoke the error callback with code
      // TIMEOUT and will not initiate a new position
      // acquisition process.
    }

    function errorCallback(error) {
      switch(error.code) {
        case error.TIMEOUT:
          // Quick fallback when no suitable cached position exists.
          doFallback();
          // Acquire a new position object.
          navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
          break;
        case ... // treat the other error cases.
      };
    }

    function doFallback() {
      // No fresh enough cached position available.
      // Fallback to a default position.
    }
   

Forcing the user agent to return any available cached position.

    // Request a position. We only accept cached positions, no matter what
    // their age is. If the user agent does not have a cached position at
    // all, it will immediately invoke the error callback.
    navigator.geolocation.getCurrentPosition(successCallback,
                                             errorCallback,
                                             {maximumAge:Infinity, timeout:0});

    function successCallback(position) {
      // By setting the 'maximumAge' to Infinity, the position
      // object is guaranteed to be a cached one.
      // By using a 'timeout' of 0 milliseconds, if there is
      // no cached position available at all, the user agent
      // will immediately invoke the error callback with code
      // TIMEOUT and will not initiate a new position
      // acquisition process.
      if (position.timestamp < freshness_threshold &&
          position.coords.accuracy < accuracy_threshold) {
        // The position is relatively fresh and accurate.
      } else {
        // The position is quite old and/or inaccurate.
      }
    }

    function errorCallback(error) {
      switch(error.code) {
        case error.TIMEOUT:
          // Quick fallback when no cached position exists at all.
          doFallback();
          // Acquire a new position object.
          navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
          break;
        case ... // treat the other error cases.
      };
    }

    function doFallback() {
      // No cached position available at all.
      // Fallback to a default position.
    }
   
IP address based Geolocation

So now the obvious question is what about those browsers that don’t support geolocation at all? The answer is that we must use an external geolocation service. These services do their best to map the IP address of a device to geographic locations using large geolocation databases. Usually they do a good job, but at times they may suffer from the following issues:

    IP addresses may be associated with the wrong location (e.g., the wrong postal code, city or suburb within a metropolitan area).
    Addresses may be associated only with a very broad geographic area (e.g., a large city, or a state). Many addresses are associated only with a city, not with a street address or latitude/longitude location.
    Some addresses will not appear in the database and therefore cannot be mapped (often true for IP numbers not commonly used on the Internet).

The important thing to remember is that when an external geolocation service is used, the accuracy is not as good as geolocation native to the device, and in some scenarios it may be completely off. Additionally, such services do not provide any information regarding the altitude, speed or heading of the device. Regardless, when GPS or triangulation are not available, they are a good fallback.

YQL Geo Library is a dedicated and lightweight library that lets you perform geolocation using good old Yahoo services. This library can do other things which I’ll leave to you to discover, but for now let’s look at how we should modify our code to successfully detect the location on both supporting and non-supporting browsers:
view plaincopy to clipboardprint?

    <!DOCTYPE html>
    <html>
     
      <head>
      <script src="js/jquery-1.4.2.min.js"></script>
      <script src="js/yqlgeo.js"></script>
      <script>
        jQuery(window).ready(function(){
            jQuery("#btnInit").click(initiate_geolocation);
        })
     
        function initiate_geolocation() {
            if (navigator.geolocation)
            {
                navigator.geolocation.getCurrentPosition(handle_geolocation_query, handle_errors);
            }
            else
            {
                yqlgeo.get('visitor', normalize_yql_response);
            }
        }
     
        function handle_errors(error)
        {
            switch(error.code)
            {
                case error.PERMISSION_DENIED: alert("user did not share geolocation data");
                break;
     
                case error.POSITION_UNAVAILABLE: alert("could not detect current position");
                break;
     
                case error.TIMEOUT: alert("retrieving position timedout");
                break;
     
                default: alert("unknown error");
                break;
            }
        }
     
        function normalize_yql_response(response)
        {
            if (response.error)
            {
                var error = { code : 0 };
                handle_error(error);
                return;
            }
     
            var position = {
                coords :
                {
                    latitude: response.place.centroid.latitude,
                    longitude: response.place.centroid.longitude
                },
                address :
                {
                    city: response.place.locality2.content,
                    region: response.place.admin1.content,
                    country: response.place.country.content
                }
            };
     
            handle_geolocation_query(position);
        }
     
        function handle_geolocation_query(position){
            alert('Lat: ' + position.coords.latitude + ' ' +
                  'Lon: ' + position.coords.longitude);
            }
        </script>
     
      </head>
      <body>
        <div>
          <button id="btnInit" >Find my location</button>
        </div>
     
      </body>
    </html>

No comments:

Post a Comment

Note: only a member of this blog may post a comment.