umap-project 3.3.6__py3-none-any.whl → 3.4.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/context_processors.py +4 -1
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +43 -33
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +43 -33
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +35 -29
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +35 -29
- umap/locale/en/LC_MESSAGES/django.po +47 -41
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +43 -33
- umap/locale/et/LC_MESSAGES/django.mo +0 -0
- umap/locale/et/LC_MESSAGES/django.po +58 -54
- umap/locale/eu/LC_MESSAGES/django.mo +0 -0
- umap/locale/eu/LC_MESSAGES/django.po +43 -33
- umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
- umap/locale/fa_IR/LC_MESSAGES/django.po +43 -33
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +36 -30
- umap/locale/gl/LC_MESSAGES/django.mo +0 -0
- umap/locale/gl/LC_MESSAGES/django.po +43 -33
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +35 -29
- umap/locale/is/LC_MESSAGES/django.mo +0 -0
- umap/locale/is/LC_MESSAGES/django.po +43 -33
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +43 -33
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +35 -29
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +114 -103
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +43 -33
- umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
- umap/locale/th_TH/LC_MESSAGES/django.po +310 -109
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +80 -70
- umap/management/commands/switch_user.py +2 -2
- umap/migrations/0018_datalayer_uuid.py +1 -1
- umap/models.py +7 -3
- umap/settings/local.py.sample +1 -1
- umap/static/umap/base.css +89 -32
- umap/static/umap/content.css +129 -33
- umap/static/umap/css/bar.css +82 -20
- umap/static/umap/css/browser.css +163 -0
- umap/static/umap/css/contextmenu.css +15 -0
- umap/static/umap/css/dialog.css +36 -16
- umap/static/umap/css/form.css +123 -33
- umap/static/umap/css/icon.css +46 -3
- umap/static/umap/css/panel.css +7 -3
- umap/static/umap/css/popup.css +34 -8
- umap/static/umap/css/tooltip.css +8 -4
- umap/static/umap/img/16-white.svg +26 -8
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/source/16-white.svg +36 -18
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/js/components/alerts/alert.css +69 -31
- umap/static/umap/js/components/alerts/alert.js +20 -2
- umap/static/umap/js/components/base.js +1 -1
- umap/static/umap/js/modules/browser.js +69 -61
- umap/static/umap/js/modules/caption.js +10 -7
- umap/static/umap/js/modules/data/features.js +85 -60
- umap/static/umap/js/modules/data/fields.js +446 -0
- umap/static/umap/js/modules/data/layer.js +78 -184
- umap/static/umap/js/modules/domutils.js +109 -0
- umap/static/umap/js/modules/filters.js +780 -0
- umap/static/umap/js/modules/form/builder.js +8 -5
- umap/static/umap/js/modules/form/fields.js +111 -221
- umap/static/umap/js/modules/formatter.js +24 -1
- umap/static/umap/js/modules/help.js +4 -3
- umap/static/umap/js/modules/i18n.js +1 -1
- umap/static/umap/js/modules/importer.js +1 -1
- umap/static/umap/js/modules/importers/opendata.js +15 -0
- umap/static/umap/js/modules/importers/openrouteservice.js +6 -1
- umap/static/umap/js/modules/managers.js +2 -2
- umap/static/umap/js/modules/permissions.js +39 -31
- umap/static/umap/js/modules/rendering/controls.js +11 -9
- umap/static/umap/js/modules/rendering/icon.js +3 -8
- umap/static/umap/js/modules/rendering/layers/base.js +1 -1
- umap/static/umap/js/modules/rendering/layers/classified.js +18 -11
- umap/static/umap/js/modules/rendering/layers/cluster.js +5 -3
- umap/static/umap/js/modules/rendering/layers/heat.js +27 -21
- umap/static/umap/js/modules/rendering/template.js +50 -23
- umap/static/umap/js/modules/rendering/ui.js +29 -23
- umap/static/umap/js/modules/rules.js +38 -44
- umap/static/umap/js/modules/schema.js +3 -6
- umap/static/umap/js/modules/share.js +5 -4
- umap/static/umap/js/modules/tableeditor.js +50 -38
- umap/static/umap/js/modules/templates.js +2 -3
- umap/static/umap/js/modules/ui/bar.js +55 -23
- umap/static/umap/js/modules/ui/dialog.js +38 -27
- umap/static/umap/js/modules/ui/panel.js +23 -8
- umap/static/umap/js/modules/ui/tooltip.js +6 -5
- umap/static/umap/js/modules/umap.js +151 -56
- umap/static/umap/js/modules/utils.js +24 -2
- umap/static/umap/js/umap.core.js +1 -110
- umap/static/umap/locale/am_ET.js +52 -17
- umap/static/umap/locale/am_ET.json +52 -17
- umap/static/umap/locale/ar.js +52 -17
- umap/static/umap/locale/ar.json +52 -17
- umap/static/umap/locale/ast.js +52 -17
- umap/static/umap/locale/ast.json +52 -17
- umap/static/umap/locale/bg.js +52 -17
- umap/static/umap/locale/bg.json +52 -17
- umap/static/umap/locale/br.js +48 -22
- umap/static/umap/locale/br.json +48 -22
- umap/static/umap/locale/ca.js +52 -17
- umap/static/umap/locale/ca.json +52 -17
- umap/static/umap/locale/cs_CZ.js +52 -17
- umap/static/umap/locale/cs_CZ.json +52 -17
- umap/static/umap/locale/da.js +54 -17
- umap/static/umap/locale/da.json +54 -17
- umap/static/umap/locale/de.js +51 -16
- umap/static/umap/locale/de.json +51 -16
- umap/static/umap/locale/el.js +52 -17
- umap/static/umap/locale/el.json +52 -17
- umap/static/umap/locale/en.js +53 -16
- umap/static/umap/locale/en.json +53 -16
- umap/static/umap/locale/en_US.json +52 -17
- umap/static/umap/locale/es.js +54 -17
- umap/static/umap/locale/es.json +54 -17
- umap/static/umap/locale/et.js +91 -56
- umap/static/umap/locale/et.json +91 -56
- umap/static/umap/locale/eu.js +84 -49
- umap/static/umap/locale/eu.json +84 -49
- umap/static/umap/locale/fa_IR.js +52 -17
- umap/static/umap/locale/fa_IR.json +52 -17
- umap/static/umap/locale/fi.js +52 -17
- umap/static/umap/locale/fi.json +52 -17
- umap/static/umap/locale/fr.js +53 -16
- umap/static/umap/locale/fr.json +53 -16
- umap/static/umap/locale/gl.js +52 -17
- umap/static/umap/locale/gl.json +52 -17
- umap/static/umap/locale/he.js +52 -17
- umap/static/umap/locale/he.json +52 -17
- umap/static/umap/locale/hr.js +52 -17
- umap/static/umap/locale/hr.json +52 -17
- umap/static/umap/locale/hu.js +59 -24
- umap/static/umap/locale/hu.json +59 -24
- umap/static/umap/locale/id.js +52 -17
- umap/static/umap/locale/id.json +52 -17
- umap/static/umap/locale/is.js +52 -17
- umap/static/umap/locale/is.json +52 -17
- umap/static/umap/locale/it.js +52 -17
- umap/static/umap/locale/it.json +52 -17
- umap/static/umap/locale/ja.js +52 -17
- umap/static/umap/locale/ja.json +52 -17
- umap/static/umap/locale/ko.js +52 -17
- umap/static/umap/locale/ko.json +52 -17
- umap/static/umap/locale/lt.js +52 -17
- umap/static/umap/locale/lt.json +52 -17
- umap/static/umap/locale/ms.js +52 -17
- umap/static/umap/locale/ms.json +52 -17
- umap/static/umap/locale/nl.js +52 -17
- umap/static/umap/locale/nl.json +52 -17
- umap/static/umap/locale/no.js +52 -17
- umap/static/umap/locale/no.json +52 -17
- umap/static/umap/locale/pl.js +53 -17
- umap/static/umap/locale/pl.json +53 -17
- umap/static/umap/locale/pl_PL.json +52 -17
- umap/static/umap/locale/pt.js +52 -17
- umap/static/umap/locale/pt.json +52 -17
- umap/static/umap/locale/pt_BR.js +52 -17
- umap/static/umap/locale/pt_BR.json +52 -17
- umap/static/umap/locale/pt_PT.js +52 -17
- umap/static/umap/locale/pt_PT.json +52 -17
- umap/static/umap/locale/ro.js +52 -17
- umap/static/umap/locale/ro.json +52 -17
- umap/static/umap/locale/ru.js +52 -17
- umap/static/umap/locale/ru.json +52 -17
- umap/static/umap/locale/si.js +1 -1
- umap/static/umap/locale/si.json +1 -1
- umap/static/umap/locale/sk_SK.js +52 -17
- umap/static/umap/locale/sk_SK.json +52 -17
- umap/static/umap/locale/sl.js +52 -17
- umap/static/umap/locale/sl.json +52 -17
- umap/static/umap/locale/sr.js +52 -17
- umap/static/umap/locale/sr.json +52 -17
- umap/static/umap/locale/sv.js +52 -17
- umap/static/umap/locale/sv.json +52 -17
- umap/static/umap/locale/th_TH.js +52 -17
- umap/static/umap/locale/th_TH.json +52 -17
- umap/static/umap/locale/tr.js +52 -17
- umap/static/umap/locale/tr.json +52 -17
- umap/static/umap/locale/uk_UA.js +52 -17
- umap/static/umap/locale/uk_UA.json +52 -17
- umap/static/umap/locale/vi.js +52 -17
- umap/static/umap/locale/vi.json +52 -17
- umap/static/umap/locale/vi_VN.json +52 -17
- umap/static/umap/locale/zh.js +52 -17
- umap/static/umap/locale/zh.json +52 -17
- umap/static/umap/locale/zh_CN.json +52 -17
- umap/static/umap/locale/zh_TW.Big5.json +52 -17
- umap/static/umap/locale/zh_TW.js +52 -16
- umap/static/umap/locale/zh_TW.json +52 -16
- umap/static/umap/map.css +63 -226
- umap/static/umap/unittests/utils.js +18 -0
- umap/static/umap/vars.css +23 -5
- umap/templates/umap/components/alerts/alert.html +32 -29
- umap/templates/umap/css.html +2 -1
- umap/templates/umap/login_popup_end.html +18 -9
- umap/templates/umap/user_map_table.html +7 -2
- umap/tests/integration/conftest.py +10 -6
- umap/tests/integration/test_anonymous_owned_map.py +90 -37
- umap/tests/integration/test_basics.py +25 -1
- umap/tests/integration/test_browser.py +37 -0
- umap/tests/integration/test_conditional_rules.py +107 -52
- umap/tests/integration/test_draw_polygon.py +6 -0
- umap/tests/integration/test_draw_polyline.py +11 -0
- umap/tests/integration/test_edit_marker.py +1 -1
- umap/tests/integration/test_export_map.py +19 -0
- umap/tests/integration/test_fields.py +541 -0
- umap/tests/integration/test_filters.py +616 -0
- umap/tests/integration/test_iframe.py +1 -1
- umap/tests/integration/test_import.py +38 -42
- umap/tests/integration/test_map_preview.py +1 -1
- umap/tests/integration/test_picto.py +1 -1
- umap/tests/integration/test_popup.py +31 -0
- umap/tests/integration/test_remote_data.py +60 -4
- umap/tests/integration/test_save.py +1 -1
- umap/tests/integration/test_share.py +4 -4
- umap/tests/integration/test_tableeditor.py +31 -7
- umap/tests/integration/test_websocket_sync.py +71 -20
- umap/tests/test_dashboard.py +11 -1
- umap/tests/test_statics.py +2 -2
- umap/tests/test_utils.py +19 -2
- umap/tests/test_views.py +1 -1
- umap/urls.py +1 -0
- umap/utils.py +8 -1
- umap/views.py +5 -0
- {umap_project-3.3.6.dist-info → umap_project-3.4.0.dist-info}/METADATA +15 -15
- {umap_project-3.3.6.dist-info → umap_project-3.4.0.dist-info}/RECORD +237 -233
- umap/static/umap/js/modules/facets.js +0 -164
- umap/tests/integration/test_facets_browser.py +0 -279
- {umap_project-3.3.6.dist-info → umap_project-3.4.0.dist-info}/WHEEL +0 -0
- {umap_project-3.3.6.dist-info → umap_project-3.4.0.dist-info}/entry_points.txt +0 -0
- {umap_project-3.3.6.dist-info → umap_project-3.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,7 +7,7 @@ export class Panel {
|
|
|
7
7
|
this._umap = umap
|
|
8
8
|
this._leafletMap = leafletMap
|
|
9
9
|
this.container = DomUtil.create('div', '', this.parent)
|
|
10
|
-
// This will be set once according to the panel
|
|
10
|
+
// This will be set once according to the panel configured at load
|
|
11
11
|
// or by using panels as popups
|
|
12
12
|
this.mode = null
|
|
13
13
|
this.className = 'left'
|
|
@@ -26,12 +26,12 @@ export class Panel {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
open({ content, className, highlight, actions = [] } = {}) {
|
|
29
|
+
let isOpen = false
|
|
29
30
|
if (this.isOpen()) {
|
|
31
|
+
isOpen = true
|
|
30
32
|
this.onClose()
|
|
31
33
|
}
|
|
32
|
-
this.container.className = `with-transition panel window ${this.className} ${
|
|
33
|
-
this.mode || ''
|
|
34
|
-
}`
|
|
34
|
+
this.container.className = `with-transition panel window ${this.className} ${this.mode || ''} ${isOpen ? 'on' : ''}`
|
|
35
35
|
if (highlight) {
|
|
36
36
|
this.container.dataset.highlight = highlight
|
|
37
37
|
}
|
|
@@ -56,8 +56,22 @@ export class Panel {
|
|
|
56
56
|
}
|
|
57
57
|
if (className) DomUtil.addClass(body, className)
|
|
58
58
|
const promise = new Promise((resolve, reject) => {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
if (isOpen) {
|
|
60
|
+
resolve(this)
|
|
61
|
+
} else {
|
|
62
|
+
this.container.classList.add('on')
|
|
63
|
+
Promise.all(
|
|
64
|
+
this.container.getAnimations?.().map((animation) => animation.finished)
|
|
65
|
+
)
|
|
66
|
+
.then(() => {
|
|
67
|
+
resolve(this)
|
|
68
|
+
})
|
|
69
|
+
.catch(() => {
|
|
70
|
+
// Panel has been removed, so the DOM has changed, so the animations
|
|
71
|
+
// were cancelled, we want the new panel callback to be called anyway.
|
|
72
|
+
resolve(this)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
61
75
|
})
|
|
62
76
|
DomEvent.on(closeButton, 'click', this.close, this)
|
|
63
77
|
DomEvent.on(resizeButton, 'click', this.resize, this)
|
|
@@ -83,11 +97,12 @@ export class Panel {
|
|
|
83
97
|
}
|
|
84
98
|
|
|
85
99
|
onClose() {
|
|
86
|
-
if (
|
|
87
|
-
|
|
100
|
+
if (this.container.classList.contains('on')) {
|
|
101
|
+
this.container.classList.remove('on')
|
|
88
102
|
this._leafletMap.invalidateSize({ pan: false })
|
|
89
103
|
}
|
|
90
104
|
}
|
|
105
|
+
|
|
91
106
|
scrollTo(selector) {
|
|
92
107
|
const fieldset = this.container.querySelector(selector)
|
|
93
108
|
if (!fieldset) return
|
|
@@ -4,11 +4,10 @@ import * as Utils from '../utils.js'
|
|
|
4
4
|
import { Positioned } from './base.js'
|
|
5
5
|
|
|
6
6
|
export default class Tooltip extends Positioned {
|
|
7
|
-
constructor(
|
|
7
|
+
constructor() {
|
|
8
8
|
super()
|
|
9
|
-
this.parent =
|
|
9
|
+
this.parent = document.body
|
|
10
10
|
this.container = Utils.loadTemplate('<div class="umap-tooltip-container"></div>')
|
|
11
|
-
this.parent.appendChild(this.container)
|
|
12
11
|
DomEvent.disableClickPropagation(this.container)
|
|
13
12
|
this.container.addEventListener('contextmenu', (event) => event.stopPropagation()) // Do not activate our custom context menu.
|
|
14
13
|
this.container.addEventListener('wheel', (event) => event.stopPropagation())
|
|
@@ -25,7 +24,7 @@ export default class Tooltip extends Positioned {
|
|
|
25
24
|
} else {
|
|
26
25
|
this.container.innerHTML = Utils.escapeHTML(opts.content)
|
|
27
26
|
}
|
|
28
|
-
this.parent.
|
|
27
|
+
this.parent.appendChild(this.container)
|
|
29
28
|
this.openAt(opts)
|
|
30
29
|
}
|
|
31
30
|
this.TOOLTIP_ID = window.setTimeout(L.bind(showIt, this), opts.delay || 0)
|
|
@@ -49,6 +48,8 @@ export default class Tooltip extends Positioned {
|
|
|
49
48
|
this.toggleClassPosition()
|
|
50
49
|
this.container.innerHTML = ''
|
|
51
50
|
this.setPosition({})
|
|
52
|
-
this.parent.
|
|
51
|
+
if (this.parent.contains(this.container)) {
|
|
52
|
+
this.parent.removeChild(this.container)
|
|
53
|
+
}
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
import Browser from './browser.js'
|
|
11
11
|
import Caption from './caption.js'
|
|
12
12
|
import { DataLayer } from './data/layer.js'
|
|
13
|
-
import
|
|
13
|
+
import { Fields } from './data/fields.js'
|
|
14
|
+
import { Filters, migrateLegacyFilters } from './filters.js'
|
|
14
15
|
import { MutatingForm } from './form/builder.js'
|
|
15
16
|
import { Formatter } from './formatter.js'
|
|
16
17
|
import Help from './help.js'
|
|
@@ -32,6 +33,7 @@ import { EditPanel, FullPanel, Panel } from './ui/panel.js'
|
|
|
32
33
|
import Tooltip from './ui/tooltip.js'
|
|
33
34
|
import URLs from './urls.js'
|
|
34
35
|
import * as Utils from './utils.js'
|
|
36
|
+
import * as DOMUtils from './domutils.js'
|
|
35
37
|
import { DataLayerManager } from './managers.js'
|
|
36
38
|
import { Importer as OpenRouteService } from './importers/openrouteservice.js'
|
|
37
39
|
|
|
@@ -48,6 +50,7 @@ export default class Umap {
|
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
async init(element, geojson) {
|
|
53
|
+
this.migrateLegacyProperties(geojson.properties)
|
|
51
54
|
this.properties = Object.assign(
|
|
52
55
|
{
|
|
53
56
|
enableMarkerDraw: true,
|
|
@@ -131,7 +134,8 @@ export default class Umap {
|
|
|
131
134
|
this.contextmenu = new ContextMenu()
|
|
132
135
|
this.server = new ServerRequest()
|
|
133
136
|
this.request = new Request()
|
|
134
|
-
this.
|
|
137
|
+
this.fields = new Fields(this, this.dialog)
|
|
138
|
+
this.filters = new Filters(this, this)
|
|
135
139
|
this.browser = new Browser(this, this._leafletMap)
|
|
136
140
|
this.caption = new Caption(this, this._leafletMap)
|
|
137
141
|
this.importer = new Importer(this)
|
|
@@ -160,10 +164,6 @@ export default class Umap {
|
|
|
160
164
|
) {
|
|
161
165
|
this.properties.slideshow.active = true
|
|
162
166
|
}
|
|
163
|
-
if (this.properties.advancedFilterKey) {
|
|
164
|
-
this.properties.facetKey = this.properties.advancedFilterKey
|
|
165
|
-
delete this.properties.advancedFilterKey
|
|
166
|
-
}
|
|
167
167
|
|
|
168
168
|
// Global storage for retrieving datalayers and features.
|
|
169
169
|
this.datalayers = new DataLayerManager()
|
|
@@ -261,17 +261,6 @@ export default class Umap {
|
|
|
261
261
|
return window.self !== window.top
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
get fields() {
|
|
265
|
-
if (!this.properties.fields) this.properties.fields = []
|
|
266
|
-
return this.properties.fields
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
get fieldKeys() {
|
|
270
|
-
return this.fields
|
|
271
|
-
.map((field) => field.key)
|
|
272
|
-
.concat(...this.datalayers.active().map((dl) => dl.fieldKeys))
|
|
273
|
-
}
|
|
274
|
-
|
|
275
264
|
setPropertiesFromQueryString() {
|
|
276
265
|
const asBoolean = (key) => {
|
|
277
266
|
const value = this.searchParams.get(key)
|
|
@@ -391,6 +380,17 @@ export default class Umap {
|
|
|
391
380
|
}
|
|
392
381
|
}
|
|
393
382
|
|
|
383
|
+
hasFilters() {
|
|
384
|
+
return this.filters.size || this.datalayers.active().some((d) => d.filters.size)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
hasActiveFilters() {
|
|
388
|
+
return (
|
|
389
|
+
this.filters.isActive() ||
|
|
390
|
+
this.datalayers.active().some((d) => d.filters.isActive())
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
394
|
getOwnContextMenu(event) {
|
|
395
395
|
const items = []
|
|
396
396
|
if (this.editEnabled) {
|
|
@@ -424,7 +424,7 @@ export default class Umap {
|
|
|
424
424
|
action: () => this.openBrowser('data'),
|
|
425
425
|
}
|
|
426
426
|
)
|
|
427
|
-
if (this.
|
|
427
|
+
if (this.hasFilters()) {
|
|
428
428
|
items.push({
|
|
429
429
|
label: translate('Filter data'),
|
|
430
430
|
action: () => this.openBrowser('filters'),
|
|
@@ -444,7 +444,13 @@ export default class Umap {
|
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
getSharedContextMenu(event) {
|
|
447
|
-
const
|
|
447
|
+
const latlng = `${event.latlng.lat.toFixed(6)},${event.latlng.lng.toFixed(6)}`
|
|
448
|
+
const items = [
|
|
449
|
+
{
|
|
450
|
+
label: latlng,
|
|
451
|
+
action: () => DOMUtils.copyToClipboard(latlng),
|
|
452
|
+
},
|
|
453
|
+
]
|
|
448
454
|
if (this.properties.urls.routing) {
|
|
449
455
|
items.push({
|
|
450
456
|
label: translate('Directions from here'),
|
|
@@ -481,7 +487,7 @@ export default class Umap {
|
|
|
481
487
|
}
|
|
482
488
|
|
|
483
489
|
search() {
|
|
484
|
-
if (this._leafletMap._controls.search) this._leafletMap._controls.search.
|
|
490
|
+
if (this._leafletMap._controls.search) this._leafletMap._controls.search.onClick()
|
|
485
491
|
}
|
|
486
492
|
|
|
487
493
|
hasEditMode() {
|
|
@@ -666,7 +672,7 @@ export default class Umap {
|
|
|
666
672
|
const parent = this._leafletMap.getPane('overlayPane')
|
|
667
673
|
const datalayers = Object.values(this.datalayers)
|
|
668
674
|
.filter((datalayer) => !datalayer._isDeleted)
|
|
669
|
-
.sort((datalayer1, datalayer2) => datalayer1.rank
|
|
675
|
+
.sort((datalayer1, datalayer2) => datalayer1.rank - datalayer2.rank)
|
|
670
676
|
for (const datalayer of datalayers) {
|
|
671
677
|
const child = parent.querySelector(`[data-id="${datalayer.id}"]`)
|
|
672
678
|
parent.appendChild(child)
|
|
@@ -720,7 +726,14 @@ export default class Umap {
|
|
|
720
726
|
return this.properties.name || translate('Untitled map')
|
|
721
727
|
}
|
|
722
728
|
|
|
729
|
+
migrateLegacyProperties(properties) {
|
|
730
|
+
if (migrateLegacyFilters(properties)) {
|
|
731
|
+
this._migrated = true
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
723
735
|
setProperties(newProperties) {
|
|
736
|
+
this.migrateLegacyProperties(newProperties)
|
|
724
737
|
for (const key of Object.keys(SCHEMA)) {
|
|
725
738
|
if (newProperties[key] !== undefined) {
|
|
726
739
|
this.properties[key] = newProperties[key]
|
|
@@ -758,7 +771,7 @@ export default class Umap {
|
|
|
758
771
|
'properties.is_template',
|
|
759
772
|
]
|
|
760
773
|
|
|
761
|
-
DomUtil.createTitle(container, translate('Edit map details'), 'icon-
|
|
774
|
+
DomUtil.createTitle(container, translate('Edit map details'), 'icon-info')
|
|
762
775
|
const builder = new MutatingForm(this, metadataFields, {
|
|
763
776
|
className: 'map-metadata',
|
|
764
777
|
umap: this,
|
|
@@ -868,23 +881,22 @@ export default class Umap {
|
|
|
868
881
|
defaultShapeProperties.appendChild(builder.build())
|
|
869
882
|
}
|
|
870
883
|
|
|
871
|
-
|
|
872
|
-
const
|
|
884
|
+
_editDefaultKeys(container) {
|
|
885
|
+
const shapeOptions = [
|
|
873
886
|
'properties.zoomTo',
|
|
874
887
|
'properties.easing',
|
|
875
888
|
'properties.labelKey',
|
|
876
889
|
'properties.sortKey',
|
|
877
890
|
'properties.filterKey',
|
|
878
|
-
'properties.facetKey',
|
|
879
891
|
'properties.slugKey',
|
|
880
892
|
]
|
|
881
893
|
|
|
882
|
-
const builder = new MutatingForm(this,
|
|
883
|
-
const
|
|
894
|
+
const builder = new MutatingForm(this, shapeOptions, { umap: this })
|
|
895
|
+
const defaultShapeProperties = DomUtil.createFieldset(
|
|
884
896
|
container,
|
|
885
897
|
translate('Default properties')
|
|
886
898
|
)
|
|
887
|
-
|
|
899
|
+
defaultShapeProperties.appendChild(builder.build())
|
|
888
900
|
}
|
|
889
901
|
|
|
890
902
|
_editInteractionsProperties(container) {
|
|
@@ -1159,7 +1171,8 @@ export default class Umap {
|
|
|
1159
1171
|
)
|
|
1160
1172
|
this._editControls(container)
|
|
1161
1173
|
this._editShapeProperties(container)
|
|
1162
|
-
this.
|
|
1174
|
+
this._editDefaultKeys(container)
|
|
1175
|
+
this.fields.edit(container)
|
|
1163
1176
|
this._editInteractionsProperties(container)
|
|
1164
1177
|
this.rules.edit(container)
|
|
1165
1178
|
this._editTilelayer(container)
|
|
@@ -1178,6 +1191,16 @@ export default class Umap {
|
|
|
1178
1191
|
})
|
|
1179
1192
|
}
|
|
1180
1193
|
|
|
1194
|
+
onAnonymousSave(editUrl) {
|
|
1195
|
+
AlertCreation.info(
|
|
1196
|
+
this,
|
|
1197
|
+
translate('Hey, you created a map without an account!'),
|
|
1198
|
+
Number.Infinity,
|
|
1199
|
+
editUrl,
|
|
1200
|
+
this.properties.urls.map_send_edit_link ? this.sendEditLinkEmail.bind(this) : null
|
|
1201
|
+
)
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1181
1204
|
async save() {
|
|
1182
1205
|
const geojson = {
|
|
1183
1206
|
type: 'Feature',
|
|
@@ -1197,11 +1220,10 @@ export default class Umap {
|
|
|
1197
1220
|
if (error) {
|
|
1198
1221
|
return
|
|
1199
1222
|
}
|
|
1200
|
-
//
|
|
1223
|
+
// TODO: map.save may not always be the first call during save process
|
|
1201
1224
|
// since SAVEMANAGER refactor
|
|
1202
1225
|
if (data.login_required) {
|
|
1203
|
-
|
|
1204
|
-
window.open(data.login_required)
|
|
1226
|
+
this.askForLogin().then(() => this.saveAll())
|
|
1205
1227
|
return
|
|
1206
1228
|
}
|
|
1207
1229
|
this.properties.user = data.user
|
|
@@ -1209,17 +1231,9 @@ export default class Umap {
|
|
|
1209
1231
|
this.properties.id = data.id
|
|
1210
1232
|
this.permissions.setProperties(data.permissions)
|
|
1211
1233
|
this.permissions.commit()
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
translate('Your map has been created with an anonymous account!'),
|
|
1216
|
-
Number.Infinity,
|
|
1217
|
-
data.permissions.anonymous_edit_url,
|
|
1218
|
-
this.properties.urls.map_send_edit_link
|
|
1219
|
-
? this.sendEditLinkEmail.bind(this)
|
|
1220
|
-
: null
|
|
1221
|
-
)
|
|
1222
|
-
})
|
|
1234
|
+
const anonymousEditUrl = data.permissions?.anonymous_edit_url
|
|
1235
|
+
if (anonymousEditUrl) {
|
|
1236
|
+
this._leafletMap.once('saved', () => this.onAnonymousSave(anonymousEditUrl))
|
|
1223
1237
|
} else {
|
|
1224
1238
|
this._leafletMap.once('saved', () => {
|
|
1225
1239
|
Alert.success(translate('Congratulations, your map has been created!'))
|
|
@@ -1241,6 +1255,29 @@ export default class Umap {
|
|
|
1241
1255
|
return true
|
|
1242
1256
|
}
|
|
1243
1257
|
|
|
1258
|
+
askForLogin() {
|
|
1259
|
+
const promise = new Promise((resolve) => {
|
|
1260
|
+
const bc = new BroadcastChannel('auth')
|
|
1261
|
+
bc.onmessage = (event) => {
|
|
1262
|
+
if (event.data === 'auth:ok') {
|
|
1263
|
+
bc.postMessage('auth:close')
|
|
1264
|
+
const url = this.urls.get('whoami', { map_id: this.id })
|
|
1265
|
+
this.server.get(url).then(([data]) => {
|
|
1266
|
+
this.properties.user = data.user
|
|
1267
|
+
if (!this.id) {
|
|
1268
|
+
this.properties.permissions.owner = { ...data.user }
|
|
1269
|
+
}
|
|
1270
|
+
this.permissions.pull()
|
|
1271
|
+
this.render(['user', 'properties.permissions'])
|
|
1272
|
+
resolve()
|
|
1273
|
+
})
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
})
|
|
1277
|
+
window.open(this.urls.get('login'))
|
|
1278
|
+
return promise
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1244
1281
|
exportProperties() {
|
|
1245
1282
|
const properties = {}
|
|
1246
1283
|
for (const key of Object.keys(SCHEMA)) {
|
|
@@ -1251,6 +1288,18 @@ export default class Umap {
|
|
|
1251
1288
|
return properties
|
|
1252
1289
|
}
|
|
1253
1290
|
|
|
1291
|
+
renameField(oldName, newName) {
|
|
1292
|
+
for (const datalayer of this.datalayers.active()) {
|
|
1293
|
+
datalayer.renameFeaturesField(oldName, newName)
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
deleteField(name) {
|
|
1298
|
+
for (const datalayer of this.datalayers.active()) {
|
|
1299
|
+
datalayer.deleteFeaturesField(name)
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1254
1303
|
geometry() {
|
|
1255
1304
|
/* Return a GeoJSON geometry Object */
|
|
1256
1305
|
const latlng = this._leafletMap.latLng(
|
|
@@ -1269,18 +1318,51 @@ export default class Umap {
|
|
|
1269
1318
|
this.drop.enable()
|
|
1270
1319
|
this.fire('edit:enabled')
|
|
1271
1320
|
this.initSyncEngine()
|
|
1272
|
-
this.
|
|
1273
|
-
|
|
1274
|
-
|
|
1321
|
+
this.checkForLegacy()
|
|
1322
|
+
this.checkForAnonymous()
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
checkForAnonymous() {
|
|
1326
|
+
if (
|
|
1327
|
+
this.permissions.isAnonymousMap() &&
|
|
1328
|
+
this.permissions.isOwner() &&
|
|
1329
|
+
this.permissions.userIsAuth()
|
|
1330
|
+
) {
|
|
1331
|
+
this.dialog
|
|
1332
|
+
.confirm(
|
|
1333
|
+
translate('This map is anonymous, do you want to attach it to your account?')
|
|
1334
|
+
)
|
|
1335
|
+
.then(() => {
|
|
1336
|
+
this.permissions.attach()
|
|
1337
|
+
})
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
checkForLegacy() {
|
|
1342
|
+
let needSaveAlert = false
|
|
1343
|
+
if (this._migrated) {
|
|
1344
|
+
needSaveAlert = true
|
|
1345
|
+
delete this._migrated
|
|
1346
|
+
// Force user to save
|
|
1347
|
+
this.sync.update('properties.name', this.properties.name, this.properties.name)
|
|
1348
|
+
}
|
|
1349
|
+
for (const datalayer of this.datalayers.active()) {
|
|
1350
|
+
if (!datalayer.isReadOnly() && datalayer._migrated) {
|
|
1351
|
+
datalayer._migrated = false
|
|
1275
1352
|
// Force user to resave those datalayers
|
|
1276
1353
|
datalayer.sync.update(
|
|
1277
1354
|
'properties.name',
|
|
1278
1355
|
datalayer.properties.name,
|
|
1279
1356
|
datalayer.properties.name
|
|
1280
1357
|
)
|
|
1281
|
-
|
|
1358
|
+
needSaveAlert = true
|
|
1282
1359
|
}
|
|
1283
|
-
}
|
|
1360
|
+
}
|
|
1361
|
+
if (needSaveAlert) {
|
|
1362
|
+
Alert.warning(
|
|
1363
|
+
translate('The map has been upgraded to latest version, please save it.')
|
|
1364
|
+
)
|
|
1365
|
+
}
|
|
1284
1366
|
}
|
|
1285
1367
|
|
|
1286
1368
|
disableEdit() {
|
|
@@ -1324,6 +1406,12 @@ export default class Umap {
|
|
|
1324
1406
|
// Propagate will remove the fields it has already
|
|
1325
1407
|
// processed
|
|
1326
1408
|
fields = this.propagate(fields)
|
|
1409
|
+
if (fields.includes('properties.filters')) {
|
|
1410
|
+
this.filters.load()
|
|
1411
|
+
if (this.browser.isOpen()) {
|
|
1412
|
+
this.browser.buildFilters()
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1327
1415
|
|
|
1328
1416
|
const impacts = Utils.getImpactsFromSchema(fields)
|
|
1329
1417
|
for (const impact of impacts) {
|
|
@@ -1365,7 +1453,7 @@ export default class Umap {
|
|
|
1365
1453
|
}
|
|
1366
1454
|
|
|
1367
1455
|
// This method does a targeted update of the UI,
|
|
1368
|
-
// it
|
|
1456
|
+
// it would be merged with `render`` method and the
|
|
1369
1457
|
// SCHEMA at some point
|
|
1370
1458
|
propagate(fields = []) {
|
|
1371
1459
|
const impacts = {
|
|
@@ -1376,7 +1464,7 @@ export default class Umap {
|
|
|
1376
1464
|
},
|
|
1377
1465
|
user: () => {
|
|
1378
1466
|
Utils.eachElement('.umap-user .username', (el) => {
|
|
1379
|
-
if (this.
|
|
1467
|
+
if (this.permissions.userIsAuth()) {
|
|
1380
1468
|
el.textContent = this.properties.user.name
|
|
1381
1469
|
}
|
|
1382
1470
|
})
|
|
@@ -1483,17 +1571,22 @@ export default class Umap {
|
|
|
1483
1571
|
`
|
|
1484
1572
|
const [container, { ul }] = Utils.loadTemplateWithRefs(template)
|
|
1485
1573
|
this.datalayers.reverse().map((datalayer) => {
|
|
1486
|
-
const row = Utils.
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1574
|
+
const [row, { toolbox, formbox }] = Utils.loadTemplateWithRefs(`
|
|
1575
|
+
<li class="orderable with-toolbox ${datalayer.cssId}">
|
|
1576
|
+
<span data-ref=formbox class="datalayer-editable-title truncate"></span>
|
|
1577
|
+
<span data-ref=toolbox>
|
|
1578
|
+
<i class="icon icon-16 icon-drag" title="${translate('Drag to reorder')}"></i>
|
|
1579
|
+
</span>
|
|
1580
|
+
</li>
|
|
1581
|
+
`)
|
|
1582
|
+
datalayer.renderToolbox(toolbox)
|
|
1490
1583
|
const builder = new MutatingForm(
|
|
1491
1584
|
datalayer,
|
|
1492
1585
|
[['properties.name', { handler: 'EditableText' }]],
|
|
1493
1586
|
{ className: 'umap-form-inline' }
|
|
1494
1587
|
)
|
|
1495
1588
|
const form = builder.build()
|
|
1496
|
-
|
|
1589
|
+
formbox.appendChild(form)
|
|
1497
1590
|
row.classList.toggle('off', !datalayer.isVisible())
|
|
1498
1591
|
row.dataset.id = datalayer.id
|
|
1499
1592
|
ul.appendChild(row)
|
|
@@ -1636,6 +1729,8 @@ export default class Umap {
|
|
|
1636
1729
|
const fields = Object.keys(importedData.properties).map(
|
|
1637
1730
|
(field) => `properties.${field}`
|
|
1638
1731
|
)
|
|
1732
|
+
this.fields.pull()
|
|
1733
|
+
this.filters.load()
|
|
1639
1734
|
this.render(fields)
|
|
1640
1735
|
this._leafletMap._setDefaultCenter()
|
|
1641
1736
|
}
|
|
@@ -1649,7 +1744,7 @@ export default class Umap {
|
|
|
1649
1744
|
this.importRaw(rawData)
|
|
1650
1745
|
} catch (e) {
|
|
1651
1746
|
console.error('Error importing data', e)
|
|
1652
|
-
|
|
1747
|
+
Alert.error(
|
|
1653
1748
|
translate('Invalid umap data in {filename}', { filename: file.name })
|
|
1654
1749
|
)
|
|
1655
1750
|
}
|
|
@@ -40,7 +40,7 @@ function _getPropertyName(field) {
|
|
|
40
40
|
* Return an array of unique impacts.
|
|
41
41
|
*
|
|
42
42
|
* @param {fields} list[fields]
|
|
43
|
-
* @param object schema object. If
|
|
43
|
+
* @param object schema object. If omitted, global U.SCHEMA will be used.
|
|
44
44
|
* @returns Array[string]
|
|
45
45
|
*/
|
|
46
46
|
export function getImpactsFromSchema(fields, schema) {
|
|
@@ -400,8 +400,30 @@ export function template(str, data) {
|
|
|
400
400
|
})
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
+
const DATE_REGEX = [
|
|
404
|
+
// Format 1: "YYYY-MM-DD"
|
|
405
|
+
/^(?<year>\d{4})[\-\/](?<month>\d{2})[\-\/](?<day>\d{2})$/,
|
|
406
|
+
// Format2 : "DD-MM-YYYY"
|
|
407
|
+
/^(?<day>0[1-9]|[12][0-9]|3[01])[\-\/](?<month>0[1-9]|1[0-2])[\-\/](?<year>\d{4})/,
|
|
408
|
+
]
|
|
409
|
+
|
|
403
410
|
export function parseNaiveDate(value) {
|
|
404
|
-
|
|
411
|
+
let naive
|
|
412
|
+
if (!value) return undefined
|
|
413
|
+
value = String(value)
|
|
414
|
+
for (const regex of DATE_REGEX) {
|
|
415
|
+
const parsed = value.match(regex)
|
|
416
|
+
if (parsed) {
|
|
417
|
+
const { year, month, day } = parsed.groups
|
|
418
|
+
naive = new Date(year, Number.parseInt(month, 10) - 1, Number.parseInt(day, 10))
|
|
419
|
+
break
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (!naive) {
|
|
423
|
+
naive = new Date(value)
|
|
424
|
+
}
|
|
425
|
+
// Number.isNaN will always return false for invalid date
|
|
426
|
+
if (isNaN(naive)) return undefined
|
|
405
427
|
// Let's pretend naive date are UTC, and remove time…
|
|
406
428
|
return new Date(Date.UTC(naive.getFullYear(), naive.getMonth(), naive.getDate()))
|
|
407
429
|
}
|
umap/static/umap/js/umap.core.js
CHANGED
|
@@ -1,30 +1,3 @@
|
|
|
1
|
-
L.Util.copyToClipboard = (textToCopy) => {
|
|
2
|
-
// https://stackoverflow.com/a/65996386
|
|
3
|
-
// Navigator clipboard api needs a secure context (https)
|
|
4
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
5
|
-
navigator.clipboard.writeText(textToCopy)
|
|
6
|
-
} else {
|
|
7
|
-
// Use the 'out of viewport hidden text area' trick
|
|
8
|
-
const textArea = document.createElement('textarea')
|
|
9
|
-
textArea.value = textToCopy
|
|
10
|
-
|
|
11
|
-
// Move textarea out of the viewport so it's not visible
|
|
12
|
-
textArea.style.position = 'absolute'
|
|
13
|
-
textArea.style.left = '-999999px'
|
|
14
|
-
|
|
15
|
-
document.body.prepend(textArea)
|
|
16
|
-
textArea.select()
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
document.execCommand('copy')
|
|
20
|
-
} catch (error) {
|
|
21
|
-
console.error(error)
|
|
22
|
-
} finally {
|
|
23
|
-
textArea.remove()
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
1
|
L.DomUtil.add = (tagName, className, container, content) => {
|
|
29
2
|
const el = L.DomUtil.create(tagName, className, container)
|
|
30
3
|
if (content) {
|
|
@@ -42,7 +15,7 @@ L.DomUtil.createFieldset = (container, legend, options) => {
|
|
|
42
15
|
const details = L.DomUtil.create('details', options.className || '', container)
|
|
43
16
|
const summary = L.DomUtil.add('summary', '', details)
|
|
44
17
|
if (options.icon) L.DomUtil.createIcon(summary, options.icon)
|
|
45
|
-
L.DomUtil.add('
|
|
18
|
+
L.DomUtil.add('h4', '', summary, legend)
|
|
46
19
|
const fieldset = L.DomUtil.add('fieldset', '', details)
|
|
47
20
|
details.open = options.on === true
|
|
48
21
|
if (options.callback) {
|
|
@@ -94,24 +67,6 @@ L.DomUtil.createTitle = (parent, text, iconClassName, className = '', tag = 'h3'
|
|
|
94
67
|
return title
|
|
95
68
|
}
|
|
96
69
|
|
|
97
|
-
L.DomUtil.createCopiableInput = (parent, label, value) => {
|
|
98
|
-
const wrapper = L.DomUtil.add('div', 'copiable-input', parent)
|
|
99
|
-
const labelEl = L.DomUtil.add('label', '', wrapper, label)
|
|
100
|
-
const input = L.DomUtil.add('input', '', labelEl)
|
|
101
|
-
input.type = 'text'
|
|
102
|
-
input.readOnly = true
|
|
103
|
-
input.value = value
|
|
104
|
-
const button = L.DomUtil.createButtonIcon(
|
|
105
|
-
wrapper,
|
|
106
|
-
'icon-copy',
|
|
107
|
-
L._('copy'),
|
|
108
|
-
() => L.Util.copyToClipboard(input.value),
|
|
109
|
-
24
|
|
110
|
-
)
|
|
111
|
-
button.type = 'button'
|
|
112
|
-
return input
|
|
113
|
-
}
|
|
114
|
-
|
|
115
70
|
L.DomUtil.element = ({ tagName, parent, ...attrs }) => {
|
|
116
71
|
const el = document.createElement(tagName)
|
|
117
72
|
if (attrs.innerHTML) {
|
|
@@ -128,70 +83,6 @@ L.DomUtil.element = ({ tagName, parent, ...attrs }) => {
|
|
|
128
83
|
return el
|
|
129
84
|
}
|
|
130
85
|
|
|
131
|
-
// From https://gist.github.com/Accudio/b9cb16e0e3df858cef0d31e38f1fe46f
|
|
132
|
-
// convert colour in range 0-255 to the modifier used within luminance calculation
|
|
133
|
-
L.DomUtil.colourMod = (colour) => {
|
|
134
|
-
const sRGB = colour / 255
|
|
135
|
-
let mod = ((sRGB + 0.055) / 1.055) ** 2.4
|
|
136
|
-
if (sRGB < 0.03928) mod = sRGB / 12.92
|
|
137
|
-
return mod
|
|
138
|
-
}
|
|
139
|
-
L.DomUtil.RGBRegex = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/
|
|
140
|
-
L.DomUtil.TextColorFromBackgroundColor = (el, bgcolor) => {
|
|
141
|
-
return L.DomUtil.contrastedColor(el, bgcolor) ? '#ffffff' : '#000000'
|
|
142
|
-
}
|
|
143
|
-
L.DomUtil.contrastWCAG21 = (rgb) => {
|
|
144
|
-
const [r, g, b] = rgb
|
|
145
|
-
// luminance of inputted colour
|
|
146
|
-
const lum =
|
|
147
|
-
0.2126 * L.DomUtil.colourMod(r) +
|
|
148
|
-
0.7152 * L.DomUtil.colourMod(g) +
|
|
149
|
-
0.0722 * L.DomUtil.colourMod(b)
|
|
150
|
-
// white has a luminance of 1
|
|
151
|
-
const whiteLum = 1
|
|
152
|
-
const contrast = (whiteLum + 0.05) / (lum + 0.05)
|
|
153
|
-
return contrast > 3 ? 1 : 0
|
|
154
|
-
}
|
|
155
|
-
L.DomUtil.colorNameToHex = (str) => {
|
|
156
|
-
const ctx = document.createElement('canvas').getContext('2d')
|
|
157
|
-
ctx.fillStyle = str
|
|
158
|
-
return ctx.fillStyle
|
|
159
|
-
}
|
|
160
|
-
L.DomUtil.hexToRGB = (hex) => {
|
|
161
|
-
return hex
|
|
162
|
-
.replace(
|
|
163
|
-
/^#?([a-f\d])([a-f\d])([a-f\d])$/i,
|
|
164
|
-
(m, r, g, b) => `#${r}${r}${g}${g}${b}${b}`
|
|
165
|
-
)
|
|
166
|
-
.substring(1)
|
|
167
|
-
.match(/.{2}/g)
|
|
168
|
-
.map((x) => Number.parseInt(x, 16))
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const _CACHE_CONSTRAST = {}
|
|
172
|
-
L.DomUtil.contrastedColor = (el, bgcolor) => {
|
|
173
|
-
// Return 0 for black and 1 for white
|
|
174
|
-
// bgcolor is a human color, it can be a any keyword (purple…)
|
|
175
|
-
if (typeof _CACHE_CONSTRAST[bgcolor] !== 'undefined') return _CACHE_CONSTRAST[bgcolor]
|
|
176
|
-
let rgb = window.getComputedStyle(el).getPropertyValue('background-color')
|
|
177
|
-
rgb = L.DomUtil.RGBRegex.exec(rgb)
|
|
178
|
-
if (rgb && rgb.length === 4) {
|
|
179
|
-
rgb = [
|
|
180
|
-
Number.parseInt(rgb[1], 10),
|
|
181
|
-
Number.parseInt(rgb[2], 10),
|
|
182
|
-
Number.parseInt(rgb[3], 10),
|
|
183
|
-
]
|
|
184
|
-
} else {
|
|
185
|
-
// The element may not yet be added to the DOM, so let's try
|
|
186
|
-
// another way
|
|
187
|
-
const hex = L.DomUtil.colorNameToHex(bgcolor)
|
|
188
|
-
rgb = L.DomUtil.hexToRGB(hex)
|
|
189
|
-
}
|
|
190
|
-
if (!rgb) return 1
|
|
191
|
-
const out = L.DomUtil.contrastWCAG21(rgb)
|
|
192
|
-
if (bgcolor) _CACHE_CONSTRAST[bgcolor] = out
|
|
193
|
-
return out
|
|
194
|
-
}
|
|
195
86
|
L.LatLng.prototype.isValid = function () {
|
|
196
87
|
return (
|
|
197
88
|
Number.isFinite(this.lat) &&
|