89b4e8ce431a3c31d27ebf5c6c28fb42cad55ecd
[rails.git] / vendor / assets / leaflet / leaflet.locate.js
1 L.Control.Locate = L.Control.extend({
2     options: {
3         position: 'topleft',
4         drawCircle: true,
5         follow: false,  // follow with zoom and pan the user's location
6         // range circle
7         circleStyle: {
8                 color: '#136AEC',
9                 fillColor: '#136AEC',
10                 fillOpacity: 0.15,
11                 weight: 2,
12                 opacity: 0.5
13             },
14         // inner marker
15         markerStyle: {
16             color: '#136AEC',
17             fillColor: '#2A93EE',
18             fillOpacity: 0.7,
19             weight: 2,
20             opacity: 0.9,
21             radius: 4
22         },
23         metric: true,
24         debug: false,
25         onLocationError: function(err) {
26             alert(err.message);
27         },
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
31         locateOptions: {}
32     },
33
34     onAdd: function (map) {
35         var className = 'leaflet-control-locate',
36             classNames = className + ' leaflet-control-zoom leaflet-bar leaflet-control',
37             container = L.DomUtil.create('div', classNames);
38
39         var self = this;
40         this._layer = new L.LayerGroup();
41         this._layer.addTo(map);
42         this._event = undefined;
43         // nested extend so that the first can overwrite the second
44         // and the second can overwrite the third
45         this._locateOptions = L.extend(L.extend({
46             'setView': false // have to set this to false because we have to
47                              // do setView manually
48         }, this.options.locateOptions), {
49             'watch': true  // if you overwrite this, visualization cannot be updated
50         });
51
52         var link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
53         link.href = '#';
54         link.title = this.options.title;
55
56         var _log = function(data) {
57             if (self.options.debug) {
58                 console.log(data);
59             }
60         };
61
62         L.DomEvent
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)) {
67                     stopLocate();
68                 } else {
69                     if (self.options.setView) {
70                         self._locateOnNextLocationFound = true;
71                     }
72                     if(!self._active) {
73                         map.locate(self._locateOptions);
74                     }
75                     self._active = true;
76                     if (!self._event) {
77                         self._container.className = classNames + " requesting";
78                     } else {
79                         visualizeLocation();
80                     }
81                 }
82             })
83             .on(link, 'dblclick', L.DomEvent.stopPropagation);
84
85         var onLocationFound = function (e) {
86             _log('onLocationFound');
87
88             self._active = true;
89
90             if (self._event &&
91                 (self._event.latlng.lat != e.latlng.lat ||
92                  self._event.latlng.lng != e.latlng.lng)) {
93                 _log('location has changed');
94             }
95
96             self._event = e;
97
98             if (self.options.follow) {
99                 self._locateOnNextLocationFound = true;
100             }
101
102             visualizeLocation();
103         };
104
105         var visualizeLocation = function() {
106             _log('visualizeLocation,' + 'setView:' + self._locateOnNextLocationFound);
107
108             var radius = self._event.accuracy / 2;
109
110             if (self._locateOnNextLocationFound) {
111                 map.fitBounds(self._event.bounds);
112                 self._locateOnNextLocationFound = false;
113             }
114
115             self._layer.clearLayers();
116
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)
120                     .addTo(self._layer);
121             }
122
123             var distance, unit;
124             if (self.options.metric) {
125                 distance = radius.toFixed(0);
126                 unit = "meters";
127             } else {
128                 distance = (radius * 3.2808399).toFixed(0);
129                 unit = "feet";
130             }
131
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])
136                 .addTo(self._layer);
137
138             if (!self._container)
139                 return;
140             self._container.className = classNames + " active";
141         };
142
143         var resetVariables = function() {
144             self._active = false;
145             self._locateOnNextLocationFound = true;
146         };
147
148         resetVariables();
149
150         var stopLocate = function() {
151             _log('stopLocate');
152             map.stopLocate();
153
154             self._container.className = classNames;
155             resetVariables();
156
157             self._layer.clearLayers();
158         };
159
160
161         var onLocationError = function (err) {
162             _log('onLocationError');
163
164             // ignore timeout error if the location is watched
165             if (err.code==3 && this._locateOptions.watch) {
166                 return;
167             }
168
169             stopLocate();
170             self.options.onLocationError(err);
171         };
172
173         // event hooks
174         map.on('locationfound', onLocationFound, self);
175         map.on('locationerror', onLocationError, self);
176
177         return container;
178     }
179 });
180
181 L.Map.addInitHook(function () {
182     if (this.options.locateControl) {
183         this.locateControl = L.control.locate();
184         this.addControl(this.locateControl);
185     }
186 });
187
188 L.control.locate = function (options) {
189     return new L.Control.Locate(options);
190 };