mirror of
https://github.com/pretix/pretix.git
synced 2026-05-07 15:34:02 +00:00
* Fix #1416 -- Add canonical geodata field for events and subevents * Add optional geocoding through OpenCageData * Fix markup everywhere * Add Leaflet map to geo coordinates * Fix tests, add credits * Fix spelling
This commit is contained in:
@@ -70,7 +70,7 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
model = Event
|
||||
fields = ('name', 'slug', 'live', 'testmode', 'currency', 'date_from',
|
||||
'date_to', 'date_admission', 'is_public', 'presale_start',
|
||||
'presale_end', 'location', 'has_subevents', 'meta_data', 'seating_plan',
|
||||
'presale_end', 'location', 'geo_lat', 'geo_lon', 'has_subevents', 'meta_data', 'seating_plan',
|
||||
'plugins', 'seat_category_mapping')
|
||||
|
||||
def validate(self, data):
|
||||
@@ -277,8 +277,9 @@ class SubEventSerializer(I18nAwareModelSerializer):
|
||||
class Meta:
|
||||
model = SubEvent
|
||||
fields = ('id', 'name', 'date_from', 'date_to', 'active', 'date_admission',
|
||||
'presale_start', 'presale_end', 'location', 'event', 'is_public', 'seating_plan',
|
||||
'item_price_overrides', 'variation_price_overrides', 'meta_data', 'seat_category_mapping')
|
||||
'presale_start', 'presale_end', 'location', 'geo_lat', 'geo_lon', 'event', 'is_public',
|
||||
'seating_plan', 'item_price_overrides', 'variation_price_overrides', 'meta_data',
|
||||
'seat_category_mapping')
|
||||
|
||||
def validate(self, data):
|
||||
data = super().validate(data)
|
||||
|
||||
@@ -14,6 +14,7 @@ from django.utils.translation.trans_real import (
|
||||
parse_accept_lang_header,
|
||||
)
|
||||
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
from pretix.multidomain.urlreverse import get_domain
|
||||
|
||||
_supported = None
|
||||
@@ -187,6 +188,11 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||
# https://github.com/pretix/pretix/issues/765
|
||||
resp['P3P'] = 'CP=\"ALL DSP COR CUR ADM TAI OUR IND COM NAV INT\"'
|
||||
|
||||
img_src = []
|
||||
gs = GlobalSettingsObject()
|
||||
if gs.settings.leaflet_tiles:
|
||||
img_src.append(gs.settings.leaflet_tiles[:gs.settings.leaflet_tiles.index("/", 10)].replace("{s}", "*"))
|
||||
|
||||
h = {
|
||||
'default-src': ["{static}"],
|
||||
'script-src': ['{static}', 'https://checkout.stripe.com', 'https://js.stripe.com'],
|
||||
@@ -196,7 +202,7 @@ class SecurityMiddleware(MiddlewareMixin):
|
||||
'child-src': ['{static}', 'https://checkout.stripe.com', 'https://js.stripe.com'],
|
||||
'style-src': ["{static}", "{media}"],
|
||||
'connect-src': ["{dynamic}", "{media}", "https://checkout.stripe.com"],
|
||||
'img-src': ["{static}", "{media}", "data:", "https://*.stripe.com"],
|
||||
'img-src': ["{static}", "{media}", "data:", "https://*.stripe.com"] + img_src,
|
||||
'font-src': ["{static}"],
|
||||
'media-src': ["{static}", "data:"],
|
||||
# form-action is not only used to match on form actions, but also on URLs
|
||||
|
||||
33
src/pretix/base/migrations/0139_auto_20191019_1317.py
Normal file
33
src/pretix/base/migrations/0139_auto_20191019_1317.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 2.2.1 on 2019-10-19 13:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0138_auto_20191017_1151'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='geo_lat',
|
||||
field=models.FloatField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='geo_lon',
|
||||
field=models.FloatField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subevent',
|
||||
name='geo_lat',
|
||||
field=models.FloatField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='subevent',
|
||||
name='geo_lon',
|
||||
field=models.FloatField(null=True),
|
||||
),
|
||||
]
|
||||
@@ -324,6 +324,14 @@ class Event(EventMixin, LoggedModel):
|
||||
max_length=200,
|
||||
verbose_name=_("Location"),
|
||||
)
|
||||
geo_lat = models.FloatField(
|
||||
verbose_name=_("Latitude"),
|
||||
null=True, blank=True,
|
||||
)
|
||||
geo_lon = models.FloatField(
|
||||
verbose_name=_("Longitude"),
|
||||
null=True, blank=True,
|
||||
)
|
||||
plugins = models.TextField(
|
||||
null=False, blank=True,
|
||||
verbose_name=_("Plugins"),
|
||||
@@ -929,6 +937,14 @@ class SubEvent(EventMixin, LoggedModel):
|
||||
max_length=200,
|
||||
verbose_name=_("Location"),
|
||||
)
|
||||
geo_lat = models.FloatField(
|
||||
verbose_name=_("Latitude"),
|
||||
null=True, blank=True,
|
||||
)
|
||||
geo_lon = models.FloatField(
|
||||
verbose_name=_("Longitude"),
|
||||
null=True, blank=True
|
||||
)
|
||||
frontpage_text = I18nTextField(
|
||||
null=True, blank=True,
|
||||
verbose_name=_("Frontpage text")
|
||||
|
||||
@@ -704,6 +704,18 @@ Your {event} team"""))
|
||||
'default': '',
|
||||
'type': LazyI18nString
|
||||
},
|
||||
'opencagedata_apikey': {
|
||||
'default': None,
|
||||
'type': str
|
||||
},
|
||||
'leaflet_tiles': {
|
||||
'default': None,
|
||||
'type': str
|
||||
},
|
||||
'leaflet_tiles_attribution': {
|
||||
'default': None,
|
||||
'type': str
|
||||
},
|
||||
'frontpage_subevent_ordering': {
|
||||
'default': 'date_ascending',
|
||||
'type': str
|
||||
|
||||
@@ -112,6 +112,8 @@ class EventWizardBasicsForm(I18nModelForm):
|
||||
'presale_start',
|
||||
'presale_end',
|
||||
'location',
|
||||
'geo_lat',
|
||||
'geo_lon',
|
||||
]
|
||||
field_classes = {
|
||||
'date_from': SplitDateTimeField,
|
||||
@@ -282,6 +284,8 @@ class EventUpdateForm(I18nModelForm):
|
||||
'presale_start',
|
||||
'presale_end',
|
||||
'location',
|
||||
'geo_lat',
|
||||
'geo_lon',
|
||||
]
|
||||
field_classes = {
|
||||
'date_from': SplitDateTimeField,
|
||||
|
||||
@@ -37,6 +37,20 @@ class GlobalSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
label=_("Global message banner detail text"),
|
||||
)),
|
||||
('opencagedata_apikey', forms.CharField(
|
||||
required=False,
|
||||
label=_("OpenCage API key for geocoding"),
|
||||
)),
|
||||
('leaflet_tiles', forms.CharField(
|
||||
required=False,
|
||||
label=_("Leaflet tiles URL pattern"),
|
||||
help_text=_("e.g. {sample}").format(sample="https://a.tile.openstreetmap.org/{z}/{x}/{y}.png")
|
||||
)),
|
||||
('leaflet_tiles_attribution', forms.CharField(
|
||||
required=False,
|
||||
label=_("Leaflet tiles attribution"),
|
||||
help_text=_("e.g. {sample}").format(sample='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors')
|
||||
)),
|
||||
])
|
||||
responses = register_global_settings.send(self)
|
||||
for r, response in sorted(responses, key=lambda r: str(r[0])):
|
||||
|
||||
@@ -37,6 +37,8 @@ class SubEventForm(I18nModelForm):
|
||||
'presale_end',
|
||||
'location',
|
||||
'frontpage_text',
|
||||
'geo_lat',
|
||||
'geo_lon',
|
||||
]
|
||||
field_classes = {
|
||||
'date_from': SplitDateTimeField,
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/quicksetup.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/dashboard.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/tabs.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "leaflet/leaflet.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/geo.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/details.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/asynctask.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "sortable/Sortable.js" %}"></script>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends "pretixcontrol/event/settings_base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
{% load hierarkey_form %}
|
||||
{% block custom_header %}
|
||||
{{ block.super }}
|
||||
@@ -19,7 +20,30 @@
|
||||
{% bootstrap_field form.slug layout="control" %}
|
||||
{% bootstrap_field form.date_from layout="control" %}
|
||||
{% bootstrap_field form.date_to layout="control" %}
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% bootstrap_field form.date_admission layout="control" %}
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
{% bootstrap_field sform.contact_mail layout="control" %}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends "pretixcontrol/events/create_base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
{% block form %}
|
||||
<fieldset>
|
||||
<legend>{% trans "General information" %}</legend>
|
||||
@@ -36,7 +37,30 @@
|
||||
</div>
|
||||
{% bootstrap_field form.date_from layout="control" %}
|
||||
{% bootstrap_field form.date_to layout="control" %}
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
{% bootstrap_field form.tax_rate addon_after="%" layout="control" %}
|
||||
</fieldset>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
{% load bootstrap3 %}
|
||||
{% load formset_tags %}
|
||||
{% load captureas %}
|
||||
{% load static %}
|
||||
{% load eventsignal %}
|
||||
{% block title %}{% trans "Date" context "subevent" %}{% endblock %}
|
||||
{% block content %}
|
||||
@@ -266,7 +267,30 @@
|
||||
{% bootstrap_field form.active layout="control" %}
|
||||
{% bootstrap_field form.time_from layout="control" %}
|
||||
{% bootstrap_field form.time_to layout="control" %}
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% bootstrap_field form.time_admission layout="control" %}
|
||||
{% bootstrap_field form.frontpage_text layout="control" %}
|
||||
{% bootstrap_field form.is_public layout="control" %}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
{% load bootstrap3 %}
|
||||
{% load formset_tags %}
|
||||
{% load eventsignal %}
|
||||
{% load static %}
|
||||
{% block title %}{% trans "Date" context "subevent" %}{% endblock %}
|
||||
{% block content %}
|
||||
{% if not subevent.pk %}
|
||||
@@ -24,7 +25,30 @@
|
||||
{% bootstrap_field form.active layout="control" %}
|
||||
{% bootstrap_field form.date_from layout="control" %}
|
||||
{% bootstrap_field form.date_to layout="control" %}
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="geodata-section">
|
||||
{% bootstrap_field form.location layout="control" %}
|
||||
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Geo coordinates" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lat layout="inline" %}
|
||||
{% if global_settings.opencagedata_apikey %}
|
||||
<p class="attrib">
|
||||
<a href="https://openstreetmap.org/" target="_blank">
|
||||
{% trans "Geocoding data © OpenStreetMap" %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{% bootstrap_field form.geo_lon layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% bootstrap_field form.date_admission layout="control" %}
|
||||
{% bootstrap_field form.frontpage_text layout="control" %}
|
||||
{% bootstrap_field form.is_public layout="control" %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.conf.urls import include, url
|
||||
|
||||
from pretix.control.views import (
|
||||
auth, checkin, dashboards, event, global_settings, item, main, oauth,
|
||||
auth, checkin, dashboards, event, geo, global_settings, item, main, oauth,
|
||||
orders, organizer, pdf, search, shredder, subevents, typeahead, user,
|
||||
users, vouchers, waitinglist,
|
||||
)
|
||||
@@ -22,6 +22,7 @@ urlpatterns = [
|
||||
url(r'^logdetail/$', global_settings.LogDetailView.as_view(), name='global.logdetail'),
|
||||
url(r'^logdetail/payment/$', global_settings.PaymentDetailView.as_view(), name='global.paymentdetail'),
|
||||
url(r'^logdetail/refund/$', global_settings.RefundDetailView.as_view(), name='global.refunddetail'),
|
||||
url(r'^geocode/$', geo.GeoCodeView.as_view(), name='global.geocode'),
|
||||
url(r'^reauth/$', user.ReauthView.as_view(), name='user.reauth'),
|
||||
url(r'^sudo/$', user.StartStaffSession.as_view(), name='user.sudo'),
|
||||
url(r'^sudo/stop/$', user.StopStaffSession.as_view(), name='user.sudo.stop'),
|
||||
|
||||
59
src/pretix/control/views/geo.py
Normal file
59
src/pretix/control/views/geo.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import logging
|
||||
from urllib.parse import quote
|
||||
|
||||
import requests
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.cache import cache
|
||||
from django.http import JsonResponse
|
||||
from django.views.generic.base import View
|
||||
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GeoCodeView(LoginRequiredMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
gs = GlobalSettingsObject()
|
||||
if not gs.settings.opencagedata_apikey:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'results': []
|
||||
}, status=200)
|
||||
|
||||
q = request.GET.get('q')
|
||||
cd = cache.get('geocode:{}'.format(q))
|
||||
if cd:
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'results': cd
|
||||
}, status=200)
|
||||
|
||||
try:
|
||||
r = requests.get(
|
||||
'https://api.opencagedata.com/geocode/v1/json?q={}&key={}'.format(
|
||||
quote(q), gs.settings.opencagedata_apikey
|
||||
)
|
||||
)
|
||||
r.raise_for_status()
|
||||
except IOError:
|
||||
logger.exception("Geocoding failed")
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'results': []
|
||||
}, status=200)
|
||||
else:
|
||||
d = r.json()
|
||||
res = [
|
||||
{
|
||||
'formatted': r['formatted'],
|
||||
'lat': r['geometry']['lat'],
|
||||
'lon': r['geometry']['lng'],
|
||||
} for r in d['results']
|
||||
]
|
||||
cache.set('geocode:{}'.format(q), res, timeout=3600 * 6)
|
||||
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'results': res
|
||||
}, status=200)
|
||||
@@ -134,6 +134,8 @@ class EventWizard(SafeSessionWizardView):
|
||||
initial['currency'] = self.clone_from.currency
|
||||
initial['date_from'] = self.clone_from.date_from
|
||||
initial['date_to'] = self.clone_from.date_to
|
||||
initial['geo_lat'] = self.clone_from.geo_lat
|
||||
initial['geo_lon'] = self.clone_from.geo_lon
|
||||
initial['presale_start'] = self.clone_from.presale_start
|
||||
initial['presale_end'] = self.clone_from.presale_end
|
||||
initial['location'] = self.clone_from.location
|
||||
@@ -245,6 +247,8 @@ class EventWizard(SafeSessionWizardView):
|
||||
presale_start=event.presale_start,
|
||||
presale_end=event.presale_end,
|
||||
location=event.location,
|
||||
geo_lat=event.geo_lat,
|
||||
geo_lon=event.geo_lon,
|
||||
active=True
|
||||
)
|
||||
|
||||
|
||||
BIN
src/pretix/static/leaflet/images/layers-2x.png
Normal file
BIN
src/pretix/static/leaflet/images/layers-2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/pretix/static/leaflet/images/layers.png
Normal file
BIN
src/pretix/static/leaflet/images/layers.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 696 B |
BIN
src/pretix/static/leaflet/images/marker-icon-2x.png
Normal file
BIN
src/pretix/static/leaflet/images/marker-icon-2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/pretix/static/leaflet/images/marker-icon.png
Normal file
BIN
src/pretix/static/leaflet/images/marker-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
BIN
src/pretix/static/leaflet/images/marker-shadow.png
Normal file
BIN
src/pretix/static/leaflet/images/marker-shadow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 618 B |
5
src/pretix/static/leaflet/leaflet.js
Normal file
5
src/pretix/static/leaflet/leaflet.js
Normal file
File diff suppressed because one or more lines are too long
640
src/pretix/static/leaflet/leaflet.scss
Normal file
640
src/pretix/static/leaflet/leaflet.scss
Normal file
@@ -0,0 +1,640 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-pane > svg,
|
||||
.leaflet-pane > canvas,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
/* Prevents IE11 from highlighting tiles in blue */
|
||||
.leaflet-tile::selection {
|
||||
background: transparent;
|
||||
}
|
||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||
.leaflet-safari .leaflet-tile {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
/* hack that prevents hw layers "stretching" when loading new tiles */
|
||||
.leaflet-safari .leaflet-tile-container {
|
||||
width: 1600px;
|
||||
height: 1600px;
|
||||
-webkit-transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
||||
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container .leaflet-overlay-pane svg,
|
||||
.leaflet-container .leaflet-marker-pane img,
|
||||
.leaflet-container .leaflet-shadow-pane img,
|
||||
.leaflet-container .leaflet-tile-pane img,
|
||||
.leaflet-container img.leaflet-image-layer,
|
||||
.leaflet-container .leaflet-tile {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.leaflet-container.leaflet-touch-zoom {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag {
|
||||
-ms-touch-action: pinch-zoom;
|
||||
/* Fallback for FF which doesn't support pinch-zoom */
|
||||
touch-action: none;
|
||||
touch-action: pinch-zoom;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.leaflet-container {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.leaflet-container a {
|
||||
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 800;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-pane { z-index: 400; }
|
||||
|
||||
.leaflet-tile-pane { z-index: 200; }
|
||||
.leaflet-overlay-pane { z-index: 400; }
|
||||
.leaflet-shadow-pane { z-index: 500; }
|
||||
.leaflet-marker-pane { z-index: 600; }
|
||||
.leaflet-tooltip-pane { z-index: 650; }
|
||||
.leaflet-popup-pane { z-index: 700; }
|
||||
|
||||
.leaflet-map-pane canvas { z-index: 100; }
|
||||
.leaflet-map-pane svg { z-index: 200; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 800;
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-tile {
|
||||
will-change: opacity;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
.leaflet-zoom-animated {
|
||||
-webkit-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
will-change: transform;
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-grab {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
.leaflet-crosshair,
|
||||
.leaflet-crosshair .leaflet-interactive {
|
||||
cursor: crosshair;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging .leaflet-grab,
|
||||
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
||||
.leaflet-dragging .leaflet-marker-draggable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* marker & overlays interactivity */
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-pane > svg path,
|
||||
.leaflet-tile-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon.leaflet-interactive,
|
||||
.leaflet-image-layer.leaflet-interactive,
|
||||
.leaflet-pane > svg path.leaflet-interactive,
|
||||
svg.leaflet-image-layer.leaflet-interactive path {
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
outline: 0;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-container a.leaflet-active {
|
||||
outline: 2px solid orange;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #38f;
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
|
||||
/* general typography */
|
||||
.leaflet-container {
|
||||
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-bar a:hover {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-bar a:hover {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
cursor: default;
|
||||
background-color: #f4f4f4;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in,
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-retina .leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers-2x.png);
|
||||
background-size: 26px 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-scrollbar {
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
/* Default icon URLs */
|
||||
.leaflet-default-icon-path {
|
||||
background-image: url(images/marker-icon.png);
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
}
|
||||
.leaflet-control-attribution a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-control-attribution a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.leaflet-container .leaflet-control-attribution,
|
||||
.leaflet-container .leaflet-control-scale {
|
||||
font-size: 11px;
|
||||
}
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution,
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
||||
/* popup */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 19px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 18px 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -10px auto 0;
|
||||
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
color: #333;
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 4px 4px 0 0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
font: 16px/14px Tahoma, Verdana, sans-serif;
|
||||
color: #c3c3c3;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background: transparent;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover {
|
||||
color: #999;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip-container {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-control-zoom,
|
||||
.leaflet-oldie .leaflet-control-layers,
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
|
||||
|
||||
/* Tooltip */
|
||||
/* Base styles for the element that has a tooltip */
|
||||
.leaflet-tooltip {
|
||||
position: absolute;
|
||||
padding: 6px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
white-space: nowrap;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-tooltip.leaflet-clickable {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-tooltip-top:before,
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border: 6px solid transparent;
|
||||
background: transparent;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* Directions */
|
||||
|
||||
.leaflet-tooltip-bottom {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.leaflet-tooltip-top {
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-top:before {
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-top:before {
|
||||
bottom: 0;
|
||||
margin-bottom: -12px;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before {
|
||||
top: 0;
|
||||
margin-top: -12px;
|
||||
margin-left: -6px;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-left {
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-right {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before {
|
||||
right: 0;
|
||||
margin-right: -12px;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-right:before {
|
||||
left: 0;
|
||||
margin-left: -12px;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
122
src/pretix/static/pretixcontrol/js/ui/geo.js
Normal file
122
src/pretix/static/pretixcontrol/js/ui/geo.js
Normal file
@@ -0,0 +1,122 @@
|
||||
/*globals $*/
|
||||
|
||||
$(function () {
|
||||
var j = 0;
|
||||
$(".geodata-section").each(function () {
|
||||
// Geocoding
|
||||
var $sec = $(this);
|
||||
var $inp = $(this).find("textarea[lang=en], input[lang=en]").first();
|
||||
if ($inp.length === 0) {
|
||||
$inp = $(this).find("textarea, input").first();
|
||||
}
|
||||
var timer, timer2;
|
||||
var touched = $sec.find("input[name$=geo_lat]").val() !== "";
|
||||
|
||||
function load() {
|
||||
window.clearTimeout(timer);
|
||||
var q = $.trim($inp.val().replace(/\n/g, ", "));
|
||||
if ((touched && $sec.find("input[name$=geo_lat]").val() !== "") || $.trim(q) === "") {
|
||||
return;
|
||||
}
|
||||
$sec.find(".col-md-1").html("<span class='fa fa-cog fa-spin'></span>");
|
||||
$.getJSON('/control/geocode/?q=' + escape(q), function (res) {
|
||||
var q2 = $.trim($inp.val().replace(/\n/g, ", "));
|
||||
if (q2 !== q) {
|
||||
return; // lost race
|
||||
}
|
||||
if (res.results) {
|
||||
$sec.find("input[name$=geo_lat]").val(res.results[0].lat);
|
||||
$sec.find("input[name$=geo_lon]").val(res.results[0].lon);
|
||||
center(13);
|
||||
}
|
||||
$sec.find(".col-md-1").html("");
|
||||
})
|
||||
}
|
||||
|
||||
$sec.find("input[name$=geo_lat], input[name$=geo_lon]").change(function () {
|
||||
touched = $sec.find("input[name$=geo_lat]").val() !== "";
|
||||
center(13);
|
||||
}).keyup(function () {
|
||||
if (timer2) {
|
||||
window.clearTimeout(timer2);
|
||||
}
|
||||
timer2 = window.setTimeout(center, 300);
|
||||
});
|
||||
|
||||
$inp.change(load);
|
||||
$inp.keyup(function () {
|
||||
if (timer) {
|
||||
window.clearTimeout(timer);
|
||||
}
|
||||
timer = window.setTimeout(load, 1000);
|
||||
});
|
||||
|
||||
// Map
|
||||
var $grp = $sec.find(".geodata-group");
|
||||
var tiles = $grp.attr("data-tiles");
|
||||
var attrib = $grp.attr("data-attrib");
|
||||
if (tiles) {
|
||||
var $map = $("<div>");
|
||||
$grp.append($("<div>").addClass("col-md-9 col-md-offset-3").append($map));
|
||||
var map = L.map($map.get(0));
|
||||
L.tileLayer(tiles, {
|
||||
attribution: attrib,
|
||||
maxZoom: 18,
|
||||
}).addTo(map);
|
||||
var $lat = $sec.find("input[name$=geo_lat]");
|
||||
var $lon = $sec.find("input[name$=geo_lon]");
|
||||
|
||||
function getpoint() {
|
||||
if ($lat.val() !== "" && $lon.val() !== "") {
|
||||
return [parseFloat($lat.val().replace(",", ".")), parseFloat($lon.val().replace(",", "."))];
|
||||
} else {
|
||||
return [0.0, 0.0];
|
||||
}
|
||||
}
|
||||
|
||||
var marker = L.marker(getpoint(), {
|
||||
draggable: 'true',
|
||||
icon: L.icon({
|
||||
iconUrl: $grp.attr("data-icon"),
|
||||
shadowUrl: $grp.attr("data-shadow"),
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
tooltipAnchor: [16, -28],
|
||||
shadowSize: [41, 41]
|
||||
})
|
||||
});
|
||||
marker.addTo(map);
|
||||
marker.on("dragend", function (event) {
|
||||
var position = marker.getLatLng();
|
||||
marker.setLatLng(position, {
|
||||
draggable: 'true'
|
||||
}).bindPopup(position).update();
|
||||
$lat.val(position.lat.toFixed(7));
|
||||
$lon.val(position.lng.toFixed(7));
|
||||
center(null);
|
||||
});
|
||||
|
||||
function center(zoom) {
|
||||
if ($lat.val() !== "" && $lon.val() !== "") {
|
||||
if (zoom) {
|
||||
map.setView(getpoint(), zoom);
|
||||
} else {
|
||||
map.panTo(getpoint());
|
||||
}
|
||||
marker.setLatLng(getpoint(), {
|
||||
draggable: 'true'
|
||||
}).bindPopup(getpoint()).update();
|
||||
} else {
|
||||
map.fitWorld();
|
||||
}
|
||||
}
|
||||
|
||||
center(13);
|
||||
} else {
|
||||
function center(zoom) {
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
@@ -224,6 +224,23 @@ div.mail-preview {
|
||||
input[type=number].short {
|
||||
width: 80px !important;
|
||||
}
|
||||
.geodata-group {
|
||||
.form-group {
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
.attrib {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: $font-size-small;
|
||||
a {
|
||||
color: $text-muted;
|
||||
}
|
||||
}
|
||||
.leaflet-container {
|
||||
height: 200px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.metadata-group {
|
||||
.form-group {
|
||||
margin: 0 0 10px 0;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
@import "_dashboard.scss";
|
||||
@import "../../pretixbase/scss/webfont.scss";
|
||||
@import "../../fileupload/jquery.fileupload.scss";
|
||||
@import "../../leaflet/leaflet.scss";
|
||||
@import "../../select2/select2.scss";
|
||||
@import "../../select2/select2_bootstrap.scss";
|
||||
@import "../../colorpicker/bootstrap-colorpicker.scss";
|
||||
|
||||
Reference in New Issue
Block a user