Skip to content

Commit

Permalink
Improve Geolocation package.
Browse files Browse the repository at this point in the history
Add the ability to tweak the PositionOptions used for Geolocation, for
instance to use low-accuracy position to save battery on mobile devices.
The options parameter is reactive.

Add a `pause` feature to temporarily halt position updates, again to
allow better power management on mobile devices.  The paused status
is also reactive.

Stop position watcher when there are no dependencies of the location,
so that we automatically save power if (for example) a reactive map
view is not visible.
  • Loading branch information
cscott committed Jan 15, 2015
1 parent 7a0f796 commit 10a0d36
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 22 deletions.
2 changes: 1 addition & 1 deletion examples/simple-map/.meteor/versions
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ [email protected]
[email protected]
[email protected]
[email protected]
mdg:[email protected].2
mdg:[email protected].3
[email protected]
[email protected]
[email protected]
Expand Down
7 changes: 6 additions & 1 deletion examples/simple-map/map.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ <h1>Where am I?</h1>

<img src="http://maps.googleapis.com/maps/api/staticmap?center={{loc.lat}},{{loc.lng}}&zoom=15&size=600x300&maptype=roadmap&markers=color:blue%7C{{loc.lat}},{{loc.lng}}" />

<label class="high-accuracy">
<input type="checkbox" checked="{{highAccuracy}}" />
High accuracy position
</label>

{{#if error}}
<p>Error: {{error.message}}</p>
{{/if}}
</body>
</body>
19 changes: 16 additions & 3 deletions examples/simple-map/map.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
if (Meteor.isClient) {
Template.body.events({
"change .high-accuracy input": function (event) {
Session.set("highAccuracy", event.target.checked);
}
});
Template.body.helpers({
loc: function () {
// options is *optional*. We're including it in this demo
// to show how it is reactive.
var options = {
enableHighAccuracy: !!Session.get("highAccuracy")
};
// return 0, 0 if the location isn't ready
return Geolocation.latLng() || { lat: 0, lng: 0 };
return Geolocation.latLng(options) || { lat: 0, lng: 0 };
},
error: Geolocation.error
error: Geolocation.error,
highAccuracy: function() {
return Session.get("highAccuracy");
}
});
}
}
18 changes: 15 additions & 3 deletions packages/mdg:geolocation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,22 @@ There are currently no options to set. Every method is reactive using [Tracker](

Returns the [position error](https://developer.mozilla.org/en-US/docs/Web/API/PositionError) that is currently preventing position updates.

### Geolocation.currentLocation()
### Geolocation.currentLocation(options)

Returns the [position](https://developer.mozilla.org/en-US/docs/Web/API/Position) that is reported by the device, or null if no position is available.

### Geolocation.latLng()
The `options` parameter is optional; if provided it as if `Geolocation.setOptions` was called before returning the position.

A simple shorthand for currentLocation() when all you need is the latitude and longitude. Returns an object that has `lat` and `lng` keys.
### Geolocation.latLng(options)

A simple shorthand for currentLocation() when all you need is the latitude and longitude. Returns an object that has `lat` and `lng` keys.

The `options` parameter is optional; if provided it as if `Geolocation.setOptions` was called before returning the position.

### Geolocation.setOptions(options)

Provide [PositionOptions](https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions) to manage power consumption on mobile devices. The options can be reactive.

### Geolocation.setPaused(boolean)

If the parameter is `true`, temporarily halts reactive position updates to reduce power consumption.
76 changes: 64 additions & 12 deletions packages/mdg:geolocation/geolocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,53 @@ var location = new ReactiveVar(null);
var error = new ReactiveVar(null);

// options for watchPosition
var options = {
var options = new ReactiveVar({
enableHighAccuracy: true,
maximumAge: 0
};
}, function(a, b) {
// Reject attempts to set this to a non-object.
if (a == null || b == null || typeof a !== 'object' || typeof b !=='object') {
return true;
}
return (
a.enableHighAccuracy === b.enableHighAccuracy &&
a.maximumAge === b.maximumAge &&
a.timeout === b.timeout
);
});

// pause geolocation updates
var paused = new ReactiveVar(false);

var onError = function (newError) {
error.set(newError);
checkDependents();
};

var onPosition = function (newLocation) {
location.set(newLocation);
error.set(null);
checkDependents();
};

var checkDependents = function() {
if (location.dep.hasDependents() || error.dep.hasDependents()) {
return;
}
watchingPosition.stop();
watchingPosition = false;
};

var startWatchingPosition = function () {
if (! watchingPosition && navigator.geolocation) {
navigator.geolocation.watchPosition(onPosition, onError, options);
watchingPosition = true;
if (watchingPosition === false && navigator.geolocation) {
watchingPosition = Tracker.autorun(function() {
if (paused.get()) { return; }
var watchId =
navigator.geolocation.watchPosition(onPosition, onError, options.get());
Tracker.onInvalidate(function() {
navigator.geolocation.clearWatch(watchId);
});
});
}
};

Expand All @@ -43,29 +72,37 @@ Geolocation = {
* that is currently preventing position updates.
*/
error: function () {
startWatchingPosition();
Tracker.nonreactive(startWatchingPosition);
return error.get();
},

/**
* @summary Get the current location
* @param {PositionOptions} options Optional geolocation options
* @param {Boolean} options.enableHighAccuracy
* @param {Number} options.maximumAge
* @param {Number} options.timeout
* @return {Position | null} The
* [position](https://developer.mozilla.org/en-US/docs/Web/API/Position)
* that is reported by the device, or null if no position is available.
*/
currentLocation: function () {
startWatchingPosition();
currentLocation: function (_options) {
if (_options != null) {
Geolocation.setOptions(_options);
}
Tracker.nonreactive(startWatchingPosition);
return location.get();
},

// simple version of location; just lat and lng

/**
* @summary Get the current latitude and longitude
* @return {Object | null} An object with `lat` and `lng` properties,
* or null if no position is available.
*/
latLng: function () {
var loc = Geolocation.currentLocation();
latLng: function (options) {
var loc = Geolocation.currentLocation(options);

if (loc) {
return {
Expand All @@ -75,5 +112,20 @@ Geolocation = {
}

return null;
},

/**
* @summary Set the PositionOptions used for geolocation.
*/
setOptions: function(_options) {
options.set(_options);
},

/**
* @summary Allow temporarily halting reactive updates to position.
*/
setPaused: function(_paused) {
paused.set(_paused);
}
};

};
4 changes: 2 additions & 2 deletions packages/mdg:geolocation/package.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package.describe({
name: "mdg:geolocation",
summary: "Provides reactive geolocation on desktop and mobile.",
version: "1.0.2",
version: "1.0.3",
git: "https://github.com/meteor/mobile-packages"
});

Expand All @@ -14,4 +14,4 @@ Package.on_use(function (api) {
api.versionsFrom("[email protected]");
api.add_files(["geolocation.js"], "client");
api.export("Geolocation", "client");
});
});

0 comments on commit 10a0d36

Please sign in to comment.