make c3nav embeddable using iframes
This commit is contained in:
parent
e768a6176c
commit
276eee5adf
5 changed files with 167 additions and 118 deletions
|
@ -96,6 +96,9 @@ main.map {
|
||||||
}
|
}
|
||||||
|
|
||||||
#search {
|
#search {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
#sidebar #search {
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
min-height: 54px;
|
min-height: 54px;
|
||||||
min-width: 54px;
|
min-width: 54px;
|
||||||
|
@ -103,7 +106,7 @@ main.map {
|
||||||
transition: width 150ms;
|
transition: width 150ms;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
#search.loading {
|
#sidebar #search.loading {
|
||||||
/*noinspection CssUnknownTarget*/
|
/*noinspection CssUnknownTarget*/
|
||||||
background: url('../../img/loader.gif') no-repeat 4px 3px;
|
background: url('../../img/loader.gif') no-repeat 4px 3px;
|
||||||
width: 5%;
|
width: 5%;
|
||||||
|
@ -116,6 +119,26 @@ main.map {
|
||||||
background: url('../../img/loader.gif');
|
background: url('../../img/loader.gif');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#embed-logo {
|
||||||
|
font-size: 3rem;
|
||||||
|
line-height: 100%;
|
||||||
|
font-weight: 300;
|
||||||
|
z-index: 2;
|
||||||
|
position: absolute;
|
||||||
|
color: #606c76;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
opacity: 0.4;
|
||||||
|
letter-spacing: -.1rem;
|
||||||
|
}
|
||||||
|
#embed-logo:hover {
|
||||||
|
opacity: 1;
|
||||||
|
text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.3),
|
||||||
|
1px -1px 1px rgba(255, 255, 255, 0.3),
|
||||||
|
-1px 1px 1px rgba(255, 255, 255, 0.3),
|
||||||
|
-1px -1px 1px rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
main:not([data-view^=route]) #origin-input,
|
main:not([data-view^=route]) #origin-input,
|
||||||
#search.loading #destination-input {
|
#search.loading #destination-input {
|
||||||
margin-bottom: -55px;
|
margin-bottom: -55px;
|
||||||
|
@ -475,13 +498,13 @@ main:not([data-view=route-result]) #route-summary {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media not all and (min-height: 700px) and (min-width: 1100px) {
|
@media not all and (min-height: 700px) and (min-width: 1100px) {
|
||||||
main[data-view=route-result] #search:not(.focused) .locationinput {
|
main[data-view=route-result] #sidebar #search:not(.focused) .locationinput {
|
||||||
margin-bottom: -21px;
|
margin-bottom: -21px;
|
||||||
}
|
}
|
||||||
main[data-view=route-result] #search:not(.focused) .locationinput input {
|
main[data-view=route-result] #sidebar #search:not(.focused) .locationinput input {
|
||||||
padding-bottom: 28px;
|
padding-bottom: 28px;
|
||||||
}
|
}
|
||||||
main[data-view=route-result] #search:not(.focused) .locationinput small {
|
main[data-view=route-result] #sidebar #search:not(.focused) .locationinput small {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
|
@ -489,16 +512,16 @@ main:not([data-view=route-result]) #route-summary {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
main[data-view=route-result] #search:not(.focused) .locationinput .icon {
|
main[data-view=route-result] #sidebar #search:not(.focused) .locationinput .icon {
|
||||||
transform: scale(0.6);
|
transform: scale(0.6);
|
||||||
top: -1px;
|
top: -1px;
|
||||||
}
|
}
|
||||||
main[data-view=route-result] #search:not(.focused) .locationinput button {
|
main[data-view=route-result] #sidebar #search:not(.focused) .locationinput button {
|
||||||
transform: scale(0.6);
|
transform: scale(0.6);
|
||||||
top: -5px;
|
top: -5px;
|
||||||
right: -5px;
|
right: -5px;
|
||||||
}
|
}
|
||||||
main[data-view=route-result] #search:not(.focused) #route-dots {
|
main[data-view=route-result] #sidebar #search:not(.focused) #route-dots {
|
||||||
transform: scale(0.7);
|
transform: scale(0.7);
|
||||||
top: 32px;
|
top: 32px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,10 @@ c3nav = {
|
||||||
|
|
||||||
$('.locationinput').data('location', null);
|
$('.locationinput').data('location', null);
|
||||||
|
|
||||||
var state = JSON.parse($('main').attr('data-state'));
|
var $main = $('main'),
|
||||||
|
state = JSON.parse($main.attr('data-state'));
|
||||||
|
c3nav.embed = $main.is('[data-embed]');
|
||||||
|
|
||||||
history.replaceState(state, window.location.path);
|
history.replaceState(state, window.location.path);
|
||||||
c3nav.load_state(state, true);
|
c3nav.load_state(state, true);
|
||||||
c3nav.update_map_locations();
|
c3nav.update_map_locations();
|
||||||
|
@ -343,16 +346,16 @@ c3nav = {
|
||||||
if (a.center[0] !== b.center[0] || a.center[1] !== b.center[1]) return false;
|
if (a.center[0] !== b.center[0] || a.center[1] !== b.center[1]) return false;
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
_build_state_url: function (state) {
|
_build_state_url: function (state, embed) {
|
||||||
var url;
|
var url = embed ? '/embed' : '';
|
||||||
if (state.routing) {
|
if (state.routing) {
|
||||||
if (state.origin) {
|
if (state.origin) {
|
||||||
url = (state.destination) ? '/r/'+state.origin.slug+'/'+state.destination.slug+'/' : '/o/'+state.origin.slug+'/';
|
url += (state.destination) ? '/r/'+state.origin.slug+'/'+state.destination.slug+'/' : '/o/'+state.origin.slug+'/';
|
||||||
} else {
|
} else {
|
||||||
url = (state.destination) ? '/d/'+state.destination.slug+'/' : '/r/';
|
url += (state.destination) ? '/d/'+state.destination.slug+'/' : '/r/';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
url = state.destination?('/l/'+state.destination.slug+'/'):'/';
|
url += state.destination?('/l/'+state.destination.slug+'/'):'/';
|
||||||
}
|
}
|
||||||
if (state.details && (url.startsWith('/l/') || url.startsWith('/r/'))) {
|
if (state.details && (url.startsWith('/l/') || url.startsWith('/r/'))) {
|
||||||
url += 'details/'
|
url += 'details/'
|
||||||
|
@ -368,7 +371,12 @@ c3nav = {
|
||||||
|
|
||||||
if (!replace && c3nav._equal_states(old_state, state)) return;
|
if (!replace && c3nav._equal_states(old_state, state)) return;
|
||||||
|
|
||||||
var url = c3nav._build_state_url(state);
|
var url = c3nav._build_state_url(state, c3nav.embed),
|
||||||
|
embed_logo = $('#embed-logo');
|
||||||
|
|
||||||
|
if (embed_logo.length) {
|
||||||
|
embed_logo.attr('href', c3nav._build_state_url(state));
|
||||||
|
}
|
||||||
|
|
||||||
c3nav.state = state;
|
c3nav.state = state;
|
||||||
if (replace || (!state.sidebar && !old_state.sidebar)) {
|
if (replace || (!state.sidebar && !old_state.sidebar)) {
|
||||||
|
@ -859,8 +867,8 @@ c3nav = {
|
||||||
var $search = $('#search'),
|
var $search = $('#search'),
|
||||||
$main = $('main'),
|
$main = $('main'),
|
||||||
padBesideSidebar = ($main.width() > 1000 && ($main.height() < 250 || c3nav.state.details)),
|
padBesideSidebar = ($main.width() > 1000 && ($main.height() < 250 || c3nav.state.details)),
|
||||||
left = padBesideSidebar ? $search.width()+10 : 0,
|
left = padBesideSidebar ? ($search.width() || 0)+10 : 0,
|
||||||
top = padBesideSidebar ? 10 : $search.height()+10;
|
top = padBesideSidebar ? 10 : ($search.height() || 0)+10;
|
||||||
options[topleft || 'paddingTopLeft'] = L.point(left+13, top+41);
|
options[topleft || 'paddingTopLeft'] = L.point(left+13, top+41);
|
||||||
options[bottomright || 'paddingBottomRight'] = L.point(50, 20);
|
options[bottomright || 'paddingBottomRight'] = L.point(50, 20);
|
||||||
return options;
|
return options;
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
<link href="{% static 'site/css/c3nav.css' %}" rel="stylesheet">
|
<link href="{% static 'site/css/c3nav.css' %}" rel="stylesheet">
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
{% if not embed %}
|
||||||
<header>
|
<header>
|
||||||
<h1>c3nav</h1>
|
<h1>c3nav</h1>
|
||||||
<a href="#" id="user">
|
<a href="#" id="user">
|
||||||
|
@ -25,7 +25,10 @@
|
||||||
{% if user_data.subtitle %}<small>{{ user_data.subtitle }}</small>{% endif %}
|
{% if user_data.subtitle %}<small>{{ user_data.subtitle }}</small>{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</header>
|
</header>
|
||||||
<main class="map" data-state="{{ state }}">
|
{% endif %}
|
||||||
|
<main class="map" data-state="{{ state }}"{% if embed %} data-embed{% endif %}>
|
||||||
|
<section id="map" data-bounds="{{ bounds }}" data-levels="{{ levels }}"{% if tile_cache_server %} data-tile-server="{{ tile_cache_server }}"{% endif %}></section>
|
||||||
|
{% if not embed %}
|
||||||
<section id="popup-buttons">
|
<section id="popup-buttons">
|
||||||
<button class="button-clear as-location">{% trans 'Show only this location' %}</button>
|
<button class="button-clear as-location">{% trans 'Show only this location' %}</button>
|
||||||
<button class="button-clear as-destination">{% trans 'Route to here' %}</button>
|
<button class="button-clear as-destination">{% trans 'Route to here' %}</button>
|
||||||
|
@ -36,7 +39,6 @@
|
||||||
<img src="">
|
<img src="">
|
||||||
<input type="text" readonly>
|
<input type="text" readonly>
|
||||||
</section>
|
</section>
|
||||||
<section id="map" data-bounds="{{ bounds }}" data-levels="{{ levels }}"{% if tile_cache_server %} data-tile-server="{{ tile_cache_server }}"{% endif %}></section>
|
|
||||||
<section id="sidebar">
|
<section id="sidebar">
|
||||||
<section id="search" class="loading">
|
<section id="search" class="loading">
|
||||||
<div class="location locationinput empty" id="origin-input">
|
<div class="location locationinput empty" id="origin-input">
|
||||||
|
@ -109,12 +111,20 @@
|
||||||
<section id="route-details" class="details"></section>
|
<section id="route-details" class="details"></section>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
{% else %}
|
||||||
|
<a id="embed-logo">c3nav</a>
|
||||||
|
<section id="popup-buttons"></section>
|
||||||
|
<section id="search">
|
||||||
|
<input type="hidden" id="origin-input">
|
||||||
|
<input type="hidden" id="destination-input">
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
</main>
|
</main>
|
||||||
|
{% if not embed %}
|
||||||
<div id="modal" class="loading">
|
<div id="modal" class="loading">
|
||||||
<div id="modal-content">
|
<div id="modal-content"></div>
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% compress js %}
|
{% compress js %}
|
||||||
<script type="text/javascript" src="{% static 'jquery/jquery.js' %}"></script>
|
<script type="text/javascript" src="{% static 'jquery/jquery.js' %}"></script>
|
||||||
<script type="text/javascript" src="{% static 'leaflet/leaflet.js' %}"></script>
|
<script type="text/javascript" src="{% static 'leaflet/leaflet.js' %}"></script>
|
||||||
|
|
|
@ -2,14 +2,17 @@ from django.conf.urls import url
|
||||||
|
|
||||||
from c3nav.site.views import map_index, qr_code
|
from c3nav.site.views import map_index, qr_code
|
||||||
|
|
||||||
|
slug = r'(?P<slug>[a-z0-9-_.:]+)'
|
||||||
|
slug2 = r'(?P<slug2>[a-z0-9-_.:]+)'
|
||||||
details = r'(?P<details>details/)?'
|
details = r'(?P<details>details/)?'
|
||||||
pos = r'(@(?P<level>[a-z0-9-_:]+),(?P<x>-?\d+(\.\d+)?),(?P<y>-?\d+(\.\d+)?),(?P<zoom>-?\d+(\.\d+)?))?'
|
pos = r'(@(?P<level>[a-z0-9-_:]+),(?P<x>-?\d+(\.\d+)?),(?P<y>-?\d+(\.\d+)?),(?P<zoom>-?\d+(\.\d+)?))?'
|
||||||
|
embed = r'(?P<embed>embed/)?'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^(?P<mode>[l])/(?P<slug>[a-z0-9-_.:]+)/%s%s$' % (details, pos), map_index, name='site.index'),
|
url(r'^%s(?P<mode>[l])/%s/%s%s$' % (embed, slug, details, pos), map_index, name='site.index'),
|
||||||
url(r'^(?P<mode>[od])/(?P<slug>[a-z0-9-_.:]+)/%s$' % pos, map_index, name='site.index'),
|
url(r'^%s(?P<mode>[od])/%s/%s$' % (embed, slug, pos), map_index, name='site.index'),
|
||||||
url(r'^r/(?P<slug>[a-z0-9-_.:]+)/(?P<slug2>[a-z0-9-_.:]+)/%s%s$' % (details, pos), map_index, name='site.index'),
|
url(r'^%sr/%s/%s/%s%s$' % (embed, slug, slug2, details, pos), map_index, name='site.index'),
|
||||||
url(r'^(?P<mode>r)/%s$' % pos, map_index, name='site.index'),
|
url(r'^%s(?P<mode>r)/%s$' % (embed, pos), map_index, name='site.index'),
|
||||||
url(r'^qr/(?P<path>.*)$', qr_code, name='site.qr'),
|
url(r'^qr/(?P<path>.*)$', qr_code, name='site.qr'),
|
||||||
url(r'^%s$' % pos, map_index, name='site.index')
|
url(r'^%s$' % pos, map_index, name='site.index')
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.views.decorators.cache import cache_control
|
from django.views.decorators.cache import cache_control
|
||||||
|
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||||
from django.views.decorators.http import etag
|
from django.views.decorators.http import etag
|
||||||
|
|
||||||
from c3nav.mapdata.models import Location, Source
|
from c3nav.mapdata.models import Location, Source
|
||||||
|
@ -35,7 +36,8 @@ def check_location(location: Optional[str], request) -> Optional[SpecificLocatio
|
||||||
return location
|
return location
|
||||||
|
|
||||||
|
|
||||||
def map_index(request, mode=None, slug=None, slug2=None, details=None, level=None, x=None, y=None, zoom=None):
|
def map_index(request, mode=None, slug=None, slug2=None, details=None,
|
||||||
|
level=None, x=None, y=None, zoom=None, embed=None):
|
||||||
origin = None
|
origin = None
|
||||||
destination = None
|
destination = None
|
||||||
routing = False
|
routing = False
|
||||||
|
@ -76,9 +78,12 @@ def map_index(request, mode=None, slug=None, slug2=None, details=None, level=Non
|
||||||
'state': json.dumps(state, separators=(',', ':'), cls=DjangoJSONEncoder),
|
'state': json.dumps(state, separators=(',', ':'), cls=DjangoJSONEncoder),
|
||||||
'tile_cache_server': settings.TILE_CACHE_SERVER,
|
'tile_cache_server': settings.TILE_CACHE_SERVER,
|
||||||
'user_data': get_user_data(request),
|
'user_data': get_user_data(request),
|
||||||
|
'embed': bool(embed),
|
||||||
}
|
}
|
||||||
response = render(request, 'site/map.html', ctx)
|
response = render(request, 'site/map.html', ctx)
|
||||||
set_tile_access_cookie(request, response)
|
set_tile_access_cookie(request, response)
|
||||||
|
if embed:
|
||||||
|
xframe_options_exempt(lambda: response)()
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue