PageSourceSearch

https://www.grenoble.fr/include/js/leaflet/geolet/geolet.js

js grenoble.fr collected 2026-09-24 17:17:20 UTC 11,727 bytes, 318 lines download raw bytes

1/*
2GEOLET version 20.12.31
3Copyright (c) 2020 Ruben Holthuijsen; available under the MIT license
4https://github.com/rhlt/leaflet-geolet/
5*/
6
7(function () {
8
9    var _consolePrefix = '[GEOLET] ';
10    var L = window.L;
11
12    if (!L || !L.map) {
13        //Was Leaflet loaded correctly?
14        console.error(_consolePrefix + 'Missing Leaflet');
15        return;
16    }
17
18    var _merge = function (object1, object2) {
19        //Merge all properties from object 2 into object 1, recursively for plain objects
20
21        if (typeof object2 != 'object' || object2 === null)
22            return object1;
23        if (typeof object1 != 'object' || object1 === null)
24            object1 = {};
25
26        for (key in object2) if (({}).hasOwnProperty.call(object2, key)) {
27            if (typeof object2[key] == 'object' && object2[key] !== null && Object.getPrototypeOf(object2[key]) == Object.getPrototypeOf({})) {
28                //Plain object: merge the next level
29                object1[key] = _merge(object1[key], object2[key]);
30            } else {
31                //Anything else (including typed objects): just assign it
32                object1[key] = object2[key];
33            }
34        }
35
36        return object1;
37    };
38
39    var _defaultMarker = function (controlOptions) {
40        //Generate a default marker
41        return L.marker(null, {
42            icon: L.divIcon({
43                html: '<svg width="20" height="20" viewport="0 0 20 20"><circle cx="10" cy="10" r="10" style="fill:white"/><circle cx="10" cy="10" r="7" style="fill:none;stroke:currentColor;stroke-width:2px"/><circle cx="10" cy="10" r="4" style="fill:currentColor"/></svg>',
44                iconAnchor: [10, 10],
45                className: ''
46            }),
47            attribution: '<a href="https://github.com/rhlt/leaflet-geolet" target="_blank">Geolet</a>',
48            zIndexOffset: 1000
49        });
50    };
51
52
53    L.Geolet = L.Control.extend({
54
55        options: {
56            title: 'Find current location',
57            className: null,
58            activeClassName: null,
59            style: { display: 'flex', color: '' },
60            activeStyle: { display: 'flex', color: '#E00' },
61            html: '<svg width="16" height="16" viewport="0 0 16 16" style="margin:auto auto"><circle cx="8" cy="8" r="7" style="fill:none;stroke:currentColor;stroke-width:2px"/><circle cx="8" cy="8" r="4" style="fill:currentColor"/></svg>',
62            geoOptions: { enableHighAccuracy: true, maximumAge: 30000, timeout: 27000 },
63            marker: null,
64            popup: null,
65            popupContent: null,
66            updatePopupWhenOpen: true,
67            autoPan: true,
68            minZoom: 9
69        },
70
71        _a: null,
72        _map: null,
73        _watchId: null,
74        _latLng: null,
75        _popupContent: null,
76        _first: false,
77
78        marker: null,
79        popup: null,
80
81        initialize: function (options) {
82            //Set control options
83            if (typeof options == 'object' && options !== null)
84                L.setOptions(this, options);
85        },
86
87        isActive: function () {
88            //Is the control active (are we displaying the current location, or trying to obtain it)?
89            return this._watchId ? true : false;
90        },
91
92        getLatLng: function () {
93            //Returns the coordinates of the location currently displayed on the map (if any) -- might still be null if isActive()
94            return this.isActive() ? this._latLng : null;
95        },
96
97        updatePopup: function () {
98            //Update the popup with new content
99            var popupContent;
100            if (!this._popup)
101                return;
102            if (typeof this.options.popupContent == 'undefined' || this.options.popupContent === null) {
103                popupContent = '<b>' + L.Geolet.formatLatLng(this.getLatLng()) + '</b>';
104            } else if (typeof this.options.popupContent == 'function') {
105                popupContent = this.options.popupContent.call(this, this.getLatLng());
106            } else if (this.options.popupContent) {
107                popupContent = this.options.popupContent;
108            }
109            if (popupContent !== null)
110                this._popup.setContent(popupContent);
111        },
112
113        activate: function () {
114            //Activate the current location display
115
116            if (!L.Geolet.browserSupport)
117                return;
118
119            this.styleAnchor(true);
120
121            var control = this;
122
123            var geoSuccessCallback = function (data) {
124                var first = !!control._first;
125                control._latLng = L.latLng(data.coords.latitude, data.coords.longitude, data.coords.altitude);
126                control._popupContent = control.options.popupContent;
127                if (control._popup) {
128                    if (control._popup.isOpen() && control.options.updatePopupWhenOpen)
129                        control.updatePopup();
130                }
131                if (control._marker) {
132                    control._marker.setLatLng(control._latLng);
133                    control._marker.addTo(control._map);
134                }
135                if (control._first) {
136                    control._first = false;
137                    if (control.options.autoPan)
138                        control._map.setView(control._latLng, control.options.minZoom ? Math.max(control._map.getZoom(), control.options.minZoom) : control._map.getZoom());
139                }
140                control._map.fire('geolet_success', {
141                    control: control,
142                    first: first,
143                    marker: control._marker,
144                    latlng: control._latLng, //"latlng" all-lowercase for consistency with Leaflet's MouseEvent
145                    raw: data
146                });
147            };
148
149            var geoErrorCallback = function (data) {
150                control.deactivate();
151                console.warn(_consolePrefix + data.message);
152                control._map.fire('geolet_error', {
153                    control: control,
154                    raw: data
155                });
156            };
157
158            this._first = true;
159            this._watchId = navigator.geolocation.watchPosition(geoSuccessCallback, geoErrorCallback, this.options.geoOptions);
160        },
161
162        deactivate: function () {
163            //Deactivate current location display
164
165            this.styleAnchor(false);
166
167            if (this.isActive()) {
168                navigator.geolocation.clearWatch(this._watchId);
169                this._watchId = null;
170            }
171
172            this._latLng = null;
173
174            if (this._marker)
175                this._marker.remove();
176            if (this._popup)
177                this._popup.remove();
178        },
179
180        styleAnchor: function (active) {
181            //Apply CSS classes and styles to the button's <a> element
182
183            var className = [];
184            if (!this._a)
185                return;
186            if (this.options.className)
187                className.push(this.options.className);
188            if (active && this.options.activeClassName)
189                className.push(this.options.activeClassName);
190            if (className.length) {
191                this._a.className = className.join(' ');
192            } else {
193                this._a.className = '';
194            }
195            if (active && this.options.activeStyle)
196                _merge(this._a.style, this.options.activeStyle);
197            if (!active && this.options.style)
198                _merge(this._a.style, this.options.style);
199        },
200
201        onAdd: function (map) {
202            //Initialize everything when the control is added
203
204            var control = this;
205            var el = L.DomUtil.create('div');
206            this._map = map;
207
208            if (!L.Geolet.browserSupport) {
209                console.warn(_consolePrefix + 'Browser does not support Geolocation');
210                el.style.display = 'none';
211                return el;
212            }
213
214            if (this._marker)
215                this._marker.remove();
216            if (typeof this.options.marker == 'function') {
217                this._marker = this.options.marker.call(this, map);
218            } else if (this.options.marker) {
219                this._marker = this.options.marker;
220            } else if (typeof this.options.marker == 'undefined' || this.options.marker === null) {
221                this._marker = _defaultMarker();
222            } else {
223                this._marker = null;
224            }
225
226            if (this._popup)
227                this._popup.remove();
228            if (typeof this.options.popup == 'function') {
229                this._popup = this.options.popup.call(this, map);
230            } else if (this.options.popup) {
231                this._popup = this.options.popup;
232            } else if (typeof this.options.popup == 'undefined' || this.options.popup === null) {
233                this._popup = L.popup({ autoPan: this.options.autoPan });
234            } else {
235                this._popup = null;
236            }
237
238            if (this._marker && this._popup) {
239                this._marker.bindPopup(this._popup);
240                this._marker.on('popupopen', function () { control.updatePopup(); });
241            }
242
243            el.className = 'leaflet-bar leaflet-control';
244
245            this._a = document.createElement('a');
246            this._a.setAttribute('href', '#');
247            if (this.options.title)
248                this._a.setAttribute('title', this.options.title);
249
250            this.styleAnchor();
251
252            this._a.addEventListener('click', function (event) {
253                if (!control.isActive()) {
254                    //Currently inactive
255                    control.activate();
256                } else {
257                    //Currently active
258                    control.deactivate();
259                }
260                event.preventDefault();
261                event.stopPropagation();
262            });
263
264            this._a.addEventListener('dblclick', function (event) {
265                //Ignore double clicks
266                event.stopPropagation();
267            });
268
269            if (this.options.html)
270                this._a.innerHTML = this.options.html;
271            el.appendChild(this._a);
272
273            return el;
274        },
275
276        onRemove: function (map) {
277            //Deinitialize everything when the control is removed
278            this.deactivate();
279            this._a = null;
280            this._map = null;
281            this._popup = null;
282            this._marker = null;
283        }
284    });
285
286
287    //Browser support test
288    L.Geolet.browserSupport = !!(navigator && navigator.geolocation && navigator.geolocation.watchPosition);
289
290    //Format coordinates (for use in the default pop up)
291    L.Geolet.formatSymbols = {};
292    L.Geolet.formatLatLng = function (latLng, l, a) {
293
294        latLng = L.latLng(latLng, l, a);
295        if (!latLng)
296            return;
297
298        var result = [];
299        var symbols = _merge({ deg: '&deg;', min: '&#8217;', sec: '&#8221;', N: 'N', E: 'E', S: 'S', W: 'W', space: ' ', comma: ', ' }, L.Geolet.formatSymbols);
300
301        ['lat', 'lng'].forEach(function (key) {
302            var dir = (key == 'lat' ? (latLng[key] < 0 ? symbols.S : symbols.N) : (latLng[key] < 0 ? symbols.W : symbols.E));
303            var val = Math.round(Math.abs(latLng[key]) * 3600) / 3600;
304            var deg = Math.floor(val)             + symbols.deg;
305            var min = Math.floor(val *   60) % 60 + symbols.min;
306            var sec = Math.floor(val * 3600) % 60 + symbols.sec;
307            result.push([deg, min, sec, dir].join(symbols.space));
308        });
309
310        return result.join(symbols.comma);
311    };
312
313    //Factory function
314    L.geolet = function (options) {
315        return new L.Geolet(options);
316    };
317
318})()

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.