X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/b9a19ab23a8dc63bc7c7f867e2ece6924319f0f2..f2bf38606e281290fee8273e247afc54f08a0a47:/vendor/assets/leaflet/leaflet.locate.js diff --git a/vendor/assets/leaflet/leaflet.locate.js b/vendor/assets/leaflet/leaflet.locate.js index be5c7fc01..7e835c877 100644 --- a/vendor/assets/leaflet/leaflet.locate.js +++ b/vendor/assets/leaflet/leaflet.locate.js @@ -1,16 +1,23 @@ +/* +Copyright (c) 2013 Dominik Moritz + +This file is part of the leaflet locate control. It is licensed under the MIT license. +You can find the project at: https://github.com/domoritz/leaflet-locatecontrol +*/ L.Control.Locate = L.Control.extend({ options: { position: 'topleft', drawCircle: true, follow: false, // follow with zoom and pan the user's location + stopFollowingOnDrag: false, // if follow is true, stop following when map is dragged (deprecated) // range circle circleStyle: { - color: '#136AEC', - fillColor: '#136AEC', - fillOpacity: 0.15, - weight: 2, - opacity: 0.5 - }, + color: '#136AEC', + fillColor: '#136AEC', + fillOpacity: 0.15, + weight: 2, + opacity: 0.5 + }, // inner marker markerStyle: { color: '#136AEC', @@ -18,106 +25,176 @@ L.Control.Locate = L.Control.extend({ fillOpacity: 0.7, weight: 2, opacity: 0.9, - radius: 4 + radius: 5 + }, + // changes to range circle and inner marker while following + // it is only necessary to provide the things that should change + followCircleStyle: {}, + followMarkerStyle: { + //color: '#FFA500', + //fillColor: '#FFB000' }, + circlePadding: [0, 0], metric: true, - debug: false, onLocationError: function(err) { + // this event is called in case of any location error + // that is not a time out error. alert(err.message); }, - title: "Show me where I am", - popupText: ["You are within ", " from this point"], + onLocationOutsideMapBounds: function(context) { + // this event is repeatedly called when the location changes + alert(context.options.strings.outsideMapBoundsMsg); + }, setView: true, // automatically sets the map view to the user's location + strings: { + title: "Show me where I am", + popup: "You are within {distance} {unit} from this point", + outsideMapBoundsMsg: "You seem located outside the boundaries of the map" + }, locateOptions: {} }, onAdd: function (map) { - var className = 'control-locate', - container = L.DomUtil.create('div', className); + var container = L.DomUtil.create('div', 'control-locate'); var self = this; this._layer = new L.LayerGroup(); this._layer.addTo(map); this._event = undefined; - // nested extend so that the first can overwrite the second - // and the second can overwrite the third - this._locateOptions = L.extend(L.extend({ - 'setView': false // have to set this to false because we have to - // do setView manually - }, this.options.locateOptions), { - 'watch': true // if you overwrite this, visualization cannot be updated + + this._locateOptions = { + watch: true // if you overwrite this, visualization cannot be updated + }; + L.extend(this._locateOptions, this.options.locateOptions); + L.extend(this._locateOptions, { + setView: false // have to set this to false because we have to + // do setView manually }); + // extend the follow marker style and circle from the normal style + var tmp = {}; + L.extend(tmp, this.options.markerStyle, this.options.followMarkerStyle); + this.options.followMarkerStyle = tmp; + tmp = {}; + L.extend(tmp, this.options.circleStyle, this.options.followCircleStyle); + this.options.followCircleStyle = tmp; + var link = L.DomUtil.create('a', 'control-button', container); link.innerHTML = ""; link.href = '#'; - link.title = this.options.title; - - var _log = function(data) { - if (self.options.debug) { - console.log(data); - } - }; + link.title = this.options.strings.title; L.DomEvent .on(link, 'click', L.DomEvent.stopPropagation) .on(link, 'click', L.DomEvent.preventDefault) .on(link, 'click', function() { - if (self._active && (map.getBounds().contains(self._event.latlng) || !self.options.setView)) { + if (self._active && (map.getBounds().contains(self._event.latlng) || !self.options.setView || + isOutsideMapBounds())) { stopLocate(); } else { - if (self.options.setView) { - self._locateOnNextLocationFound = true; - } - if(!self._active) { - map.locate(self._locateOptions); - } - self._active = true; - if (!self._event) { - self._container.className = className + " requesting"; - } else { - visualizeLocation(); - } + locate(); } }) .on(link, 'dblclick', L.DomEvent.stopPropagation); - var onLocationFound = function (e) { - _log('onLocationFound'); - + var locate = function () { + if (self.options.setView) { + self._locateOnNextLocationFound = true; + } + if(!self._active) { + map.locate(self._locateOptions); + } self._active = true; + if (self.options.follow) { + startFollowing(); + } + if (!self._event) { + L.DomUtil.addClass(self._container, "requesting"); + L.DomUtil.removeClass(self._container, "active"); + L.DomUtil.removeClass(self._container, "following"); + } else { + visualizeLocation(); + } + }; + var onLocationFound = function (e) { + // no need to do anything if the location has not changed if (self._event && - (self._event.latlng.lat != e.latlng.lat || - self._event.latlng.lng != e.latlng.lng)) { - _log('location has changed'); + (self._event.latlng.lat === e.latlng.lat && + self._event.latlng.lng === e.latlng.lng && + self._event.accuracy === e.accuracy)) { + return; + } + + if (!self._active) { + return; } self._event = e; - if (self.options.follow) { + if (self.options.follow && self._following) { self._locateOnNextLocationFound = true; } visualizeLocation(); }; - var visualizeLocation = function() { - _log('visualizeLocation,' + 'setView:' + self._locateOnNextLocationFound); + var startFollowing = function() { + map.fire('startfollowing'); + self._following = true; + if (self.options.stopFollowingOnDrag) { + map.on('dragstart', stopFollowing); + } + }; + + var stopFollowing = function() { + map.fire('stopfollowing'); + self._following = false; + if (self.options.stopFollowingOnDrag) { + map.off('dragstart', stopFollowing); + } + visualizeLocation(); + }; + + var isOutsideMapBounds = function () { + if (self._event === undefined) + return false; + return map.options.maxBounds && + !map.options.maxBounds.contains(self._event.latlng); + }; - var radius = self._event.accuracy / 2; + var visualizeLocation = function() { + if (self._event.accuracy === undefined) + self._event.accuracy = 0; + var radius = self._event.accuracy; if (self._locateOnNextLocationFound) { - map.fitBounds(self._event.bounds); + if (isOutsideMapBounds()) { + self.options.onLocationOutsideMapBounds(self); + } else { + map.fitBounds(self._event.bounds, { padding: self.options.circlePadding }); + } self._locateOnNextLocationFound = false; } - self._layer.clearLayers(); - // circle with the radius of the location's accuracy + var style, o; if (self.options.drawCircle) { - L.circle(self._event.latlng, radius, self.options.circleStyle) - .addTo(self._layer); + if (self._following) { + style = self.options.followCircleStyle; + } else { + style = self.options.circleStyle; + } + + if (!self._circle) { + self._circle = L.circle(self._event.latlng, radius, style) + .addTo(self._layer); + } else { + self._circle.setLatLng(self._event.latlng).setRadius(radius); + for (o in style) { + self._circle.options[o] = style[o]; + } + } } var distance, unit; @@ -130,39 +207,65 @@ L.Control.Locate = L.Control.extend({ } // small inner marker - var t = self.options.popupText; - L.circleMarker(self._event.latlng, self.options.markerStyle) - .bindPopup(t[0] + distance + " " + unit + t[1]) - .addTo(self._layer); + var mStyle; + if (self._following) { + mStyle = self.options.followMarkerStyle; + } else { + mStyle = self.options.markerStyle; + } + + var t = self.options.strings.popup; + if (!self._circleMarker) { + self._circleMarker = L.circleMarker(self._event.latlng, mStyle) + .bindPopup(L.Util.template(t, {distance: distance, unit: unit})) + .addTo(self._layer); + } else { + self._circleMarker.setLatLng(self._event.latlng) + .bindPopup(L.Util.template(t, {distance: distance, unit: unit})) + ._popup.setLatLng(self._event.latlng); + for (o in mStyle) { + self._circleMarker.options[o] = mStyle[o]; + } + } if (!self._container) return; - self._container.className = className + " active"; + if (self._following) { + L.DomUtil.removeClass(self._container, "requesting"); + L.DomUtil.addClass(self._container, "active"); + L.DomUtil.addClass(self._container, "following"); + } else { + L.DomUtil.removeClass(self._container, "requesting"); + L.DomUtil.addClass(self._container, "active"); + L.DomUtil.removeClass(self._container, "following"); + } }; var resetVariables = function() { self._active = false; - self._locateOnNextLocationFound = true; + self._locateOnNextLocationFound = self.options.setView; + self._following = false; }; resetVariables(); var stopLocate = function() { - _log('stopLocate'); map.stopLocate(); + map.off('dragstart', stopFollowing); - self._container.className = className; + L.DomUtil.removeClass(self._container, "requesting"); + L.DomUtil.removeClass(self._container, "active"); + L.DomUtil.removeClass(self._container, "following"); resetVariables(); self._layer.clearLayers(); + self._circleMarker = undefined; + self._circle = undefined; }; - var onLocationError = function (err) { - _log('onLocationError'); - - // ignore timeout error if the location is watched - if (err.code==3 && this._locateOptions.watch) { + // ignore time out error if the location is watched + if (err.code == 3 && this._locateOptions.watch) { return; } @@ -174,6 +277,11 @@ L.Control.Locate = L.Control.extend({ map.on('locationfound', onLocationFound, self); map.on('locationerror', onLocationError, self); + // make locate functions available to outside world + this.locate = locate; + this.stopLocate = stopLocate; + this.stopFollowing = stopFollowing; + return container; } });