Geolocation developer

From HaFrWiki42
Jump to navigation Jump to search

Geolocation is the identification or estimation of the real-world geographic location of an object, such as a radar source, mobile phone, or Internet-connected computer terminal.
In this page only the Website HTML-5 Geolocation is described [1].

The HTML Geolocation option is build-in option in HTML-5.
The purpose of this page is to describe how to implement the Geolocation in JavaScript with jQuery.

Introduction

The HTML-5 Geolocation implementation makes it possible to get the current location of the Website user with the following restrictions:

  • The feature is only available in secure contexts (https).
  • The user has to give permission to access his personal location (privacy reason).

The functionality has also a limitation:

  • A VPN connection hides the real position and replace the location by the VPN instead. This makes the Geolocation useless.

Usage

JavaScript Anonymous function

For me the best way to implement new functionality is by using an anonymous function with all referred variables and methods inside the anonymous function.
Sorry for the users but I am an addict of the C printf/sprintf functions, look for a good implementation on the internet or look at the details below. <syntaxhighlight lang="javascript" line="line"> /**

* Anonymous function for handling geolocation.
* @param  object geoLocation Object and Name of the function.
* @param  object $           jQuery Object.
* @param  object undefined   Prevents the overriding of the undefined.
*/

(function( geoLocation, $, undefined ) {

  'use strict';
  geoLocation.versionNumber = "0.1.0.1";
  geoLocation.versionDate   = "30 Sep 2017";
  /** GeoData object. */
  var geoData = {
     available      : "geolocation" in navigator,
     allowed        : false,    // Has the user consented in the geolocation detection.
     latitude       : -1,
     longitude      : -1,
  };
  /* Verbode developer flag. */
  var verbose             = false;
  /**
   * Gets the Version number and date of the anonymous function.
   * @return string number + date.
   */
  geoLocation.version = function() {
     return sprintf("%s - %s", geoLocation.versionNumber, geoLocation.versionDate)
  }
  /**
   * Initializes the geoLocation.
   * @param boolean verboseFlag  Optional Verbose flag.
   * @return void
   */
  geoLocation.init = function( verboseFlag) {
     'use strict';
     verbose = typeof verboseFlag === 'undefined' ? verbose : verboseFlag;
     if ( location.protocol == 'https:' && geoData.available ) {
        if ( navigator.geolocation ) {
           navigator.geolocation.getCurrentPosition( geoLocation.successLocation, geoLocation.errorLocation );
           return;
        }
     }
     geoLocation.errorLocation();
  }  // .init
  /**
   * Success Callback function for getting the User location.
   * When called the geodata object is enriched with allowed, Latitude and Longitude.
   * @global Object geoData  JSO GeoLocation object.
   * @param  Object position JSO with latitude and longitude.
   * @return void
  */
  geoLocation.successLocation = function( position ) {
     'use strict';
     var met = "geoLocation.successLocation";
     geoData.allowed   = true;
     geoData.latitude  = position.coords.latitude;
     geoData.longitude = position.coords.longitude;
     logts( sprintf( logFormatLBW, met, "GeoLocation",
        "Latitude: " + geoData.latitude + ", Longitude: " + geoData.longitude));
  }  // .successLocation
  /**
   * Error Callback function for handling errors in GeoLocation.
   * Sets the global geoData.allowed to false.
   * @return void
  */
  geoLocation.errorLocation = function() {
     'use strict';
     var met = "geoLocation.errorLocation";
     logts( sprintf( logFormatLBW, met, "GeoLocation", "No position available"));
     geoData.allowed   = false;
  }  // .errorLocation
  /**
   * Checks the given protocol.
   * For realtime https is necesassry, for local testing http.
   * Sets the geoData.allowed flag.
   * @return void
   */
  geoLocation.checkProtocol = function() {
     if ( location.protocol == 'http:') {
        geoData.allowed   = true;
        geoData.latitude  = 52.414947;
        geoData.longitude =  7.082583;
        return false;
     }
     return true;
  }  // checkProtocol
  /**
   * Getters for the geoData.allowed, geoData.latitude, geoData.getLongitude
   * @return boolean geoData.allowed
   */
  geoLocation.getAllowed =  function() {
     return geoData.allowed;
  }
  geoLocation.getLatitude = function() {
     return geoData.latitude;
  }  // . getLatitude
  geoLocation.getLongitude = function() {
     return geoData.longitude;
  }  // .getLongitude

} ( window.geoLocation = window.geoLocation || {}, jQuery) ); </syntaxhighlight>

  • Line 7 - 10: The anonymous function name and version number and date.
  • Line 12 - 18: The geodata object with all important variables,
    • available is set true when the geolocation is available in the browser
    • allowed is set true when the user has permitted the usage of his location.
  • geoLocation.version is a public method for returning the version date and number.
  • geoLocation.init is the public method that the user has to call to use the anonymous function.
  • geoLocation.successLocation is a public callback function that is called by the geoLocation.init in case of success.
  • geoLocation.errorLocation is a public callback function that is called by the geoLocation.init in case of an error/failure.
  • geoLocation.checkProtocol is the public function that can be used for testing the anonymous function functionality in a http environment. It sets a dummy location.

Calling anonymous function

To use the anonymous function place the following in the .ready function of your Website.

