1 L.Control.Locate = L.Control.extend({
5 follow: false, // follow with zoom and pan the user's location
25 onLocationError: function(err) {
28 title: "Show me where I am",
29 popupText: ["You are within ", " from this point"],
30 setView: true, // automatically sets the map view to the user's location
34 onAdd: function (map) {
35 var className = 'control-locate',
36 container = L.DomUtil.create('div', className);
39 this._layer = new L.LayerGroup();
40 this._layer.addTo(map);
41 this._event = undefined;
42 // nested extend so that the first can overwrite the second
43 // and the second can overwrite the third
44 this._locateOptions = L.extend(L.extend({
45 'setView': false // have to set this to false because we have to
46 // do setView manually
47 }, this.options.locateOptions), {
48 'watch': true // if you overwrite this, visualization cannot be updated
51 var link = L.DomUtil.create('a', 'control-button', container);
52 link.innerHTML = "<span class='icon geolocate'></span>";
54 link.title = this.options.title;
56 var _log = function(data) {
57 if (self.options.debug) {
63 .on(link, 'click', L.DomEvent.stopPropagation)
64 .on(link, 'click', L.DomEvent.preventDefault)
65 .on(link, 'click', function() {
66 if (self._active && (map.getBounds().contains(self._event.latlng) || !self.options.setView)) {
69 if (self.options.setView) {
70 self._locateOnNextLocationFound = true;
73 map.locate(self._locateOptions);
77 self._container.className = className + " requesting";
83 .on(link, 'dblclick', L.DomEvent.stopPropagation);
85 var onLocationFound = function (e) {
86 _log('onLocationFound');
91 (self._event.latlng.lat != e.latlng.lat ||
92 self._event.latlng.lng != e.latlng.lng)) {
93 _log('location has changed');
98 if (self.options.follow) {
99 self._locateOnNextLocationFound = true;
105 var visualizeLocation = function() {
106 _log('visualizeLocation,' + 'setView:' + self._locateOnNextLocationFound);
108 var radius = self._event.accuracy / 2;
110 if (self._locateOnNextLocationFound) {
111 map.fitBounds(self._event.bounds);
112 self._locateOnNextLocationFound = false;
115 self._layer.clearLayers();
117 // circle with the radius of the location's accuracy
118 if (self.options.drawCircle) {
119 L.circle(self._event.latlng, radius, self.options.circleStyle)
124 if (self.options.metric) {
125 distance = radius.toFixed(0);
128 distance = (radius * 3.2808399).toFixed(0);
132 // small inner marker
133 var t = self.options.popupText;
134 L.circleMarker(self._event.latlng, self.options.markerStyle)
135 .bindPopup(t[0] + distance + " " + unit + t[1])
138 if (!self._container)
140 self._container.className = className + " active";
143 var resetVariables = function() {
144 self._active = false;
145 self._locateOnNextLocationFound = true;
150 var stopLocate = function() {
154 self._container.className = className;
157 self._layer.clearLayers();
161 var onLocationError = function (err) {
162 _log('onLocationError');
164 // ignore timeout error if the location is watched
165 if (err.code==3 && this._locateOptions.watch) {
170 self.options.onLocationError(err);
174 map.on('locationfound', onLocationFound, self);
175 map.on('locationerror', onLocationError, self);
181 L.Map.addInitHook(function () {
182 if (this.options.locateControl) {
183 this.locateControl = L.control.locate();
184 this.addControl(this.locateControl);
188 L.control.locate = function (options) {
189 return new L.Control.Locate(options);