Skip to content

Commit

Permalink
request location via GPS, interactive map, and/or manual lat-long entry
Browse files Browse the repository at this point in the history
  • Loading branch information
sheppard committed Jun 4, 2013
1 parent eaab813 commit 1015862
Showing 1 changed file with 159 additions and 0 deletions.
159 changes: 159 additions & 0 deletions js/locate.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,165 @@ locate.locate = function(success, error, high, watch) {
}
}

// Interactive GPS & map-based locator tool
// map should be an L.map; fields should be an object of jQuery-wrapped <input>s
locate.Locator = function(map, fields) {
var self = this;

if (!fields) fields = {};

var _mode, _marker, _circle, _locate;

// Mode switching functions (define fields.toggle for default usage)
self.setMode = function(mode) {
if (!mode || !self[mode + 'Start'])
return;
self.stop();
_mode = mode;
self.start();
};

self.start = function() {
if (_mode)
self[_mode + 'Start']();
};

self.stop = function() {
if (_mode)
self[_mode + 'Stop']();
};

// GPS mode
self.gpsStart = function() {
locate.init(map);
_locate = locate.locate(function(evt) {
self.update(evt.latlng, evt.accuracy);
}, function(evt) {
self.onerror(evt);
}, true, true);
};

self.gpsStop = function() {
if (_locate)
_locate.stop();
};

// Interactive mode
self.interactiveStart = function() {
L.DomUtil.addClass(map._container, 'interactive');
};

self.interactiveStop = function() {
L.DomUtil.removeClass(map._container, 'interactive');
};

// Manual mode
self.manualStart = function() {
if (!fields.latitude || !fields.longitude)
return;
fields.latitude.attr('readonly', false);
fields.longitude.attr('readonly', false);
};

self.manualStop = function() {
fields.latitude.attr('readonly', true);
fields.longitude.attr('readonly', true);
};

// Default Circle & Marker generators, override to customize
self.makeCircle = function() {
return L.circle([0,0],1,{'weight': 1});
};

self.makeMarker = function() {
return L.marker([0,0]);
};

// Display and save updates to location
self.update = function(loc, accuracy) {
if (!_marker)
_marker = self.makeMarker().addTo(map);
if (!_circle)
_circle = self.makeCircle().addTo(map);
// Update display
_marker.setLatLng(loc);
_circle.setLatLng(loc).setRadius(accuracy);

// Save to fields
if (fields) {
if (fields.latitude) fields.latitude.val(loc.lat);
if (fields.longitude) fields.longitude.val(loc.lng);
if (fields.accuracy) fields.accuracy.val(accuracy);
if (fields.mode) fields.mode.val(_mode);
}

// User-defined callback (FIXME: make event?)
if (self.onupdate)
self.onupdate(loc, accuracy)
};

self.onerror = function(evt) {
if (window.console)
console.log("Error retreiving coordinates!");
};

// Respond to map clicks in interactive mode
function _clickMap(evt) {
if (_mode != 'interactive')
return;
// Estimate accuracy based on viewport information
// (higher zoom = better accuracy)
var ll = map.getBounds();
var px = map.getPixelBounds();
var distance = ll.getNorthWest().distanceTo(ll.getSouthWest());
var height = px.getSize().y;

// Assume accuracy is equivalent to the real-world length represented
// by 2 pixels
var accuracy = L.Util.formatNum(distance / height * 2, 3);

self.update(evt.latlng, accuracy);
}

function _updateManual() {
if (_mode != 'manual')
return;
self.update(L.latLng(
fields.latitude.val(),
fields.longitude.val()
), null);
}

function _getVal($input) {
if ($input.is('select'))
return $input.val();
else if ($input.is('input[type=radio]'))
return $input.filter(':checked').val();
return null;
}

// Leaflet events
map.on('click', _clickMap);

// jQuery Events
if (fields.toggle) {
fields.toggle.on('click', function() {
self.setMode(_getVal(fields.toggle));
});
self.setMode(_getVal(fields.toggle));
}

if (fields.latitude && fields.longitude) {
fields.latitude.on('change', _updateManual);
fields.longitude.on('change', _updateManual);
}
}

// Leaflet-style generator function
locate.locator = function(map, fields) {
return new locate.Locator(map, fields);
}

return locate;

});

0 comments on commit 1015862

Please sign in to comment.