From a74f0fc1d4574c9fd04f7bd3d7b477e99977be1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 28 Nov 2017 12:32:46 +0100 Subject: [PATCH] show route in frontend --- src/c3nav/routing/api.py | 8 ++- src/c3nav/site/static/site/css/c3nav.css | 7 +++ src/c3nav/site/static/site/js/c3nav.js | 76 +++++++++++++++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/c3nav/routing/api.py b/src/c3nav/routing/api.py index b370daaf..0f85a444 100644 --- a/src/c3nav/routing/api.py +++ b/src/c3nav/routing/api.py @@ -23,4 +23,10 @@ class RoutingViewSet(ViewSet): destination=form.cleaned_data['destination'], permissions=AccessPermission.get_for_request(request)) - return Response(route.serialize(locations=visible_locations_for_request(request))) + return Response({ + 'request': { + 'origin': form.cleaned_data['origin'].pk, + 'destination': form.cleaned_data['destination'].pk, + }, + 'result': route.serialize(locations=visible_locations_for_request(request)), + }) diff --git a/src/c3nav/site/static/site/css/c3nav.css b/src/c3nav/site/static/site/css/c3nav.css index 8c5461a3..808da461 100644 --- a/src/c3nav/site/static/site/css/c3nav.css +++ b/src/c3nav/site/static/site/css/c3nav.css @@ -447,6 +447,13 @@ button .material-icons, .button .material-icons { #route-summary small { line-height: 1.1; } +#route-summary.loading { + /*noinspection CssUnknownTarget*/ + background: url('../../img/loader.gif') no-repeat 4px 4px; +} +#route-summary.loading > * { + display: none; +} main:not([data-view=route-result]) #route-summary { margin-bottom: -55px; pointer-events: none; diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index 9108dd95..8b9d9435 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -72,6 +72,9 @@ c3nav = { window.onpopstate = c3nav._onpopstate; }, + get_csrf_token: function() { + return document.cookie.match(new RegExp('c3nav_csrftoken=([^;]+)'))[1]; + }, state: {}, update_state: function(routing, replace, details) { @@ -114,11 +117,18 @@ c3nav = { c3nav._view = view; if (view === 'location' && state.details) { - this.load_location_details(state.destination); + c3nav.load_location_details(state.destination); } else { $('#location-details').removeAttr('data-id'); } + if (view === 'route-result') { + c3nav.load_route(state.origin, state.destination); + } else { + $('#route-summary').removeAttr('data-origin').removeAttr('data-destination'); + c3nav._clear_route_layers(); + } + $('main').attr('data-view', view).toggleClass('show-details', state.details); var $search = $('#search'); @@ -133,6 +143,12 @@ c3nav = { c3nav.update_map_locations(); }, + _clear_route_layers: function() { + console.log('clear route layers'); + for (var id in c3nav._routeLayers) { + c3nav._routeLayers[id].clearLayers(); + } + }, load_location_details: function (location) { var $location_details = $('#location-details'); @@ -176,6 +192,64 @@ c3nav = { $location_details.find('.details-body').html('').append(elem); $location_details.removeClass('loading').find('.editor').attr('href', data.editor_url); }, + load_route: function (origin, destination) { + var $route = $('#route-summary'); + if (parseInt($route.attr('data-origin')) !== origin.id || parseInt($route.attr('data-destination')) !== destination.id) { + c3nav._clear_route_layers(); + $route.addClass('loading').attr('data-origin', origin.id).attr('data-destination', destination.id); + $.post('/api/routing/route/', { + 'origin': origin.id, + 'destination': destination.id, + 'csrfmiddlewaretoken': c3nav.get_csrf_token() + }, c3nav._route_loaded, 'json'); + } + }, + _route_loaded: function(data) { + var $route = $('#route-summary'); + if (parseInt($route.attr('data-origin')) !== data.request.origin || parseInt($route.attr('data-destination')) !== data.request.destination) { + // loaded too late, information no longer needed + return; + } + var result = data.result, + last_primary_level = null, + level_collect = [], + next_level_collect = [], + in_intermediate_level = true, + item, coords; + for (var i=0; i < result.items.length; i++) { + item = result.items[i]; + coords = [item.coordinates[0], item.coordinates[1]]; + level_collect.push(coords); + if (item.level) { + if (last_primary_level) { + c3nav._add_line_to_level(last_primary_level, level_collect); + } + + if (in_intermediate_level) { + next_level_collect = next_level_collect.concat(level_collect); + } + + if (item.level.on_top_of) { + in_intermediate_level = true; + } else { + in_intermediate_level = false; + last_primary_level = item.level.id; + c3nav._add_line_to_level(last_primary_level, next_level_collect); + next_level_collect = []; + } + level_collect = level_collect.slice(-1); + } + } + if (last_primary_level && level_collect.length >= 2) { + c3nav._add_line_to_level(last_primary_level, level_collect); + } + $route.find('span').text(String(result.distance)+' m'); + $route.removeClass('loading'); + }, + _add_line_to_level: function(level, coords) { + if (coords.length < 2) return; + L.polyline(L.GeoJSON.coordsToLatLngs(coords)).addTo(c3nav._routeLayers[level]); + }, _equal_states: function (a, b) { if (a.routing !== b.routing || a.details !== b.details) return false; if ((a.origin && a.origin.id) !== (b.origin && b.origin.id)) return false;