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                         L.DomUtil.addClass(self._container, "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)
 
 141             L.DomUtil.removeClass(self._container, "requesting");
 
 142             L.DomUtil.addClass(self._container, "active");
 
 145         var resetVariables = function() {
 
 146             self._active = false;
 
 147             self._locateOnNextLocationFound = true;
 
 152         var stopLocate = function() {
 
 156             L.DomUtil.removeClass(self._container, "requesting");
 
 157             L.DomUtil.removeClass(self._container, "active");
 
 161             self._layer.clearLayers();
 
 165         var onLocationError = function (err) {
 
 166             _log('onLocationError');
 
 168             // ignore timeout error if the location is watched
 
 169             if (err.code==3 && this._locateOptions.watch) {
 
 174             self.options.onLocationError(err);
 
 178         map.on('locationfound', onLocationFound, self);
 
 179         map.on('locationerror', onLocationError, self);
 
 185 L.Map.addInitHook(function () {
 
 186     if (this.options.locateControl) {
 
 187         this.locateControl = L.control.locate();
 
 188         this.addControl(this.locateControl);
 
 192 L.control.locate = function (options) {
 
 193     return new L.Control.Locate(options);