You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2012/05/07 22:52:06 UTC
[4/8] js commit: start of geolocation rewrite to conform with
Geolocation W3C API spec.
start of geolocation rewrite to conform with Geolocation W3C API spec.
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/95d979d6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/95d979d6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/95d979d6
Branch: refs/heads/master
Commit: 95d979d69e306517c5487f431b0140da0886806f
Parents: 34f5fec
Author: Fil Maj <ma...@gmail.com>
Authored: Thu Mar 22 15:26:08 2012 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Mon May 7 13:51:05 2012 -0700
----------------------------------------------------------------------
lib/common/plugin/Position.js | 8 +++-
lib/common/plugin/geolocation.js | 77 ++++++++++++++++++++++++++++----
test/test.geolocation.js | 40 +++++++++++++----
3 files changed, 104 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/95d979d6/lib/common/plugin/Position.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/Position.js b/lib/common/plugin/Position.js
index 33c5be9..deb7c49 100644
--- a/lib/common/plugin/Position.js
+++ b/lib/common/plugin/Position.js
@@ -1,8 +1,12 @@
var Coordinates = require('cordova/plugin/Coordinates');
var Position = function(coords, timestamp) {
- this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy);
+ if (coords) {
+ this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy);
+ } else {
+ this.coords = new Coordinates();
+ }
this.timestamp = (timestamp !== undefined) ? timestamp : new Date().getTime();
};
-module.exports = Position;
\ No newline at end of file
+module.exports = Position;
http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/95d979d6/lib/common/plugin/geolocation.js
----------------------------------------------------------------------
diff --git a/lib/common/plugin/geolocation.js b/lib/common/plugin/geolocation.js
index 1b86f02..443fb61 100644
--- a/lib/common/plugin/geolocation.js
+++ b/lib/common/plugin/geolocation.js
@@ -8,20 +8,24 @@ var timers = {}; // list of timers in use
// Returns default params, overrides if provided with values
function parseParameters(options) {
var opt = {
- maximumAge: 10000,
+ maximumAge: 0,
enableHighAccuracy: false,
- timeout: 10000
+ timeout: Infinity
};
if (options) {
- if (options.maximumAge !== undefined) {
+ if (options.maximumAge !== undefined && !isNaN(options.maximumAge) && options.maximumAge > 0) {
opt.maximumAge = options.maximumAge;
}
if (options.enableHighAccuracy !== undefined) {
opt.enableHighAccuracy = options.enableHighAccuracy;
}
- if (options.timeout !== undefined) {
- opt.timeout = options.timeout;
+ if (options.timeout !== undefined && !isNaN(options.timeout)) {
+ if (options.timeout < 0) {
+ opt.timeout = 0;
+ } else {
+ opt.timeout = options.timeout;
+ }
}
}
@@ -29,6 +33,7 @@ function parseParameters(options) {
}
var geolocation = {
+ lastPosition:null, // reference to last known (cached) position returned
/**
* Asynchronously aquires the current position.
*
@@ -37,10 +42,24 @@ var geolocation = {
* @param {PositionOptions} options The options for getting the position data. (OPTIONAL)
*/
getCurrentPosition:function(successCallback, errorCallback, options) {
+ if (arguments.length === 0) {
+ throw new Error("getCurrentPosition must be called with at least one argument.");
+ }
options = parseParameters(options);
+ // Timer var that will fire an error callback if no position is retrieved from native
+ // before the "timeout" param provided expires
+ var timeoutTimer = null;
+
var win = function(p) {
- successCallback(new Position(
+ clearTimeout(timeoutTimer);
+ if (!timeoutTimer) {
+ // Timeout already happened, or native fired error callback for
+ // this geo request.
+ // Don't continue with success callback.
+ return;
+ }
+ var pos = new Position(
{
latitude:p.latitude,
longitude:p.longitude,
@@ -51,13 +70,51 @@ var geolocation = {
altitudeAccuracy:p.altitudeAccuracy
},
p.timestamp || new Date()
- ));
+ );
+ geolocation.lastPosition = pos;
+ successCallback(pos);
};
var fail = function(e) {
- errorCallback(new PositionError(e.code, e.message));
+ clearTimeout(timeoutTimer);
+ timeoutTimer = null;
+ var err = new PositionError(e.code, e.message);
+ if (errorCallback) {
+ errorCallback(err);
+ }
};
- exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.timeout, options.maximumAge]);
+ // Check our cached position, if its timestamp difference with current time is less than the timeout, then just
+ // fire the success callback with the cached position.
+ if (geolocation.lastPosition && options.timeout && ((new Date()).getTime() - geolocation.lastPosition.timestamp.getTime() <= options.timeout)) {
+ successCallback(cachedPosition);
+ // If the cached position check failed and the timeout was set to 0, error out with a TIMEOUT error object.
+ } else if (options.timeout === 0) {
+ fail({
+ code:PositionError.TIMEOUT,
+ message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceed's provided PositionOptions' maximumAge parameter."
+ });
+ // Otherwise we have to call into native to retrieve a position.
+ } else {
+ if (options.timeout !== Infinity) {
+ // If the timeout value was not set to Infinity (default), then
+ // set up a timeout function that will fire the error callback
+ // if no successful position was retrieved before timeout expired.
+ timeoutTimer = setTimeout(function() {
+ clearTimeout(timeoutTimer);
+ timeoutTimer = null;
+ fail({
+ code:PositionError.TIMEOUT,
+ message:"Position retrieval timed out."
+ });
+ }, options.timeout);
+ } else {
+ // This is here so the check in the win function doesn't mess stuff up
+ // may seem weird but this guarantees timeoutTimer is
+ // always truthy before we call into native
+ timeoutTimer = true;
+ }
+ exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.timeout, options.maximumAge]);
+ }
},
/**
* Asynchronously watches the geolocation for changes to geolocation. When a change occurs,
@@ -91,4 +148,4 @@ var geolocation = {
}
};
-module.exports = geolocation;
\ No newline at end of file
+module.exports = geolocation;
http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/95d979d6/test/test.geolocation.js
----------------------------------------------------------------------
diff --git a/test/test.geolocation.js b/test/test.geolocation.js
index a24059c..e5fe4f2 100644
--- a/test/test.geolocation.js
+++ b/test/test.geolocation.js
@@ -1,32 +1,54 @@
describe("geolocation", function () {
var geo = require('cordova/plugin/geolocation'),
+ Position = require('cordova/plugin/Position'),
+ PositionError = require('cordova/plugin/PositionError'),
s, e;
exec = require('cordova/exec');
beforeEach(function () {
s = jasmine.createSpy("success");
e = jasmine.createSpy("error");
+ exec.reset();
});
describe("when getting the current position", function () {
- it("uses the default values", function () {
+ beforeEach(function() {
+ geo.lastPosition = null; // reset the cached position
+ });
+
+ it("uses default PositionOptions if none are specified", function () {
geo.getCurrentPosition(s, e);
- expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 10000, 10000]);
+ expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, Infinity, 0]);
});
- it("uses the maximumAge option", function () {
+ it("uses the maximumAge option if specified", function () {
geo.getCurrentPosition(s, e, {maximumAge: 10});
- expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 10000, 10]);
+ expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, Infinity, 10]);
});
- it("uses the enableHighAccuracy option", function () {
+ it("uses the enableHighAccuracy option if specified", function () {
geo.getCurrentPosition(s, e, {enableHighAccuracy: true, maximumAge: 100});
- expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [true, 10000, 100]);
+ expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [true, Infinity, 100]);
});
- it("uses the timeout option", function () {
+ it("uses the timeout option if specified and positive", function () {
geo.getCurrentPosition(s, e, {timeout: 1000});
- expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 1000, 10000]);
+ expect(exec).toHaveBeenCalledWith(jasmine.any(Function), jasmine.any(Function), "Geolocation", "getLocation", [false, 1000, 0]);
+ });
+ it("uses a timeout value of 0 if specified and negative, which should call the error callback immediately (since we have no cached position)", function () {
+ geo.getCurrentPosition(s, e, {timeout: -1000});
+ expect(e).toHaveBeenCalledWith({
+ code:PositionError.TIMEOUT,
+ message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceed's provided PositionOptions' maximumAge parameter."
+ });
+ });
+ it("can be used with one, two or three arguments", function() {
+ expect(function() { geo.getCurrentPosition(s); }).not.toThrow();
+ expect(function() { geo.getCurrentPosition(s,e); }).not.toThrow();
+ expect(function() { geo.getCurrentPosition(s,e,{}); }).not.toThrow();
+ });
+ it("should throw an exception if used with no arguments", function() {
+ expect(function() { geo.getCurrentPosition();}).toThrow("getCurrentPosition must be called with at least one argument.");
});
});
@@ -46,7 +68,7 @@ describe("geolocation", function () {
it("sets an interval for the default timeout", function () {
geo.watchPosition(s, e);
- expect(window.setInterval).toHaveBeenCalledWith(jasmine.any(Function), 10000);
+ expect(window.setInterval).toHaveBeenCalledWith(jasmine.any(Function), Infinity);
});
it("sets an interval for the provided timeout", function () {