diff --git a/index.html b/index.html index 949624c..65bdec0 100644 --- a/index.html +++ b/index.html @@ -92,6 +92,7 @@ + diff --git a/js/control/RoutingOptions.js b/js/control/RoutingOptions.js index 7a85b5b..6030128 100644 --- a/js/control/RoutingOptions.js +++ b/js/control/RoutingOptions.js @@ -17,7 +17,16 @@ BR.RoutingOptions = BR.Control.extend({ alternative: L.DomUtil.get('alternative').value }; }, - + + setOptions: function(options) { + if (options.profile) { + L.DomUtil.get('profile').value = options.profile; + } + if (options.alternative) { + L.DomUtil.get('alternative').value = options.alternative; + } + }, + _getChangeHandler: function() { return L.bind(function(evt) { this.fire('update', {options: this.getOptions()}); diff --git a/js/index.js b/js/index.js index ee88a75..dfdccc5 100644 --- a/js/index.js +++ b/js/index.js @@ -6,6 +6,9 @@ (function() { + var map, + layersControl; + function initMap() { var osmAttribution = '© OpenStreetMap contributors'; @@ -50,7 +53,7 @@ + '(CC-BY-SA 3.0 DE)' }); - var map = new L.Map('map', { + map = new L.Map('map', { layers: [osm], center: new L.LatLng(50.99, 9.86), zoom: 6 @@ -60,7 +63,7 @@ + 'routing + map data © OpenStreetMap contributors ' + '(ODbL)'); - var layersControl = L.control.layers({ + layersControl = L.control.layers({ 'OpenStreetMap': osm, 'OpenStreetMap.de': osmde, 'OpenTopoMap': topo, @@ -71,13 +74,10 @@ 'Hiking (Waymarked Trails)': hiking }).addTo(map); - map.addControl(new L.Control.Permalink({text: 'Permalink', position: 'bottomright', layers: layersControl})); map.addControl(new BR.Search()); - - return map; } - function initApp(map) { + function initApp() { var router, routing, routesLayer, @@ -147,9 +147,19 @@ nogos.addTo(map); routing.addTo(map); + + map.addControl(new L.Control.Permalink({ + text: 'Permalink', + position: 'bottomright', + layers: layersControl, + routingOptions: routingOptions, + nogos: nogos, + router: router, + routing: routing + })); } - map = initMap(); - initApp(map); + initMap(); + initApp(); })(); diff --git a/js/plugin/NogoAreas.js b/js/plugin/NogoAreas.js index 66fad17..4570ab3 100644 --- a/js/plugin/NogoAreas.js +++ b/js/plugin/NogoAreas.js @@ -58,6 +58,16 @@ BR.NogoAreas = L.Control.Draw.extend({ }; }, + setOptions: function(options) { + var nogos = options.nogos; + if (nogos) { + this.drawnItems.clearLayers(); + for (var i = 0; i < nogos.length; i++) { + this.drawnItems.addLayer(nogos[i]); + } + } + }, + _fireUpdate: function () { this.fire('update', {options: this.getOptions()}); } diff --git a/js/plugin/Permalink.Routing.js b/js/plugin/Permalink.Routing.js new file mode 100644 index 0000000..8c6a356 --- /dev/null +++ b/js/plugin/Permalink.Routing.js @@ -0,0 +1,85 @@ +//#include "Permalink.js + +// patch to not encode URL (beside 'layer', better readable/hackable, Browser can handle) +L.Control.Permalink.include({ + _update_href: function() { + //var params = L.Util.getParamString(this._params); + var params = this.getParamString(this._params); + + var sep = '?'; + if (this.options.useAnchor) sep = '#'; + var url = this._url_base + sep + params.slice(1); + if (this._href) this._href.setAttribute('href', url); + if (this.options.useLocation) + location.replace('#' + params.slice(1)); + return url; + }, + + getParamString: function (obj, existingUrl, uppercase) { + var params = []; + for (var i in obj) { + // do encode layer (e.g. spaces) + if (i === 'layer') { + params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); + } else { + params.push(uppercase ? i.toUpperCase() : i + '=' + obj[i]); + } + } + return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); + } +}); + + +L.Control.Permalink.include({ + + initialize_routing: function() { + this.on('update', this._set_routing, this); + this.on('add', this._onadd_routing, this); + }, + + _onadd_routing: function(e) { + this.options.routingOptions.on('update', this._update_routing, this); + this.options.nogos.on('update', this._update_routing, this); + // waypoint add, move, delete (but last) + this.options.routing.on('routing:routeWaypointEnd', this._update_routing, this); + // delete last waypoint + this.options.routing.on('waypoint:click', function(evt) { + var r = evt.marker._routing; + if (!r.prevMarker && ! r.nextMarker) { + console.log('delete last'); + this._update_routing(evt); + } + }, this); + }, + + _update_routing: function(evt) { + var router = this.options.router, + routing = this.options.routing, + latLngs; + + if (evt && evt.options) { + router.setOptions(evt.options); + } + + latLngs = routing.getWaypoints(); + this._update(router.getUrlParams(latLngs)); + }, + + _set_routing: function(e) { + var router = this.options.router, + routing = this.options.routing, + routingOptions = this.options.routingOptions, + nogos = this.options.nogos; + + var opts = router.parseUrlParams(e.params); + router.setOptions(opts); + routingOptions.setOptions(opts); + nogos.setOptions(opts); + + if (opts.lonlats) { + routing.draw(false); + routing.clear(); + routing.setWaypoints(opts.lonlats); + } + } +}); diff --git a/js/plugin/Routing.js b/js/plugin/Routing.js index f35fd29..ab94d57 100644 --- a/js/plugin/Routing.js +++ b/js/plugin/Routing.js @@ -26,4 +26,47 @@ BR.Routing = L.Routing.extend({ return container; } + + ,_removeMarkerEvents: function(marker) { + marker.off('mouseover', this._fireWaypointEvent, this); + marker.off('mouseout' , this._fireWaypointEvent, this); + marker.off('dragstart', this._fireWaypointEvent, this); + marker.off('dragend' , this._fireWaypointEvent, this); + marker.off('drag' , this._fireWaypointEvent, this); + marker.off('click' , this._fireWaypointEvent, this); + } + + ,clear: function() { + var current = this._waypoints._first; + if (current === null) { return; } + this._removeMarkerEvents(current); + while (current._routing.nextMarker) { + var marker = current._routing.nextMarker; + this._removeMarkerEvents(marker); + current = marker; + }; + + this._waypoints._first = null; + this._waypoints._last = null; + this._waypoints.clearLayers(); + this._segments.clearLayers(); + } + + ,setWaypoints: function(latLngs) { + var $this = this; + var index = 0; + + var add = function() { + if (!latLngs || index >= latLngs.length) { return; } + + var prev = $this._waypoints._last; + + $this.addWaypoint(latLngs[index], prev, null, function(err, m) { + add(++index); + }); + }; + + add(); + } + }); diff --git a/js/router/BRouter.js b/js/router/BRouter.js index 0cae7a7..6d384f3 100644 --- a/js/router/BRouter.js +++ b/js/router/BRouter.js @@ -19,14 +19,38 @@ L.BRouter = L.Class.extend({ L.setOptions(this, options); }, - getUrl: function(latLngs, format) { - var urlParams = { + getUrlParams: function(latLngs, format) { + return { lonlats: this._getLonLatsString(latLngs), nogos: this._getNogosString(this.options.nogos), profile: this.options.profile, alternativeidx: this.options.alternative, format: format || this.options.format }; + }, + + parseUrlParams: function(params) { + var opts = {}; + if (params.lonlats) { + opts.lonlats = this._parseLonLats(params.lonlats); + } + if (params.nogos) { + opts.nogos = this._parseNogos(params.nogos); + } + if (params.alternativeidx) { + opts.alternative = params.alternativeidx; + } + if (params.profile) { + opts.profile = params.profile; + } + if (params.format) { + opts.format = params.format; + } + return opts; + }, + + getUrl: function(latLngs, format) { + var urlParams = this.getUrlParams(latLngs, format); var url = L.Util.template(L.BRouter.URL_TEMPLATE, urlParams); return url; }, @@ -74,7 +98,26 @@ L.BRouter = L.Class.extend({ } return s; }, - + + _parseLonLats: function(s) { + var groups, + numbers, + lonlats = []; + + if (!s) { + return lonlats; + } + + groups = s.split(L.BRouter.GROUP_SEPARATOR); + for (var i = 0; i < groups.length; i++) { + // lng,lat + numbers = groups[i].split(L.BRouter.NUMBER_SEPARATOR); + lonlats.push(L.latLng(numbers[1], numbers[0])); + } + + return lonlats; + }, + _getNogosString: function(nogos) { var s = ''; for (var i = 0, circle; i < nogos.length; i++) { @@ -89,6 +132,27 @@ L.BRouter = L.Class.extend({ return s; }, + _parseNogos: function(s) { + var groups, + numbers, + nogos = []; + + if (!s) { + return nogos; + } + + groups = s.split(L.BRouter.GROUP_SEPARATOR); + for (var i = 0; i < groups.length; i++) { + // lng,lat,radius + numbers = groups[i].split(L.BRouter.NUMBER_SEPARATOR); + // TODO refactor: pass simple obj, create circle in NogoAreas; use shapeOptions of instance + // [lat,lng],radius + nogos.push(L.circle([numbers[1], numbers[0]], numbers[2], L.Draw.Circle.prototype.options.shapeOptions)); + } + + return nogos; + }, + // formats L.LatLng object as lng,lat string _formatLatLng: function(latLng) { var s = '';