umap-project 1.12.1__py3-none-any.whl → 1.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- umap/__init__.py +1 -1
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +82 -54
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +82 -54
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +86 -58
- umap/locale/en/LC_MESSAGES/django.po +79 -51
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +82 -54
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +84 -56
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +108 -80
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +82 -54
- umap/locale/ms/LC_MESSAGES/django.mo +0 -0
- umap/locale/ms/LC_MESSAGES/django.po +82 -54
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +82 -54
- umap/locale/sv/LC_MESSAGES/django.mo +0 -0
- umap/locale/sv/LC_MESSAGES/django.po +82 -54
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +86 -58
- umap/models.py +29 -0
- umap/static/umap/base.css +33 -5
- umap/static/umap/content.css +41 -2
- umap/static/umap/img/16.svg +12 -2
- umap/static/umap/img/source/16.svg +165 -820
- umap/static/umap/js/umap.browser.js +9 -3
- umap/static/umap/js/umap.controls.js +60 -222
- umap/static/umap/js/umap.core.js +66 -30
- umap/static/umap/js/umap.forms.js +18 -31
- umap/static/umap/js/umap.icon.js +44 -21
- umap/static/umap/js/umap.js +11 -27
- umap/static/umap/js/umap.layer.js +68 -25
- umap/static/umap/js/umap.popup.js +87 -0
- umap/static/umap/js/umap.share.js +254 -0
- umap/static/umap/js/umap.ui.js +4 -2
- umap/static/umap/locale/am_ET.js +19 -9
- umap/static/umap/locale/am_ET.json +19 -9
- umap/static/umap/locale/ar.js +19 -9
- umap/static/umap/locale/ar.json +19 -9
- umap/static/umap/locale/ast.js +19 -9
- umap/static/umap/locale/ast.json +19 -9
- umap/static/umap/locale/bg.js +19 -9
- umap/static/umap/locale/bg.json +19 -9
- umap/static/umap/locale/br.js +22 -12
- umap/static/umap/locale/br.json +22 -12
- umap/static/umap/locale/ca.js +19 -9
- umap/static/umap/locale/ca.json +19 -9
- umap/static/umap/locale/cs_CZ.js +19 -9
- umap/static/umap/locale/cs_CZ.json +19 -9
- umap/static/umap/locale/da.js +19 -9
- umap/static/umap/locale/da.json +19 -9
- umap/static/umap/locale/de.js +30 -20
- umap/static/umap/locale/de.json +30 -20
- umap/static/umap/locale/el.js +19 -9
- umap/static/umap/locale/el.json +19 -9
- umap/static/umap/locale/en.js +19 -9
- umap/static/umap/locale/en.json +19 -9
- umap/static/umap/locale/en_US.json +19 -9
- umap/static/umap/locale/es.js +19 -9
- umap/static/umap/locale/es.json +19 -9
- umap/static/umap/locale/et.js +19 -9
- umap/static/umap/locale/et.json +19 -9
- umap/static/umap/locale/fa_IR.js +19 -9
- umap/static/umap/locale/fa_IR.json +19 -9
- umap/static/umap/locale/fi.js +19 -9
- umap/static/umap/locale/fi.json +19 -9
- umap/static/umap/locale/fr.js +21 -11
- umap/static/umap/locale/fr.json +21 -11
- umap/static/umap/locale/gl.js +19 -9
- umap/static/umap/locale/gl.json +19 -9
- umap/static/umap/locale/he.js +19 -9
- umap/static/umap/locale/he.json +19 -9
- umap/static/umap/locale/hr.js +19 -9
- umap/static/umap/locale/hr.json +19 -9
- umap/static/umap/locale/hu.js +19 -9
- umap/static/umap/locale/hu.json +19 -9
- umap/static/umap/locale/id.js +19 -9
- umap/static/umap/locale/id.json +19 -9
- umap/static/umap/locale/is.js +19 -9
- umap/static/umap/locale/is.json +19 -9
- umap/static/umap/locale/it.js +19 -9
- umap/static/umap/locale/it.json +19 -9
- umap/static/umap/locale/ja.js +19 -9
- umap/static/umap/locale/ja.json +19 -9
- umap/static/umap/locale/ko.js +19 -9
- umap/static/umap/locale/ko.json +19 -9
- umap/static/umap/locale/lt.js +19 -9
- umap/static/umap/locale/lt.json +19 -9
- umap/static/umap/locale/ms.js +19 -9
- umap/static/umap/locale/ms.json +19 -9
- umap/static/umap/locale/nl.js +20 -10
- umap/static/umap/locale/nl.json +20 -10
- umap/static/umap/locale/no.js +19 -9
- umap/static/umap/locale/no.json +19 -9
- umap/static/umap/locale/pl.js +19 -9
- umap/static/umap/locale/pl.json +19 -9
- umap/static/umap/locale/pl_PL.json +19 -9
- umap/static/umap/locale/pt.js +19 -9
- umap/static/umap/locale/pt.json +19 -9
- umap/static/umap/locale/pt_BR.js +19 -9
- umap/static/umap/locale/pt_BR.json +19 -9
- umap/static/umap/locale/pt_PT.js +19 -9
- umap/static/umap/locale/pt_PT.json +19 -9
- umap/static/umap/locale/ro.js +19 -9
- umap/static/umap/locale/ro.json +19 -9
- umap/static/umap/locale/ru.js +19 -9
- umap/static/umap/locale/ru.json +19 -9
- umap/static/umap/locale/sk_SK.js +19 -9
- umap/static/umap/locale/sk_SK.json +19 -9
- umap/static/umap/locale/sl.js +19 -9
- umap/static/umap/locale/sl.json +19 -9
- umap/static/umap/locale/sr.js +19 -9
- umap/static/umap/locale/sr.json +19 -9
- umap/static/umap/locale/sv.js +19 -9
- umap/static/umap/locale/sv.json +19 -9
- umap/static/umap/locale/th_TH.js +19 -9
- umap/static/umap/locale/th_TH.json +19 -9
- umap/static/umap/locale/tr.js +19 -9
- umap/static/umap/locale/tr.json +19 -9
- umap/static/umap/locale/uk_UA.js +19 -9
- umap/static/umap/locale/uk_UA.json +19 -9
- umap/static/umap/locale/vi.js +19 -9
- umap/static/umap/locale/vi.json +19 -9
- umap/static/umap/locale/vi_VN.json +19 -9
- umap/static/umap/locale/zh.js +19 -9
- umap/static/umap/locale/zh.json +19 -9
- umap/static/umap/locale/zh_CN.json +19 -9
- umap/static/umap/locale/zh_TW.Big5.json +19 -9
- umap/static/umap/locale/zh_TW.js +55 -45
- umap/static/umap/locale/zh_TW.json +55 -45
- umap/static/umap/map.css +77 -10
- umap/static/umap/test/Map.Export.js +3 -3
- umap/static/umap/test/Polygon.js +2 -2
- umap/static/umap/test/Polyline.js +2 -0
- umap/static/umap/test/index.html +1 -0
- umap/static/umap/vendors/leaflet/leaflet-src.esm.js +7055 -7054
- umap/static/umap/vendors/leaflet/leaflet-src.js +7144 -7144
- umap/static/umap/vendors/toolbar/leaflet.toolbar-src.js +1 -1
- umap/templates/auth/user_form.html +1 -1
- umap/templates/umap/content.html +1 -1
- umap/templates/umap/js.html +1 -0
- umap/templates/umap/map_list.html +1 -1
- umap/templates/umap/map_table.html +67 -35
- umap/templates/umap/user_dashboard.html +23 -1
- umap/templatetags/umap_tags.py +7 -27
- umap/tests/integration/test_edit_datalayer.py +45 -0
- umap/tests/integration/test_export_map.py +2 -3
- umap/tests/integration/test_facets_browser.py +86 -0
- umap/utils.py +17 -0
- umap/views.py +7 -18
- {umap_project-1.12.1.dist-info → umap_project-1.13.0.dist-info}/METADATA +4 -11
- {umap_project-1.12.1.dist-info → umap_project-1.13.0.dist-info}/RECORD +159 -156
- {umap_project-1.12.1.dist-info → umap_project-1.13.0.dist-info}/WHEEL +0 -0
- {umap_project-1.12.1.dist-info → umap_project-1.13.0.dist-info}/entry_points.txt +0 -0
- {umap_project-1.12.1.dist-info → umap_project-1.13.0.dist-info}/licenses/LICENSE +0 -0
umap/static/umap/js/umap.icon.js
CHANGED
|
@@ -67,15 +67,8 @@ L.U.Icon.Default = L.U.Icon.extend({
|
|
|
67
67
|
|
|
68
68
|
onAdd: function () {
|
|
69
69
|
const src = this._getIconUrl('icon')
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (src.startsWith('/') && src.endsWith('.svg')) {
|
|
73
|
-
const bgcolor = this._getColor()
|
|
74
|
-
// Must be called after icon container is added to the DOM
|
|
75
|
-
if (L.DomUtil.contrastedColor(this.elements.container, bgcolor)) {
|
|
76
|
-
this.elements.img.style.filter = 'invert(1)'
|
|
77
|
-
}
|
|
78
|
-
}
|
|
70
|
+
const bgcolor = this._getColor()
|
|
71
|
+
L.U.Icon.setIconContrast(this.elements.icon, this.elements.container, src, bgcolor)
|
|
79
72
|
},
|
|
80
73
|
|
|
81
74
|
createIcon: function () {
|
|
@@ -89,18 +82,7 @@ L.U.Icon.Default = L.U.Icon.extend({
|
|
|
89
82
|
this.elements.arrow = L.DomUtil.create('div', 'icon_arrow', this.elements.main)
|
|
90
83
|
const src = this._getIconUrl('icon')
|
|
91
84
|
if (src) {
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
src.startsWith('http') ||
|
|
95
|
-
src.startsWith('/') ||
|
|
96
|
-
src.startsWith('data:image')
|
|
97
|
-
) {
|
|
98
|
-
this.elements.img = L.DomUtil.create('img', null, this.elements.container)
|
|
99
|
-
this.elements.img.src = src
|
|
100
|
-
} else {
|
|
101
|
-
this.elements.span = L.DomUtil.create('span', null, this.elements.container)
|
|
102
|
-
this.elements.span.textContent = src
|
|
103
|
-
}
|
|
85
|
+
this.elements.icon = L.U.Icon.makeIconElement(src, this.elements.container)
|
|
104
86
|
}
|
|
105
87
|
this._setIconStyles(this.elements.main, 'icon')
|
|
106
88
|
return this.elements.main
|
|
@@ -208,3 +190,44 @@ L.U.Icon.Cluster = L.DivIcon.extend({
|
|
|
208
190
|
return color || L.DomUtil.TextColorFromBackgroundColor(el, backgroundColor)
|
|
209
191
|
},
|
|
210
192
|
})
|
|
193
|
+
|
|
194
|
+
L.U.Icon.isImg = function (src) {
|
|
195
|
+
return L.Util.isPath(src) || L.Util.isRemoteUrl(src) || L.Util.isDataImage(src)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
L.U.Icon.makeIconElement = function (src, parent) {
|
|
199
|
+
let icon
|
|
200
|
+
if (L.U.Icon.isImg(src)) {
|
|
201
|
+
icon = L.DomUtil.create('img')
|
|
202
|
+
icon.src = src
|
|
203
|
+
} else {
|
|
204
|
+
icon = L.DomUtil.create('span')
|
|
205
|
+
icon.textContent = src
|
|
206
|
+
}
|
|
207
|
+
parent.appendChild(icon)
|
|
208
|
+
return icon
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
L.U.Icon.setIconContrast = function (el, parent, src, bgcolor) {
|
|
212
|
+
/*
|
|
213
|
+
* el: the element we'll adapt the style, it can be an image or text
|
|
214
|
+
* parent: the element we'll consider to decide whether to adapt the style,
|
|
215
|
+
* by looking at its background color
|
|
216
|
+
* src: the raw "icon" value, can be an URL, a path, text, emoticon, etc.
|
|
217
|
+
* bgcolor: the background color, used for caching and in case we cannot guess the
|
|
218
|
+
* parent background color
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
if (L.DomUtil.contrastedColor(parent, bgcolor)) {
|
|
222
|
+
// Decide whether to switch svg to white or not, but do it
|
|
223
|
+
// only for internal SVG, as invert could do weird things
|
|
224
|
+
if (L.Util.isPath(src) && src.endsWith('.svg')) {
|
|
225
|
+
// Must be called after icon container is added to the DOM
|
|
226
|
+
// An image
|
|
227
|
+
el.style.filter = 'invert(1)'
|
|
228
|
+
} else if (!el.src) {
|
|
229
|
+
// Text icon
|
|
230
|
+
el.style.color = 'white'
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
umap/static/umap/js/umap.js
CHANGED
|
@@ -29,7 +29,12 @@ L.Map.mergeOptions({
|
|
|
29
29
|
name: '',
|
|
30
30
|
description: '',
|
|
31
31
|
displayPopupFooter: false,
|
|
32
|
-
|
|
32
|
+
// When a TileLayer is in TMS mode, it needs -y instead of y.
|
|
33
|
+
// This is usually handled by the TileLayer instance itself, but
|
|
34
|
+
// we cannot rely on this because of the y is overriden by Leaflet
|
|
35
|
+
// See https://github.com/Leaflet/Leaflet/pull/9201
|
|
36
|
+
// And let's remove this -y when this PR is merged and released.
|
|
37
|
+
demoTileInfos: { s: 'a', z: 9, x: 265, y: 181, '-y': 181, r: '' },
|
|
33
38
|
licences: [],
|
|
34
39
|
licence: '',
|
|
35
40
|
enableMarkerDraw: true,
|
|
@@ -254,7 +259,7 @@ L.U.Map.include({
|
|
|
254
259
|
}
|
|
255
260
|
this.initShortcuts()
|
|
256
261
|
this.onceDataLoaded(function () {
|
|
257
|
-
if (L.Util.queryString('share')) this.
|
|
262
|
+
if (L.Util.queryString('share')) this.share.open()
|
|
258
263
|
else if (this.options.onLoadPanel === 'databrowser') this.openBrowser()
|
|
259
264
|
else if (this.options.onLoadPanel === 'caption') this.displayCaption()
|
|
260
265
|
else if (
|
|
@@ -347,6 +352,7 @@ L.U.Map.include({
|
|
|
347
352
|
this.browser = new L.U.Browser(this)
|
|
348
353
|
this.importer = new L.U.Importer(this)
|
|
349
354
|
this.drop = new L.U.DropControl(this)
|
|
355
|
+
this.share = new L.U.Share(this)
|
|
350
356
|
this._controls.tilelayers = new L.U.TileLayerControl(this)
|
|
351
357
|
this._controls.tilelayers.setLayers()
|
|
352
358
|
|
|
@@ -848,28 +854,6 @@ L.U.Map.include({
|
|
|
848
854
|
})
|
|
849
855
|
},
|
|
850
856
|
|
|
851
|
-
format: function (mode) {
|
|
852
|
-
const type = this.EXPORT_TYPES[mode]
|
|
853
|
-
const content = type.formatter(this)
|
|
854
|
-
let name = this.options.name || 'data'
|
|
855
|
-
name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
|
|
856
|
-
const filename = name + type.ext
|
|
857
|
-
return { content, filetype: type.filetype, filename }
|
|
858
|
-
},
|
|
859
|
-
|
|
860
|
-
download: function (mode) {
|
|
861
|
-
const { content, filetype, filename } = this.format(mode)
|
|
862
|
-
const blob = new Blob([content], { type: filetype })
|
|
863
|
-
window.URL = window.URL || window.webkitURL
|
|
864
|
-
const el = document.createElement('a')
|
|
865
|
-
el.download = filename
|
|
866
|
-
el.href = window.URL.createObjectURL(blob)
|
|
867
|
-
el.style.display = 'none'
|
|
868
|
-
document.body.appendChild(el)
|
|
869
|
-
el.click()
|
|
870
|
-
document.body.removeChild(el)
|
|
871
|
-
},
|
|
872
|
-
|
|
873
857
|
processFileToImport: function (file, layer, type) {
|
|
874
858
|
type = type || L.Util.detectFileType(file)
|
|
875
859
|
if (!type) {
|
|
@@ -1701,9 +1685,9 @@ L.U.Map.include({
|
|
|
1701
1685
|
L.DomUtil.createButton(
|
|
1702
1686
|
'button umap-download',
|
|
1703
1687
|
advancedButtons,
|
|
1704
|
-
L._('Open download panel'),
|
|
1705
|
-
this.
|
|
1706
|
-
this
|
|
1688
|
+
L._('Open share & download panel'),
|
|
1689
|
+
this.share.open,
|
|
1690
|
+
this.share
|
|
1707
1691
|
)
|
|
1708
1692
|
},
|
|
1709
1693
|
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
L.U.Layer = {
|
|
2
2
|
canBrowse: true,
|
|
3
3
|
|
|
4
|
+
getType: function () {
|
|
5
|
+
const proto = Object.getPrototypeOf(this)
|
|
6
|
+
return proto.constructor.TYPE
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
getName: function () {
|
|
10
|
+
const proto = Object.getPrototypeOf(this)
|
|
11
|
+
return proto.constructor.NAME
|
|
12
|
+
},
|
|
13
|
+
|
|
4
14
|
getFeatures: function () {
|
|
5
15
|
return this._layers
|
|
6
16
|
},
|
|
@@ -9,7 +19,7 @@ L.U.Layer = {
|
|
|
9
19
|
return []
|
|
10
20
|
},
|
|
11
21
|
|
|
12
|
-
|
|
22
|
+
onEdit: function () {},
|
|
13
23
|
|
|
14
24
|
hasDataVisible: function () {
|
|
15
25
|
return !!Object.keys(this._layers).length
|
|
@@ -17,7 +27,10 @@ L.U.Layer = {
|
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
L.U.Layer.Default = L.FeatureGroup.extend({
|
|
20
|
-
|
|
30
|
+
statics: {
|
|
31
|
+
NAME: L._('Default'),
|
|
32
|
+
TYPE: 'Default',
|
|
33
|
+
},
|
|
21
34
|
includes: [L.U.Layer],
|
|
22
35
|
|
|
23
36
|
initialize: function (datalayer) {
|
|
@@ -39,7 +52,10 @@ L.U.MarkerCluster = L.MarkerCluster.extend({
|
|
|
39
52
|
})
|
|
40
53
|
|
|
41
54
|
L.U.Layer.Cluster = L.MarkerClusterGroup.extend({
|
|
42
|
-
|
|
55
|
+
statics: {
|
|
56
|
+
NAME: L._('Clustered'),
|
|
57
|
+
TYPE: 'Cluster',
|
|
58
|
+
},
|
|
43
59
|
includes: [L.U.Layer],
|
|
44
60
|
|
|
45
61
|
initialize: function (datalayer) {
|
|
@@ -104,20 +120,23 @@ L.U.Layer.Cluster = L.MarkerClusterGroup.extend({
|
|
|
104
120
|
]
|
|
105
121
|
},
|
|
106
122
|
|
|
107
|
-
|
|
108
|
-
if (
|
|
123
|
+
onEdit: function (field, builder) {
|
|
124
|
+
if (field === 'options.cluster.radius') {
|
|
109
125
|
// No way to reset radius of an already instanciated MarkerClusterGroup...
|
|
110
126
|
this.datalayer.resetLayer(true)
|
|
111
127
|
return
|
|
112
128
|
}
|
|
113
|
-
if (
|
|
129
|
+
if (field === 'options.color') {
|
|
114
130
|
this.options.polygonOptions.color = this.datalayer.getColor()
|
|
115
131
|
}
|
|
116
132
|
},
|
|
117
133
|
})
|
|
118
134
|
|
|
119
135
|
L.U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
120
|
-
|
|
136
|
+
statics: {
|
|
137
|
+
NAME: L._('Choropleth'),
|
|
138
|
+
TYPE: 'Choropleth',
|
|
139
|
+
},
|
|
121
140
|
includes: [L.U.Layer],
|
|
122
141
|
canBrowse: true,
|
|
123
142
|
// Have defaults that better suit the choropleth mode.
|
|
@@ -234,14 +253,17 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
234
253
|
L.FeatureGroup.prototype.onAdd.call(this, map)
|
|
235
254
|
},
|
|
236
255
|
|
|
237
|
-
|
|
238
|
-
|
|
256
|
+
onEdit: function (field, builder) {
|
|
257
|
+
// If user touches the breaks, then force manual mode
|
|
258
|
+
if (field === 'options.choropleth.breaks') {
|
|
239
259
|
this.datalayer.options.choropleth.mode = 'manual'
|
|
240
|
-
|
|
260
|
+
builder.helpers['options.choropleth.mode'].fetch()
|
|
241
261
|
}
|
|
242
262
|
this.computeBreaks()
|
|
243
|
-
|
|
244
|
-
|
|
263
|
+
// If user changes the mode or the number of classes,
|
|
264
|
+
// then update the breaks input value
|
|
265
|
+
if (field === 'options.choropleth.mode' || field === 'options.choropleth.classes') {
|
|
266
|
+
builder.helpers['options.choropleth.breaks'].fetch()
|
|
245
267
|
}
|
|
246
268
|
},
|
|
247
269
|
|
|
@@ -317,7 +339,10 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
317
339
|
})
|
|
318
340
|
|
|
319
341
|
L.U.Layer.Heat = L.HeatLayer.extend({
|
|
320
|
-
|
|
342
|
+
statics: {
|
|
343
|
+
NAME: L._('Heatmap'),
|
|
344
|
+
TYPE: 'Heat',
|
|
345
|
+
},
|
|
321
346
|
includes: [L.U.Layer],
|
|
322
347
|
canBrowse: false,
|
|
323
348
|
|
|
@@ -382,12 +407,12 @@ L.U.Layer.Heat = L.HeatLayer.extend({
|
|
|
382
407
|
]
|
|
383
408
|
},
|
|
384
409
|
|
|
385
|
-
|
|
386
|
-
if (
|
|
410
|
+
onEdit: function (field, builder) {
|
|
411
|
+
if (field === 'options.heat.intensityProperty') {
|
|
387
412
|
this.datalayer.resetLayer(true) // We need to repopulate the latlngs
|
|
388
413
|
return
|
|
389
414
|
}
|
|
390
|
-
if (
|
|
415
|
+
if (field === 'options.heat.radius') {
|
|
391
416
|
this.options.radius = this.datalayer.options.heat.radius
|
|
392
417
|
}
|
|
393
418
|
this._updateOptions()
|
|
@@ -612,7 +637,7 @@ L.U.DataLayer = L.Evented.extend({
|
|
|
612
637
|
// Only reset if type is defined (undefined is the default) and different from current type
|
|
613
638
|
if (
|
|
614
639
|
this.layer &&
|
|
615
|
-
(!this.options.type || this.options.type === this.layer.
|
|
640
|
+
(!this.options.type || this.options.type === this.layer.getType()) &&
|
|
616
641
|
!force
|
|
617
642
|
) {
|
|
618
643
|
return
|
|
@@ -1185,6 +1210,28 @@ L.U.DataLayer = L.Evented.extend({
|
|
|
1185
1210
|
})
|
|
1186
1211
|
container.appendChild(builder.build())
|
|
1187
1212
|
|
|
1213
|
+
const redrawCallback = function (e) {
|
|
1214
|
+
const field = e.helper.field,
|
|
1215
|
+
builder = e.helper.builder
|
|
1216
|
+
this.hide()
|
|
1217
|
+
this.layer.onEdit(field, builder)
|
|
1218
|
+
this.show()
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
const layerOptions = this.layer.getEditableOptions()
|
|
1222
|
+
|
|
1223
|
+
if (layerOptions.length) {
|
|
1224
|
+
builder = new L.U.FormBuilder(this, layerOptions, {
|
|
1225
|
+
id: 'datalayer-layer-properties',
|
|
1226
|
+
callback: redrawCallback,
|
|
1227
|
+
})
|
|
1228
|
+
const layerProperties = L.DomUtil.createFieldset(
|
|
1229
|
+
container,
|
|
1230
|
+
`${this.layer.getName()}: ${L._('settings')}`
|
|
1231
|
+
)
|
|
1232
|
+
layerProperties.appendChild(builder.build())
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1188
1235
|
let shapeOptions = [
|
|
1189
1236
|
'options.color',
|
|
1190
1237
|
'options.iconClass',
|
|
@@ -1198,12 +1245,6 @@ L.U.DataLayer = L.Evented.extend({
|
|
|
1198
1245
|
'options.fillOpacity',
|
|
1199
1246
|
]
|
|
1200
1247
|
|
|
1201
|
-
const redrawCallback = function (e) {
|
|
1202
|
-
this.hide()
|
|
1203
|
-
this.layer.postUpdate(e)
|
|
1204
|
-
this.show()
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
1248
|
builder = new L.U.FormBuilder(this, shapeOptions, {
|
|
1208
1249
|
id: 'datalayer-advanced-properties',
|
|
1209
1250
|
callback: redrawCallback,
|
|
@@ -1220,8 +1261,6 @@ L.U.DataLayer = L.Evented.extend({
|
|
|
1220
1261
|
'options.labelKey',
|
|
1221
1262
|
]
|
|
1222
1263
|
|
|
1223
|
-
optionsFields = optionsFields.concat(this.layer.getEditableOptions())
|
|
1224
|
-
|
|
1225
1264
|
builder = new L.U.FormBuilder(this, optionsFields, {
|
|
1226
1265
|
id: 'datalayer-advanced-properties',
|
|
1227
1266
|
callback: redrawCallback,
|
|
@@ -1443,6 +1482,10 @@ L.U.DataLayer = L.Evented.extend({
|
|
|
1443
1482
|
return !!this.options.browsable && this.canBrowse() && this.isVisible()
|
|
1444
1483
|
},
|
|
1445
1484
|
|
|
1485
|
+
count: function () {
|
|
1486
|
+
return this._index.length
|
|
1487
|
+
},
|
|
1488
|
+
|
|
1446
1489
|
hasData: function () {
|
|
1447
1490
|
return !!this._index.length
|
|
1448
1491
|
},
|
|
@@ -251,3 +251,90 @@ L.U.PopupTemplate.GeoRSSLink = L.U.PopupTemplate.Default.extend({
|
|
|
251
251
|
return a
|
|
252
252
|
},
|
|
253
253
|
})
|
|
254
|
+
|
|
255
|
+
L.U.PopupTemplate.OSM = L.U.PopupTemplate.Default.extend({
|
|
256
|
+
options: {
|
|
257
|
+
className: 'umap-openstreetmap',
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
getName: function () {
|
|
261
|
+
const props = this.feature.properties
|
|
262
|
+
if (L.locale && props[`name:${L.locale}`]) return props[`name:${L.locale}`]
|
|
263
|
+
return props.name
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
renderBody: function () {
|
|
267
|
+
const props = this.feature.properties
|
|
268
|
+
const container = L.DomUtil.add('div')
|
|
269
|
+
const title = L.DomUtil.add('h3', 'popup-title', container)
|
|
270
|
+
const color = this.feature.getDynamicOption('color')
|
|
271
|
+
title.style.backgroundColor = color
|
|
272
|
+
const iconUrl = this.feature.getDynamicOption('iconUrl')
|
|
273
|
+
let icon = L.U.Icon.makeIconElement(iconUrl, title)
|
|
274
|
+
L.DomUtil.addClass(icon, 'icon')
|
|
275
|
+
L.U.Icon.setIconContrast(icon, title, iconUrl, color)
|
|
276
|
+
if (L.DomUtil.contrastedColor(title, color)) title.style.color = 'white'
|
|
277
|
+
L.DomUtil.add('span', '', title, this.getName())
|
|
278
|
+
const street = props['addr:street']
|
|
279
|
+
if (street) {
|
|
280
|
+
const row = L.DomUtil.add('address', 'address', container)
|
|
281
|
+
const number = props['addr:housenumber']
|
|
282
|
+
if (number) {
|
|
283
|
+
// Poor way to deal with international forms of writting addresses
|
|
284
|
+
L.DomUtil.add('span', '', row, `${L._('No.')}: ${number}`)
|
|
285
|
+
L.DomUtil.add('span', '', row, `${L._('Street')}: ${street}`)
|
|
286
|
+
} else {
|
|
287
|
+
L.DomUtil.add('span', '', row, street)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (props.website) {
|
|
291
|
+
L.DomUtil.element(
|
|
292
|
+
'a',
|
|
293
|
+
{ href: props.website, textContent: props.website },
|
|
294
|
+
container
|
|
295
|
+
)
|
|
296
|
+
}
|
|
297
|
+
const phone = props.phone || props['contact:phone']
|
|
298
|
+
if (phone) {
|
|
299
|
+
L.DomUtil.add(
|
|
300
|
+
'div',
|
|
301
|
+
'',
|
|
302
|
+
container,
|
|
303
|
+
L.DomUtil.element('a', { href: `tel:${phone}`, textContent: phone })
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
if (props.mobile) {
|
|
307
|
+
L.DomUtil.add(
|
|
308
|
+
'div',
|
|
309
|
+
'',
|
|
310
|
+
container,
|
|
311
|
+
L.DomUtil.element('a', {
|
|
312
|
+
href: `tel:${props.mobile}`,
|
|
313
|
+
textContent: props.mobile,
|
|
314
|
+
})
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
const email = props.email || props['contact:email']
|
|
318
|
+
if (email) {
|
|
319
|
+
L.DomUtil.add(
|
|
320
|
+
'div',
|
|
321
|
+
'',
|
|
322
|
+
container,
|
|
323
|
+
L.DomUtil.element('a', { href: `mailto:${email}`, textContent: email })
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
const id = props['@id']
|
|
327
|
+
if (id) {
|
|
328
|
+
L.DomUtil.add(
|
|
329
|
+
'div',
|
|
330
|
+
'osm-link',
|
|
331
|
+
container,
|
|
332
|
+
L.DomUtil.element('a', {
|
|
333
|
+
href: `https://www.openstreetmap.org/${id}`,
|
|
334
|
+
textContent: L._('See on OpenStreetMap'),
|
|
335
|
+
})
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
return container
|
|
339
|
+
},
|
|
340
|
+
})
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
L.U.Share = L.Class.extend({
|
|
2
|
+
EXPORT_TYPES: {
|
|
3
|
+
geojson: {
|
|
4
|
+
formatter: function (map) {
|
|
5
|
+
return JSON.stringify(map.toGeoJSON(), null, 2)
|
|
6
|
+
},
|
|
7
|
+
ext: '.geojson',
|
|
8
|
+
filetype: 'application/json',
|
|
9
|
+
},
|
|
10
|
+
gpx: {
|
|
11
|
+
formatter: function (map) {
|
|
12
|
+
return togpx(map.toGeoJSON())
|
|
13
|
+
},
|
|
14
|
+
ext: '.gpx',
|
|
15
|
+
filetype: 'application/gpx+xml',
|
|
16
|
+
},
|
|
17
|
+
kml: {
|
|
18
|
+
formatter: function (map) {
|
|
19
|
+
return tokml(map.toGeoJSON())
|
|
20
|
+
},
|
|
21
|
+
ext: '.kml',
|
|
22
|
+
filetype: 'application/vnd.google-earth.kml+xml',
|
|
23
|
+
},
|
|
24
|
+
csv: {
|
|
25
|
+
formatter: function (map) {
|
|
26
|
+
const table = []
|
|
27
|
+
map.eachFeature((feature) => {
|
|
28
|
+
const row = feature.toGeoJSON()['properties'],
|
|
29
|
+
center = feature.getCenter()
|
|
30
|
+
delete row['_umap_options']
|
|
31
|
+
row['Latitude'] = center.lat
|
|
32
|
+
row['Longitude'] = center.lng
|
|
33
|
+
table.push(row)
|
|
34
|
+
})
|
|
35
|
+
return csv2geojson.dsv.csvFormat(table)
|
|
36
|
+
},
|
|
37
|
+
ext: '.csv',
|
|
38
|
+
filetype: 'text/csv',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
initialize: function (map) {
|
|
43
|
+
this.map = map
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
build: function () {
|
|
47
|
+
this.container = L.DomUtil.create('div', 'umap-share')
|
|
48
|
+
this.title = L.DomUtil.create('h3', '', this.container)
|
|
49
|
+
this.title.textContent = L._('Share and download')
|
|
50
|
+
|
|
51
|
+
L.DomUtil.createCopiableInput(
|
|
52
|
+
this.container,
|
|
53
|
+
L._('Link to view the map'),
|
|
54
|
+
window.location.protocol + L.Util.getBaseUrl()
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if (this.map.options.shortUrl) {
|
|
58
|
+
L.DomUtil.createCopiableInput(
|
|
59
|
+
this.container,
|
|
60
|
+
L._('Short link'),
|
|
61
|
+
this.map.options.shortUrl
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
L.DomUtil.create('hr', '', this.container)
|
|
66
|
+
|
|
67
|
+
L.DomUtil.add('h4', '', this.container, L._('Download'))
|
|
68
|
+
L.DomUtil.add('small', 'label', this.container, L._("Only visible layers' data"))
|
|
69
|
+
for (const key in this.EXPORT_TYPES) {
|
|
70
|
+
if (this.EXPORT_TYPES.hasOwnProperty(key)) {
|
|
71
|
+
L.DomUtil.createButton(
|
|
72
|
+
'download-file',
|
|
73
|
+
this.container,
|
|
74
|
+
this.EXPORT_TYPES[key].name || key,
|
|
75
|
+
() => this.download(key),
|
|
76
|
+
this
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
L.DomUtil.create('div', 'vspace', this.container)
|
|
81
|
+
L.DomUtil.add(
|
|
82
|
+
'small',
|
|
83
|
+
'label',
|
|
84
|
+
this.container,
|
|
85
|
+
L._('All data and settings of the map')
|
|
86
|
+
)
|
|
87
|
+
const downloadUrl = L.Util.template(this.map.options.urls.map_download, {
|
|
88
|
+
map_id: this.map.options.umap_id,
|
|
89
|
+
})
|
|
90
|
+
const link = L.DomUtil.createLink(
|
|
91
|
+
'download-backup',
|
|
92
|
+
this.container,
|
|
93
|
+
L._('full backup'),
|
|
94
|
+
downloadUrl
|
|
95
|
+
)
|
|
96
|
+
let name = this.map.options.name || 'data'
|
|
97
|
+
name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
|
|
98
|
+
link.setAttribute('download', `${name}.umap`)
|
|
99
|
+
L.DomUtil.create('hr', '', this.container)
|
|
100
|
+
|
|
101
|
+
const embedTitle = L.DomUtil.add('h4', '', this.container, L._('Embed the map'))
|
|
102
|
+
const iframe = L.DomUtil.create('textarea', 'umap-share-iframe', this.container)
|
|
103
|
+
const urlTitle = L.DomUtil.add('h4', '', this.container, L._('Direct link'))
|
|
104
|
+
const exportUrl = L.DomUtil.createCopiableInput(
|
|
105
|
+
this.container,
|
|
106
|
+
L._('Share this link to open a customized map view'),
|
|
107
|
+
''
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
exportUrl.type = 'text'
|
|
111
|
+
const UIFields = [
|
|
112
|
+
['dimensions.width', { handler: 'Input', label: L._('width') }],
|
|
113
|
+
['dimensions.height', { handler: 'Input', label: L._('height') }],
|
|
114
|
+
[
|
|
115
|
+
'options.includeFullScreenLink',
|
|
116
|
+
{ handler: 'Switch', label: L._('Include full screen link?') },
|
|
117
|
+
],
|
|
118
|
+
[
|
|
119
|
+
'options.currentView',
|
|
120
|
+
{ handler: 'Switch', label: L._('Current view instead of default map view?') },
|
|
121
|
+
],
|
|
122
|
+
[
|
|
123
|
+
'options.keepCurrentDatalayers',
|
|
124
|
+
{ handler: 'Switch', label: L._('Keep current visible layers') },
|
|
125
|
+
],
|
|
126
|
+
[
|
|
127
|
+
'options.viewCurrentFeature',
|
|
128
|
+
{ handler: 'Switch', label: L._('Open current feature on load') },
|
|
129
|
+
],
|
|
130
|
+
'queryString.moreControl',
|
|
131
|
+
'queryString.scrollWheelZoom',
|
|
132
|
+
'queryString.miniMap',
|
|
133
|
+
'queryString.scaleControl',
|
|
134
|
+
'queryString.onLoadPanel',
|
|
135
|
+
'queryString.captionBar',
|
|
136
|
+
'queryString.captionMenus',
|
|
137
|
+
]
|
|
138
|
+
for (let i = 0; i < this.map.HIDDABLE_CONTROLS.length; i++) {
|
|
139
|
+
UIFields.push(`queryString.${this.map.HIDDABLE_CONTROLS[i]}Control`)
|
|
140
|
+
}
|
|
141
|
+
const iframeExporter = new L.U.IframeExporter(this.map)
|
|
142
|
+
const buildIframeCode = () => {
|
|
143
|
+
iframe.innerHTML = iframeExporter.build()
|
|
144
|
+
exportUrl.value = window.location.protocol + iframeExporter.buildUrl()
|
|
145
|
+
}
|
|
146
|
+
buildIframeCode()
|
|
147
|
+
const builder = new L.U.FormBuilder(iframeExporter, UIFields, {
|
|
148
|
+
callback: buildIframeCode,
|
|
149
|
+
})
|
|
150
|
+
const iframeOptions = L.DomUtil.createFieldset(
|
|
151
|
+
this.container,
|
|
152
|
+
L._('Embed and link options')
|
|
153
|
+
)
|
|
154
|
+
iframeOptions.appendChild(builder.build())
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
open: function () {
|
|
158
|
+
if (!this.container) this.build()
|
|
159
|
+
this.map.ui.openPanel({ data: { html: this.container } })
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
format: function (mode) {
|
|
163
|
+
const type = this.EXPORT_TYPES[mode]
|
|
164
|
+
const content = type.formatter(this.map)
|
|
165
|
+
let name = this.map.options.name || 'data'
|
|
166
|
+
name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
|
|
167
|
+
const filename = name + type.ext
|
|
168
|
+
return { content, filetype: type.filetype, filename }
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
download: function (mode) {
|
|
172
|
+
const { content, filetype, filename } = this.format(mode)
|
|
173
|
+
const blob = new Blob([content], { type: filetype })
|
|
174
|
+
window.URL = window.URL || window.webkitURL
|
|
175
|
+
const el = document.createElement('a')
|
|
176
|
+
el.download = filename
|
|
177
|
+
el.href = window.URL.createObjectURL(blob)
|
|
178
|
+
el.style.display = 'none'
|
|
179
|
+
document.body.appendChild(el)
|
|
180
|
+
el.click()
|
|
181
|
+
document.body.removeChild(el)
|
|
182
|
+
},
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
L.U.IframeExporter = L.Evented.extend({
|
|
186
|
+
options: {
|
|
187
|
+
includeFullScreenLink: true,
|
|
188
|
+
currentView: false,
|
|
189
|
+
keepCurrentDatalayers: false,
|
|
190
|
+
viewCurrentFeature: false,
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
queryString: {
|
|
194
|
+
scaleControl: false,
|
|
195
|
+
miniMap: false,
|
|
196
|
+
scrollWheelZoom: false,
|
|
197
|
+
zoomControl: true,
|
|
198
|
+
editMode: 'disabled',
|
|
199
|
+
moreControl: true,
|
|
200
|
+
searchControl: null,
|
|
201
|
+
tilelayersControl: null,
|
|
202
|
+
embedControl: null,
|
|
203
|
+
datalayersControl: true,
|
|
204
|
+
onLoadPanel: 'none',
|
|
205
|
+
captionBar: false,
|
|
206
|
+
captionMenus: true,
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
dimensions: {
|
|
210
|
+
width: '100%',
|
|
211
|
+
height: '300px',
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
initialize: function (map) {
|
|
215
|
+
this.map = map
|
|
216
|
+
this.baseUrl = L.Util.getBaseUrl()
|
|
217
|
+
// Use map default, not generic default
|
|
218
|
+
this.queryString.onLoadPanel = this.map.options.onLoadPanel
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
getMap: function () {
|
|
222
|
+
return this.map
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
buildUrl: function (options) {
|
|
226
|
+
const datalayers = []
|
|
227
|
+
if (this.options.viewCurrentFeature && this.map.currentFeature) {
|
|
228
|
+
this.queryString.feature = this.map.currentFeature.getSlug()
|
|
229
|
+
}
|
|
230
|
+
if (this.options.keepCurrentDatalayers) {
|
|
231
|
+
this.map.eachDataLayer((datalayer) => {
|
|
232
|
+
if (datalayer.isVisible() && datalayer.umap_id) {
|
|
233
|
+
datalayers.push(datalayer.umap_id)
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
this.queryString.datalayers = datalayers.join(',')
|
|
237
|
+
} else {
|
|
238
|
+
delete this.queryString.datalayers
|
|
239
|
+
}
|
|
240
|
+
const currentView = this.options.currentView ? window.location.hash : ''
|
|
241
|
+
const queryString = L.extend({}, this.queryString, options)
|
|
242
|
+
return `${this.baseUrl}?${L.Util.buildQueryString(queryString)}${currentView}`
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
build: function () {
|
|
246
|
+
const iframeUrl = this.buildUrl()
|
|
247
|
+
let code = `<iframe width="${this.dimensions.width}" height="${this.dimensions.height}" frameborder="0" allowfullscreen allow="geolocation" src="${iframeUrl}"></iframe>`
|
|
248
|
+
if (this.options.includeFullScreenLink) {
|
|
249
|
+
const fullUrl = this.buildUrl({ scrollWheelZoom: true })
|
|
250
|
+
code += `<p><a href="${fullUrl}">${L._('See full screen')}</a></p>`
|
|
251
|
+
}
|
|
252
|
+
return code
|
|
253
|
+
},
|
|
254
|
+
})
|