js/geolocation.js
author Ryan Willoughby <ryan.willoughby@nitobi.com>
Tue, 06 Jul 2010 11:31:19 -0700
changeset 0 54063d8b0412
permissions -rwxr-xr-x
initial commit of PhoneGap WRT framework, licensing and test code

/**
 * This class provides access to device GPS data.
 * @constructor
 */
function Geolocation() {
    /**
     * The last known GPS position.
     */
    this.lastPosition = null;
    this.lastError = null;
    this.callbacks = {
        onLocationChanged: [],
        onError:           []
    };
};

/**
 * Asynchronously aquires the current position.
 * @param {Function} successCallback The function to call when the position
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the position data.
 * @param {PositionOptions} options The options for getting the position data
 * such as timeout.
 */
Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) {
    var referenceTime = 0;
    if (this.lastPosition)
        referenceTime = this.lastPosition.timestamp;
    else
        this.start(options);

    var timeout = 20000;
    var interval = 500;
    if (typeof(options) == 'object' && options.interval)
        interval = options.interval;

    if (typeof(successCallback) != 'function')
        successCallback = function() {};
    if (typeof(errorCallback) != 'function')
        errorCallback = function() {};

    var dis = this;
    var delay = 0;
    var timer = setInterval(function() {
        delay += interval;
		//if we have a new position, call success and cancel the timer
        if (dis.lastPosition && dis.lastPosition.timestamp > referenceTime) {
            successCallback(dis.lastPosition);
            clearInterval(timer);
        } else if (delay >= timeout) { //else if timeout has occured then call error and cancel the timer
            errorCallback();
            clearInterval(timer);
        }
		//else the interval gets called again
    }, interval);
};

/**
 * Asynchronously aquires the position repeatedly at a given interval.
 * @param {Function} successCallback The function to call each time the position
 * data is available
 * @param {Function} errorCallback The function to call when there is an error 
 * getting the position data.
 * @param {PositionOptions} options The options for getting the position data
 * such as timeout and the frequency of the watch.
 */
Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) {
	// Invoke the appropriate callback with a new Position object every time the implementation 
	// determines that the position of the hosting device has changed. 
	this.getCurrentPosition(successCallback, errorCallback, options);
	var frequency = 10000;
        if (typeof options == 'object' && options.frequency)
            frequency = options.frequency;
	var that = this;
	return setInterval(function() {
		that.getCurrentPosition(successCallback, errorCallback, options);
	}, frequency);
};


/**
 * Clears the specified position watch.
 * @param {String} watchId The ID of the watch returned from #watchPosition.
 */
Geolocation.prototype.clearWatch = function(watchId) {
	clearInterval(watchId);
};

Geolocation.prototype.start = function(options) {
	var so = device.getServiceObject("Service.Location", "ILocation");
	
	//construct the criteria for our location request
	var updateOptions = new Object();
	// Specify that location information need not be guaranteed. This helps in
	// that the widget doesn't need to wait for that information possibly indefinitely.
	updateOptions.PartialUpdates = true;
	
	//default 15 seconds
	if (typeof(options) == 'object' && options.timeout) 
		//options.timeout in in ms, updateOptions.UpdateTimeout in microsecs
		updateOptions.UpdateTimeOut = options.timeout * 1000;

	//default 1 second
	if (typeof(options) == 'object' && options.interval) 
		//options.timeout in in ms, updateOptions.UpdateTimeout in microsecs
		updateOptions.UpdateInterval = options.interval * 1000;
	
	// Initialize the criteria for the GetLocation call
	var trackCriteria = new Object();
	// could use "BasicLocationInformation" or "GenericLocationInfo"
	trackCriteria.LocationInformationClass = "GenericLocationInfo";
	trackCriteria.Updateoptions = updateOptions;
	
	var dis = this;
	so.ILocation.Trace(trackCriteria, function(transId, eventCode, result) {
		var retVal = result.ReturnValue;

		if (result.ErrorCode != 0 || isNaN(retVal.Latitude))
			return;
		
		// heading options: retVal.TrueCourse, retVal.MagneticHeading, retVal.Heading, retVal.MagneticCourse
		// but retVal.Heading was the only field being returned with data on the test device (Nokia 5800)
		// WRT does not provide accuracy
		var newCoords = new Coordinates(retVal.Latitude, retVal.Longitude, retVal.Altitude, null, retVal.Heading, retVal.HorizontalSpeed);
		var positionObj = { coords: newCoords, timestamp: (new Date()).getTime() };

		dis.lastPosition = positionObj;
	});
	
};


if (typeof navigator.geolocation == "undefined") navigator.geolocation = new Geolocation();