<syntaxhighlight lang="javascript" line="line"> /**

* jQuery function .ready
*/

$(document).ready(

     function() {
        'use strict';
        ...
        // Initializes the geoLocation.
        geoLocation.init();
       ...
       setTimeout( "bgAuditMonitor()", 3500);

});

/**

* Time delayed Audit monitor call.
* The delay is necessary to catch the GeoLocation (only under https protocol).
* @global ipAddress, loginID, loginUID
* @return void
*/

function bgAuditMonitor() {

     'use strict';
     ...
     // If there is geolocation information 
     if (geoLocation.getAllowed() ) {
        altert( "Geolocation latitude " + geoLocation.getLatitude() + ", longitude " +geoLocation.getLongitude() );
     }

} </syntaxhighlight>

  • line 1 - 7: Example lines to implement the jQuery.ready() method.
  • line 8 - 9: Calling the anonymous function geoLocation.init() method which will set all necessary variables.
  • line 11: Calls the method to show the found geolocation with a timeout because the location determination has a delay itself.
  • line 20 - 27: Example setTime method implementation for showing the geolocation.

Details

Detecting Geolocation Availability

First detect if your browser and context support geolocation. Use the following code: <syntaxhighlight lang="javascript" line='line'> if ("geolocation" in navigator) {

 /* geolocation is available */

} else {

 /* geolocation IS NOT available */

} </syntaxhighlight>

Browser Compatibility

Feature Chrome Edge Firefox Internet Explorer Opera Safari
Basic Support 5.0 (Yes) 3.5 9 10.6 5
Secure origins only 50.0 No support 55 No support 39 10


Utility/Tools

sprintf

<syntaxhighlight lang="javascript" line="line"> /** Javascript implementation for C/C++ sprintf. Uses InvalidArgumentException and getJSFileLinePos. (since 1.0.6.3). The elements are variable string list with arguments. @return string formatted according to the required format.

  • /

function sprintf() {

  'use strict';
  var   i = 0, a,
        f = arguments[i++],
        o = [], m, p, c, x, s = ;
  while (f) {
     if (m = /^[^\x25]+/.exec(f)) {
        o.push(m[0]);
     } else if (m = /^\x25{2}/.exec(f)) {
        o.push('%');
     } else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
        if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) {
           var as = "",
               aj = 0,
               an = arguments.length;
           for (aj = 0; aj< an; aj++) {
              as+= arguments[aj] + "; ";
           }
           throw(" Too few arguments. Given arguments: " + as);
        }
        if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) {
           // throw('Expecting number but found ' + typeof(a));
           throw new InvalidArgumentException("Expecting number but found " + typeof(a) + " " +
                       getJSFileLinePos( new Error().stack, 2) + ".");
        }
        switch (m[7]) {
           case 'b': a = a.toString(2); break;
           case 'c': a = String.fromCharCode(a); break;
           case 'd': a = parseInt(a); break;
           case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
           case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
           case 'o': a = a.toString(8); break;
           case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
           case 'u': a = Math.abs(a); break;
           case 'x': a = a.toString(16); break;
           case 'X': a = a.toString(16).toUpperCase(); break;
        }
        a = (/[def]/.test(m[7]) && m[2] && a >= 0 ? '+'+ a : a);
        c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
        x = m[5] - String(a).length - s.length;
        p = m[5] ? str_repeat(c, x) : ;
        o.push(s + (m[4] ? a + p : p + a));
     } else {
        throw('Huh ?!');
        // throw new InvalidArgumentException("Huh ?! " + getJSFileLinePos( new Error().stack, 2) + ".");
     }
     f = f.substring(m[0].length);
  }
  return o.join();

} // sprintf

/** InvalidArgumentException @param message The String exception-error-message @since 1.0.6.3

  • /

function InvalidArgumentException(message) {

   this.message = message;
   // Use V8's native method if available, otherwise fallback
   if ("captureStackTrace" in Error)
       Error.captureStackTrace(this, InvalidArgumentException);
   else
       this.stack = (new Error()).stack;

} // InvalidArgumentException

InvalidArgumentException.prototype = Object.create(Error.prototype); InvalidArgumentException.prototype.name = "InvalidArgumentException"; InvalidArgumentException.prototype.constructor = InvalidArgumentException;

/** Gets the File-Line-Position of the error location. The function expects the index to be the correct place of the calling function so the search for the error is simplified. See for an example call the function sprintf. The difference between the browsers for a successful implementation almost impossible.. @param es String Exception Stack error (create with 'new Error().stack'). @param index Integer Index of the line in the stack trace containing the error. @since 1.0.6.3

  • /

function getJSFileLinePos(es, index) {

  'use strict';
  var i = typeof index === 'undefined' ? 2 : index;
  var bi = getBrowserInfo();
  var separator = "\n";
  var aFLP = es.split(separator);
  var n = aFLP.length;
  if (index >= n) {
     index = n-1;
  }
  switch(bi.name.toLowerCase()) {
     case "safari"  : return aFLP[0].trim();
     default        : return aFLP[index].trim();
  }
  return aFLP[index].trim();

} // getJSFileLinePos </syntaxhighlight>

See also

top

Reference

top

  1. Developer Mozilla, Using Geolocation Developer.