umap-project 2.4.2__py3-none-any.whl → 2.5.1__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.
Files changed (177) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/hu/LC_MESSAGES/django.po +100 -50
  6. umap/static/umap/base.css +4 -1
  7. umap/static/umap/css/contextmenu.css +11 -0
  8. umap/static/umap/css/dialog.css +24 -3
  9. umap/static/umap/css/panel.css +4 -2
  10. umap/static/umap/css/slideshow.css +69 -0
  11. umap/static/umap/css/tableeditor.css +69 -0
  12. umap/static/umap/css/tooltip.css +3 -3
  13. umap/static/umap/img/16-white.svg +4 -0
  14. umap/static/umap/img/source/16-white.svg +5 -1
  15. umap/static/umap/js/components/alerts/alert.css +10 -10
  16. umap/static/umap/js/modules/autocomplete.js +23 -1
  17. umap/static/umap/js/modules/browser.js +14 -8
  18. umap/static/umap/js/modules/facets.js +40 -10
  19. umap/static/umap/js/modules/formatter.js +153 -0
  20. umap/static/umap/js/modules/global.js +10 -1
  21. umap/static/umap/js/modules/help.js +25 -25
  22. umap/static/umap/js/modules/importer.js +4 -4
  23. umap/static/umap/js/modules/importers/communesfr.js +3 -1
  24. umap/static/umap/js/modules/importers/datasets.js +8 -6
  25. umap/static/umap/js/modules/importers/geodatamine.js +10 -10
  26. umap/static/umap/js/modules/importers/overpass.js +18 -14
  27. umap/static/umap/js/modules/rules.js +13 -1
  28. umap/static/umap/js/modules/schema.js +16 -12
  29. umap/static/umap/js/{umap.share.js → modules/share.js} +60 -99
  30. umap/static/umap/js/modules/slideshow.js +141 -0
  31. umap/static/umap/js/modules/tableeditor.js +329 -0
  32. umap/static/umap/js/modules/ui/base.js +93 -0
  33. umap/static/umap/js/modules/ui/contextmenu.js +50 -0
  34. umap/static/umap/js/modules/ui/dialog.js +169 -31
  35. umap/static/umap/js/modules/ui/panel.js +6 -4
  36. umap/static/umap/js/modules/ui/tooltip.js +5 -75
  37. umap/static/umap/js/modules/utils.js +20 -0
  38. umap/static/umap/js/umap.controls.js +1 -1
  39. umap/static/umap/js/umap.features.js +22 -14
  40. umap/static/umap/js/umap.forms.js +157 -154
  41. umap/static/umap/js/umap.js +48 -34
  42. umap/static/umap/js/umap.layer.js +232 -164
  43. umap/static/umap/js/umap.permissions.js +1 -1
  44. umap/static/umap/js/umap.popup.js +1 -1
  45. umap/static/umap/locale/am_ET.js +22 -5
  46. umap/static/umap/locale/am_ET.json +19 -5
  47. umap/static/umap/locale/ar.js +22 -5
  48. umap/static/umap/locale/ar.json +19 -5
  49. umap/static/umap/locale/ast.js +22 -5
  50. umap/static/umap/locale/ast.json +19 -5
  51. umap/static/umap/locale/bg.js +22 -5
  52. umap/static/umap/locale/bg.json +19 -5
  53. umap/static/umap/locale/br.js +22 -5
  54. umap/static/umap/locale/br.json +19 -5
  55. umap/static/umap/locale/ca.js +56 -39
  56. umap/static/umap/locale/ca.json +53 -39
  57. umap/static/umap/locale/cs_CZ.js +22 -5
  58. umap/static/umap/locale/cs_CZ.json +19 -5
  59. umap/static/umap/locale/da.js +22 -5
  60. umap/static/umap/locale/da.json +19 -5
  61. umap/static/umap/locale/de.js +22 -5
  62. umap/static/umap/locale/de.json +19 -5
  63. umap/static/umap/locale/el.js +27 -10
  64. umap/static/umap/locale/el.json +19 -5
  65. umap/static/umap/locale/en.js +22 -6
  66. umap/static/umap/locale/en.json +19 -5
  67. umap/static/umap/locale/en_US.json +19 -5
  68. umap/static/umap/locale/es.js +22 -6
  69. umap/static/umap/locale/es.json +19 -5
  70. umap/static/umap/locale/et.js +22 -5
  71. umap/static/umap/locale/et.json +19 -5
  72. umap/static/umap/locale/eu.js +167 -150
  73. umap/static/umap/locale/eu.json +167 -150
  74. umap/static/umap/locale/fa_IR.js +22 -5
  75. umap/static/umap/locale/fa_IR.json +19 -5
  76. umap/static/umap/locale/fi.js +22 -5
  77. umap/static/umap/locale/fi.json +19 -5
  78. umap/static/umap/locale/fr.js +22 -6
  79. umap/static/umap/locale/fr.json +19 -5
  80. umap/static/umap/locale/gl.js +22 -5
  81. umap/static/umap/locale/gl.json +19 -5
  82. umap/static/umap/locale/he.js +22 -5
  83. umap/static/umap/locale/he.json +19 -5
  84. umap/static/umap/locale/hr.js +22 -5
  85. umap/static/umap/locale/hr.json +19 -5
  86. umap/static/umap/locale/hu.js +89 -72
  87. umap/static/umap/locale/hu.json +89 -75
  88. umap/static/umap/locale/id.js +22 -5
  89. umap/static/umap/locale/id.json +19 -5
  90. umap/static/umap/locale/is.js +22 -5
  91. umap/static/umap/locale/is.json +19 -5
  92. umap/static/umap/locale/it.js +22 -5
  93. umap/static/umap/locale/it.json +19 -5
  94. umap/static/umap/locale/ja.js +22 -5
  95. umap/static/umap/locale/ja.json +19 -5
  96. umap/static/umap/locale/ko.js +22 -5
  97. umap/static/umap/locale/ko.json +19 -5
  98. umap/static/umap/locale/lt.js +22 -5
  99. umap/static/umap/locale/lt.json +19 -5
  100. umap/static/umap/locale/ms.js +22 -5
  101. umap/static/umap/locale/ms.json +19 -5
  102. umap/static/umap/locale/nl.js +22 -5
  103. umap/static/umap/locale/nl.json +19 -5
  104. umap/static/umap/locale/no.js +22 -5
  105. umap/static/umap/locale/no.json +19 -5
  106. umap/static/umap/locale/pl.js +22 -5
  107. umap/static/umap/locale/pl.json +19 -5
  108. umap/static/umap/locale/pl_PL.json +19 -5
  109. umap/static/umap/locale/pt.js +22 -6
  110. umap/static/umap/locale/pt.json +21 -7
  111. umap/static/umap/locale/pt_BR.js +22 -5
  112. umap/static/umap/locale/pt_BR.json +19 -5
  113. umap/static/umap/locale/pt_PT.js +22 -5
  114. umap/static/umap/locale/pt_PT.json +19 -5
  115. umap/static/umap/locale/ro.js +22 -5
  116. umap/static/umap/locale/ro.json +19 -5
  117. umap/static/umap/locale/ru.js +22 -5
  118. umap/static/umap/locale/ru.json +19 -5
  119. umap/static/umap/locale/sk_SK.js +22 -5
  120. umap/static/umap/locale/sk_SK.json +19 -5
  121. umap/static/umap/locale/sl.js +22 -5
  122. umap/static/umap/locale/sl.json +19 -5
  123. umap/static/umap/locale/sr.js +22 -5
  124. umap/static/umap/locale/sr.json +19 -5
  125. umap/static/umap/locale/sv.js +22 -5
  126. umap/static/umap/locale/sv.json +19 -5
  127. umap/static/umap/locale/th_TH.js +22 -5
  128. umap/static/umap/locale/th_TH.json +19 -5
  129. umap/static/umap/locale/tr.js +22 -5
  130. umap/static/umap/locale/tr.json +19 -5
  131. umap/static/umap/locale/uk_UA.js +22 -5
  132. umap/static/umap/locale/uk_UA.json +19 -5
  133. umap/static/umap/locale/vi.js +22 -5
  134. umap/static/umap/locale/vi.json +19 -5
  135. umap/static/umap/locale/vi_VN.json +19 -5
  136. umap/static/umap/locale/zh.js +22 -5
  137. umap/static/umap/locale/zh.json +19 -5
  138. umap/static/umap/locale/zh_CN.json +19 -5
  139. umap/static/umap/locale/zh_TW.Big5.json +19 -5
  140. umap/static/umap/locale/zh_TW.js +22 -5
  141. umap/static/umap/locale/zh_TW.json +19 -5
  142. umap/static/umap/map.css +2 -145
  143. umap/static/umap/vars.css +5 -0
  144. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +410 -428
  145. umap/static/umap/vendors/geojson-to-gpx/index.js +155 -0
  146. umap/static/umap/vendors/osmtogeojson/osmtogeojson.js +1 -2
  147. umap/static/umap/vendors/togeojson/togeojson.es.js +1109 -0
  148. umap/static/umap/vendors/togeojson/{togeojson.umd.js.map → togeojson.es.mjs.map} +1 -1
  149. umap/static/umap/vendors/tokml/tokml.es.js +895 -0
  150. umap/static/umap/vendors/tokml/tokml.es.mjs.map +1 -0
  151. umap/storage.py +6 -2
  152. umap/templates/umap/components/alerts/alert.html +3 -3
  153. umap/templates/umap/css.html +3 -0
  154. umap/templates/umap/js.html +0 -6
  155. umap/tests/fixtures/categorized_highway.geojson +1 -0
  156. umap/tests/fixtures/test_import_osm_relation.json +130 -0
  157. umap/tests/integration/conftest.py +8 -1
  158. umap/tests/integration/test_browser.py +3 -2
  159. umap/tests/integration/test_categorized_layer.py +141 -0
  160. umap/tests/integration/test_conditional_rules.py +21 -0
  161. umap/tests/integration/test_datalayer.py +9 -4
  162. umap/tests/integration/test_edit_datalayer.py +1 -0
  163. umap/tests/integration/test_edit_polygon.py +1 -1
  164. umap/tests/integration/test_export_map.py +2 -3
  165. umap/tests/integration/test_import.py +22 -0
  166. umap/tests/integration/test_tableeditor.py +158 -4
  167. umap/tests/integration/test_websocket_sync.py +2 -2
  168. {umap_project-2.4.2.dist-info → umap_project-2.5.1.dist-info}/METADATA +8 -8
  169. {umap_project-2.4.2.dist-info → umap_project-2.5.1.dist-info}/RECORD +172 -162
  170. umap/static/umap/js/umap.slideshow.js +0 -163
  171. umap/static/umap/js/umap.tableeditor.js +0 -118
  172. umap/static/umap/vendors/togeojson/togeojson.umd.js +0 -2
  173. umap/static/umap/vendors/togpx/togpx.js +0 -547
  174. umap/static/umap/vendors/tokml/tokml.js +0 -343
  175. {umap_project-2.4.2.dist-info → umap_project-2.5.1.dist-info}/WHEEL +0 -0
  176. {umap_project-2.4.2.dist-info → umap_project-2.5.1.dist-info}/entry_points.txt +0 -0
  177. {umap_project-2.4.2.dist-info → umap_project-2.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -25,7 +25,6 @@ const TEMPLATE = `
25
25
  </label>
26
26
  <label id="boundary">
27
27
  </label>
28
- <button class="button">${translate('Choose this data')}</button>
29
28
  `
30
29
 
31
30
  class Autocomplete extends SingleMixin(BaseAjax) {
@@ -66,7 +65,6 @@ export class Importer {
66
65
  } else {
67
66
  console.error(response)
68
67
  }
69
- const asPoint = container.querySelector('[name=aspoint]')
70
68
  this.autocomplete = new Autocomplete(container.querySelector('#boundary'), {
71
69
  placeholder: translate('Search admin boundary'),
72
70
  url: `${this.baseUrl}/boundaries/search?text={q}`,
@@ -75,21 +73,23 @@ export class Importer {
75
73
  boundaryName = choice.item.label
76
74
  },
77
75
  })
78
- const confirm = () => {
76
+ const confirm = (form) => {
79
77
  if (!boundary || !select.value) {
80
78
  Alert.error(translate('Please choose a theme and a boundary first.'))
81
79
  return
82
80
  }
83
- importer.url = `${this.baseUrl}/data/${select.value}/${boundary}?format=geojson&aspoint=${asPoint.checked}`
81
+ importer.url = `${this.baseUrl}/data/${form.theme}/${boundary}?format=geojson&aspoint=${Boolean(form.aspoint)}`
84
82
  importer.format = 'geojson'
85
83
  importer.layerName = `${boundaryName} — ${select.options[select.selectedIndex].textContent}`
86
- importer.dialog.close()
87
84
  }
88
- DomEvent.on(container.querySelector('button'), 'click', confirm)
89
85
 
90
- importer.dialog.open({
91
- content: container,
92
- className: `${this.id} importer dark`,
93
- })
86
+ importer.dialog
87
+ .open({
88
+ template: container,
89
+ className: `${this.id} importer dark`,
90
+ accept: translate('Choose this data'),
91
+ cancel: false,
92
+ })
93
+ .then(confirm)
94
94
  }
95
95
  }
@@ -11,7 +11,7 @@ const TEMPLATE = `
11
11
  </label>
12
12
  <label>
13
13
  ${translate('Geometry mode')}
14
- <select name="out-mode">
14
+ <select name="out">
15
15
  <option value="geom" selected>${translate('Default')}</option>
16
16
  <option value="center">${translate('Only geometry centers')}</option>
17
17
  </select>
@@ -38,6 +38,9 @@ export class Importer {
38
38
  this.map = map
39
39
  this.name = options.name || 'Overpass'
40
40
  this.baseUrl = options?.url || 'https://overpass-api.de/api/interpreter'
41
+ this.searchUrl =
42
+ options?.searchUrl ||
43
+ 'https://photon.komoot.io/api?q={q}&layer=county&layer=city&layer=state'
41
44
  this.id = 'overpass'
42
45
  }
43
46
 
@@ -47,7 +50,7 @@ export class Importer {
47
50
  const container = DomUtil.create('div')
48
51
  container.innerHTML = TEMPLATE
49
52
  this.autocomplete = new Autocomplete(container.querySelector('#area'), {
50
- url: 'https://photon.komoot.io/api?q={q}&osm_tag=place',
53
+ url: this.searchUrl,
51
54
  placeholder: translate(
52
55
  'Type area name, or let empty to load data in current map view'
53
56
  ),
@@ -58,27 +61,28 @@ export class Importer {
58
61
  })
59
62
  this.map.help.parse(container)
60
63
 
61
- const confirm = () => {
62
- let tags = container.querySelector('[name=tags]').value
63
- if (!tags) {
64
- Alert.error(translate('Please define an expression for the query first'))
64
+ const confirm = (form) => {
65
+ if (!form.tags) {
66
+ Alert.error(translate('Expression is empty'))
65
67
  return
66
68
  }
67
- const outMode = container.querySelector('[name=out-mode]').value
69
+ let tags = form.tags
68
70
  if (!tags.startsWith('[')) tags = `[${tags}]`
69
71
  let area = '{south},{west},{north},{east}'
70
72
  if (boundary) area = `area:${boundary}`
71
- const query = `[out:json];nwr${tags}(${area});out ${outMode};`
73
+ const query = `[out:json];nwr${tags}(${area});out ${form.out};`
72
74
  importer.url = `${this.baseUrl}?data=${query}`
73
75
  if (boundary) importer.layerName = boundaryName
74
76
  importer.format = 'osm'
75
- importer.dialog.close()
76
77
  }
77
- L.DomUtil.createButton('', container, translate('Choose this data'), confirm)
78
78
 
79
- importer.dialog.open({
80
- content: container,
81
- className: `${this.id} importer dark`,
82
- })
79
+ importer.dialog
80
+ .open({
81
+ template: container,
82
+ className: `${this.id} importer dark`,
83
+ accept: translate('Choose this data'),
84
+ cancel: false
85
+ })
86
+ .then(confirm)
83
87
  }
84
88
  }
@@ -1,6 +1,7 @@
1
1
  import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
2
2
  import { translate } from './i18n.js'
3
3
  import * as Utils from './utils.js'
4
+ import { AutocompleteDatalist } from './autocomplete.js'
4
5
 
5
6
  class Rule {
6
7
  get condition() {
@@ -123,7 +124,18 @@ class Rule {
123
124
  const builder = new U.FormBuilder(this, options)
124
125
  const defaultShapeProperties = DomUtil.add('div', '', container)
125
126
  defaultShapeProperties.appendChild(builder.build())
126
-
127
+ const autocomplete = new AutocompleteDatalist(builder.helpers.condition.input)
128
+ const properties = this.map.allProperties()
129
+ autocomplete.suggestions = properties
130
+ autocomplete.input.addEventListener('input', (event) => {
131
+ const value = event.target.value
132
+ if (properties.includes(value)) {
133
+ autocomplete.suggestions = [`${value}=`, `${value}!=`, `${value}>`, `${value}<`]
134
+ } else if (value.endsWith('=')) {
135
+ const key = value.split('!')[0].split('=')[0]
136
+ autocomplete.suggestions = this.map.sortedValues(key).map((str) => `${value}${str || ''}`)
137
+ }
138
+ })
127
139
  this.map.editPanel.open({ content: container })
128
140
  }
129
141
 
@@ -40,12 +40,16 @@ export const SCHEMA = {
40
40
  label: translate('Do you want to display caption menus?'),
41
41
  default: true,
42
42
  },
43
+ categorized: {
44
+ type: Object,
45
+ impacts: ['data'],
46
+ },
43
47
  color: {
44
48
  type: String,
45
49
  impacts: ['data'],
46
50
  handler: 'ColorPicker',
47
51
  label: translate('color'),
48
- helpEntries: 'colorValue',
52
+ helpEntries: ['colorValue'],
49
53
  inheritable: true,
50
54
  default: 'DarkBlue',
51
55
  },
@@ -65,7 +69,7 @@ export const SCHEMA = {
65
69
  type: String,
66
70
  impacts: ['data'],
67
71
  label: translate('dash array'),
68
- helpEntries: 'dashArray',
72
+ helpEntries: ['dashArray'],
69
73
  inheritable: true,
70
74
  },
71
75
  datalayersControl: {
@@ -92,7 +96,7 @@ export const SCHEMA = {
92
96
  type: 'Text',
93
97
  impacts: ['ui'],
94
98
  label: translate('description'),
95
- helpEntries: 'textFormatting',
99
+ helpEntries: ['textFormatting'],
96
100
  },
97
101
  displayOnLoad: {
98
102
  type: Boolean,
@@ -131,7 +135,7 @@ export const SCHEMA = {
131
135
  type: Boolean,
132
136
  impacts: ['data'],
133
137
  label: translate('fill'),
134
- helpEntries: 'fill',
138
+ helpEntries: ['fill'],
135
139
  inheritable: true,
136
140
  default: true,
137
141
  },
@@ -140,7 +144,7 @@ export const SCHEMA = {
140
144
  impacts: ['data'],
141
145
  handler: 'ColorPicker',
142
146
  label: translate('fill color'),
143
- helpEntries: 'fillColor',
147
+ helpEntries: ['fillColor'],
144
148
  inheritable: true,
145
149
  },
146
150
  fillOpacity: {
@@ -216,7 +220,7 @@ export const SCHEMA = {
216
220
  type: Boolean,
217
221
  impacts: ['data'],
218
222
  label: translate('Allow interactions'),
219
- helpEntries: 'interactive',
223
+ helpEntries: ['interactive'],
220
224
  inheritable: true,
221
225
  default: true,
222
226
  },
@@ -243,7 +247,7 @@ export const SCHEMA = {
243
247
  labelKey: {
244
248
  type: String,
245
249
  impacts: ['data'],
246
- helpEntries: 'labelKey',
250
+ helpEntries: ['labelKey'],
247
251
  placeholder: translate('Default: name'),
248
252
  label: translate('Label key'),
249
253
  inheritable: true,
@@ -319,7 +323,7 @@ export const SCHEMA = {
319
323
  type: String,
320
324
  impacts: [],
321
325
  label: translate('Link to…'),
322
- helpEntries: 'outlink',
326
+ helpEntries: ['outlink'],
323
327
  placeholder: 'http://...',
324
328
  inheritable: true,
325
329
  },
@@ -441,7 +445,7 @@ export const SCHEMA = {
441
445
  max: 10,
442
446
  step: 0.5,
443
447
  label: translate('Simplify'),
444
- helpEntries: 'smoothFactor',
448
+ helpEntries: ['smoothFactor'],
445
449
  inheritable: true,
446
450
  default: 1.0,
447
451
  },
@@ -459,7 +463,7 @@ export const SCHEMA = {
459
463
  type: Boolean,
460
464
  impacts: ['data'],
461
465
  label: translate('stroke'),
462
- helpEntries: 'stroke',
466
+ helpEntries: ['stroke'],
463
467
  inheritable: true,
464
468
  default: true,
465
469
  },
@@ -467,7 +471,7 @@ export const SCHEMA = {
467
471
  type: Boolean,
468
472
  impacts: ['sync', 'ui'],
469
473
  label: translate('Enable real-time collaboration'),
470
- helpEntries: 'sync',
474
+ helpEntries: ['sync'],
471
475
  default: false,
472
476
  },
473
477
  tilelayer: {
@@ -526,7 +530,7 @@ export const SCHEMA = {
526
530
  type: Number,
527
531
  impacts: [], // not need to update the view
528
532
  placeholder: translate('Inherit'),
529
- helpEntries: 'zoomTo',
533
+ helpEntries: ['zoomTo'],
530
534
  label: translate('Default zoom level'),
531
535
  inheritable: true,
532
536
  },
@@ -1,43 +1,11 @@
1
- U.Share = L.Class.extend({
2
- EXPORT_TYPES: {
3
- geojson: {
4
- formatter: (map) => JSON.stringify(map.toGeoJSON(), null, 2),
5
- ext: '.geojson',
6
- filetype: 'application/json',
7
- },
8
- gpx: {
9
- formatter: (map) => togpx(map.toGeoJSON()),
10
- ext: '.gpx',
11
- filetype: 'application/gpx+xml',
12
- },
13
- kml: {
14
- formatter: (map) => tokml(map.toGeoJSON()),
15
- ext: '.kml',
16
- filetype: 'application/vnd.google-earth.kml+xml',
17
- },
18
- csv: {
19
- formatter: (map) => {
20
- const table = []
21
- map.eachFeature((feature) => {
22
- const row = feature.toGeoJSON().properties
23
- const center = feature.getCenter()
24
- delete row._umap_options
25
- row.Latitude = center.lat
26
- row.Longitude = center.lng
27
- table.push(row)
28
- })
29
- return csv2geojson.dsv.csvFormat(table)
30
- },
31
- ext: '.csv',
32
- filetype: 'text/csv',
33
- },
34
- },
35
-
36
- initialize: function (map) {
1
+ import { EXPORT_FORMATS } from './formatter.js'
2
+
3
+ export default class Share {
4
+ constructor(map) {
37
5
  this.map = map
38
- },
6
+ }
39
7
 
40
- build: function () {
8
+ build() {
41
9
  this.container = L.DomUtil.create('div', '')
42
10
  this.title = L.DomUtil.createTitle(
43
11
  this.container,
@@ -63,16 +31,10 @@ U.Share = L.Class.extend({
63
31
 
64
32
  L.DomUtil.add('h4', '', this.container, L._('Download'))
65
33
  L.DomUtil.add('small', 'label', this.container, L._("Only visible layers' data"))
66
- for (const key in this.EXPORT_TYPES) {
67
- if (this.EXPORT_TYPES.hasOwnProperty(key)) {
68
- L.DomUtil.createButton(
69
- 'download-file',
70
- this.container,
71
- this.EXPORT_TYPES[key].name || key,
72
- () => this.download(key),
73
- this
74
- )
75
- }
34
+ for (const format of Object.keys(EXPORT_FORMATS)) {
35
+ L.DomUtil.createButton('download-file', this.container, format, () =>
36
+ this.download(format)
37
+ )
76
38
  }
77
39
  L.DomUtil.create('div', 'vspace', this.container)
78
40
  L.DomUtil.add(
@@ -135,7 +97,7 @@ U.Share = L.Class.extend({
135
97
  for (let i = 0; i < this.map.HIDDABLE_CONTROLS.length; i++) {
136
98
  UIFields.push(`queryString.${this.map.HIDDABLE_CONTROLS[i]}Control`)
137
99
  }
138
- const iframeExporter = new U.IframeExporter(this.map)
100
+ const iframeExporter = new IframeExporter(this.map)
139
101
  const buildIframeCode = () => {
140
102
  iframe.textContent = iframeExporter.build()
141
103
  exportUrl.value = window.location.protocol + iframeExporter.buildUrl()
@@ -149,24 +111,24 @@ U.Share = L.Class.extend({
149
111
  L._('Embed and link options')
150
112
  )
151
113
  iframeOptions.appendChild(builder.build())
152
- },
114
+ }
153
115
 
154
- open: function () {
116
+ open() {
155
117
  if (!this.container) this.build()
156
118
  this.map.panel.open({ content: this.container })
157
- },
119
+ }
158
120
 
159
- format: function (mode) {
160
- const type = this.EXPORT_TYPES[mode]
161
- const content = type.formatter(this.map)
121
+ async format(mode) {
122
+ const type = EXPORT_FORMATS[mode]
123
+ const content = await type.formatter(this.map)
162
124
  let name = this.map.options.name || 'data'
163
125
  name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
164
126
  const filename = name + type.ext
165
127
  return { content, filetype: type.filetype, filename }
166
- },
128
+ }
167
129
 
168
- download: function (mode) {
169
- const { content, filetype, filename } = this.format(mode)
130
+ async download(mode) {
131
+ const { content, filetype, filename } = await this.format(mode)
170
132
  const blob = new Blob([content], { type: filetype })
171
133
  window.URL = window.URL || window.webkitURL
172
134
  const el = document.createElement('a')
@@ -176,50 +138,49 @@ U.Share = L.Class.extend({
176
138
  document.body.appendChild(el)
177
139
  el.click()
178
140
  document.body.removeChild(el)
179
- },
180
- })
181
-
182
- U.IframeExporter = L.Evented.extend({
183
- options: {
184
- includeFullScreenLink: true,
185
- currentView: false,
186
- keepCurrentDatalayers: false,
187
- viewCurrentFeature: false,
188
- },
189
-
190
- queryString: {
191
- scaleControl: false,
192
- miniMap: false,
193
- scrollWheelZoom: false,
194
- zoomControl: true,
195
- editMode: 'disabled',
196
- moreControl: true,
197
- searchControl: null,
198
- tilelayersControl: null,
199
- embedControl: null,
200
- datalayersControl: true,
201
- onLoadPanel: 'none',
202
- captionBar: false,
203
- captionMenus: true,
204
- },
205
-
206
- dimensions: {
207
- width: '100%',
208
- height: '300px',
209
- },
210
-
211
- initialize: function (map) {
141
+ }
142
+ }
143
+
144
+ class IframeExporter {
145
+ constructor(map) {
212
146
  this.map = map
213
147
  this.baseUrl = U.Utils.getBaseUrl()
148
+ this.options = {
149
+ includeFullScreenLink: true,
150
+ currentView: false,
151
+ keepCurrentDatalayers: false,
152
+ viewCurrentFeature: false,
153
+ }
154
+
155
+ this.queryString = {
156
+ scaleControl: false,
157
+ miniMap: false,
158
+ scrollWheelZoom: false,
159
+ zoomControl: true,
160
+ editMode: 'disabled',
161
+ moreControl: true,
162
+ searchControl: null,
163
+ tilelayersControl: null,
164
+ embedControl: null,
165
+ datalayersControl: true,
166
+ onLoadPanel: 'none',
167
+ captionBar: false,
168
+ captionMenus: true,
169
+ }
170
+
171
+ this.dimensions = {
172
+ width: '100%',
173
+ height: '300px',
174
+ }
214
175
  // Use map default, not generic default
215
176
  this.queryString.onLoadPanel = this.map.getOption('onLoadPanel')
216
- },
177
+ }
217
178
 
218
- getMap: function () {
179
+ getMap() {
219
180
  return this.map
220
- },
181
+ }
221
182
 
222
- buildUrl: function (options) {
183
+ buildUrl(options) {
223
184
  const datalayers = []
224
185
  if (this.options.viewCurrentFeature && this.map.currentFeature) {
225
186
  this.queryString.feature = this.map.currentFeature.getSlug()
@@ -239,9 +200,9 @@ U.IframeExporter = L.Evented.extend({
239
200
  const currentView = this.options.currentView ? window.location.hash : ''
240
201
  const queryString = L.extend({}, this.queryString, options)
241
202
  return `${this.baseUrl}?${U.Utils.buildQueryString(queryString)}${currentView}`
242
- },
203
+ }
243
204
 
244
- build: function () {
205
+ build() {
245
206
  const iframeUrl = this.buildUrl()
246
207
  let code = `<iframe width="${this.dimensions.width}" height="${this.dimensions.height}" frameborder="0" allowfullscreen allow="geolocation" src="${iframeUrl}"></iframe>`
247
208
  if (this.options.includeFullScreenLink) {
@@ -249,5 +210,5 @@ U.IframeExporter = L.Evented.extend({
249
210
  code += `<p><a href="${fullUrl}">${L._('See full screen')}</a></p>`
250
211
  }
251
212
  return code
252
- },
253
- })
213
+ }
214
+ }
@@ -0,0 +1,141 @@
1
+ import { WithTemplate } from './utils.js'
2
+ import { translate } from './i18n.js'
3
+
4
+ const TOOLBOX_TEMPLATE = `
5
+ <ul class="umap-slideshow-toolbox dark">
6
+ <li class="play" title="${translate('Start slideshow')}" data-ref="play">
7
+ <div class="spinner" style="animation: none;"></div>
8
+ </li>
9
+ <li class="stop" title="${translate('Stop slideshow')}" data-ref="stop"></li>
10
+ <li class="prev" title="${translate('Zoom to the previous')}" data-ref="previous"></li>
11
+ <li class="next" title="${translate('Zoom to the next')}" data-ref="next"></li>
12
+ </ul>
13
+ `
14
+
15
+ export default class Slideshow extends WithTemplate {
16
+ constructor(map, options) {
17
+ super()
18
+ this.map = map
19
+ this._id = null
20
+ this.CLASSNAME = 'umap-slideshow-active'
21
+ this.setOptions(options)
22
+ this._current = null
23
+
24
+ if (this.options.autoplay) {
25
+ this.map.onceDataLoaded(function () {
26
+ this.play()
27
+ }, this)
28
+ }
29
+ this.map.on(
30
+ 'edit:enabled',
31
+ function () {
32
+ this.stop()
33
+ },
34
+ this
35
+ )
36
+ }
37
+
38
+ set current(feature) {
39
+ this._current = feature
40
+ }
41
+
42
+ get current() {
43
+ if (!this._current) {
44
+ const datalayer = this.defaultDatalayer()
45
+ if (datalayer) this._current = datalayer.getFeatureByIndex(0)
46
+ }
47
+ return this._current
48
+ }
49
+
50
+ get next() {
51
+ if (this._current === null) {
52
+ return this.current
53
+ }
54
+ return this.current.getNext()
55
+ }
56
+
57
+ setOptions(options) {
58
+ this.options = Object.assign(
59
+ {
60
+ delay: 5000,
61
+ autoplay: false,
62
+ },
63
+ options
64
+ )
65
+ }
66
+
67
+ defaultDatalayer() {
68
+ return this.map.findDataLayer((d) => d.canBrowse())
69
+ }
70
+
71
+ startSpinner() {
72
+ const time = Number.parseInt(this.options.delay, 10)
73
+ if (!time) return
74
+ const css = `rotation ${time / 1000}s infinite linear`
75
+ const spinner = document.querySelector('.umap-slideshow-toolbox .play .spinner')
76
+ spinner.style.animation = css
77
+ }
78
+
79
+ stopSpinner() {
80
+ const spinner = document.querySelector('.umap-slideshow-toolbox .play .spinner')
81
+ spinner.style.animation = 'none'
82
+ }
83
+
84
+ play() {
85
+ if (this._id) return
86
+ if (this.map.editEnabled || !this.map.options.slideshow.active) return
87
+ L.DomUtil.addClass(document.body, this.CLASSNAME)
88
+ this._id = window.setInterval(L.bind(this.loop, this), this.options.delay)
89
+ this.startSpinner()
90
+ this.loop()
91
+ }
92
+
93
+ loop() {
94
+ this.current = this.next
95
+ this.step()
96
+ }
97
+
98
+ pause() {
99
+ if (this._id) {
100
+ this.stopSpinner()
101
+ L.DomUtil.removeClass(document.body, this.CLASSNAME)
102
+ window.clearInterval(this._id)
103
+ this._id = null
104
+ }
105
+ }
106
+
107
+ stop() {
108
+ this.pause()
109
+ this.current = null
110
+ }
111
+
112
+ forward() {
113
+ this.pause()
114
+ this.current = this.next
115
+ this.step()
116
+ }
117
+
118
+ backward() {
119
+ this.pause()
120
+ if (this.current) this.current = this.current.getPrevious()
121
+ this.step()
122
+ }
123
+
124
+ step() {
125
+ if (!this.current) return this.stop()
126
+ this.current.zoomTo({ easing: this.options.easing })
127
+ this.current.view()
128
+ }
129
+
130
+ toggle() {
131
+ this._id ? this.pause() : this.play()
132
+ }
133
+
134
+ renderToolbox(container) {
135
+ container.appendChild(this.loadTemplate(TOOLBOX_TEMPLATE))
136
+ this.elements.play.addEventListener('click', this.toggle.bind(this))
137
+ this.elements.stop.addEventListener('click', this.stop.bind(this))
138
+ this.elements.previous.addEventListener('click', this.backward.bind(this))
139
+ this.elements.next.addEventListener('click', this.forward.bind(this))
140
+ }
141
+ }