Projekt

Obecné

Profil

Stáhnout (18.2 KB) Statistiky
| Větev: | Revize:
1 8feb1753 ballakt
/* global L */
2
/* global $ */
3 2f227a6c ballakt
4 8feb1753 ballakt
var mymap
5
var heatmapLayer = null
6
var marksLayer = null
7 03c02899 vastja
8 8feb1753 ballakt
var startX = 49.7248
9
var startY = 13.3521
10
var startZoom = 17
11 3fc08f2d vastja
12 8feb1753 ballakt
var dataSourceRoute
13 1cf1413d ballakt
let positionsSourceRoute
14 1774c06d Tomáš Ballák
15
let currentTime
16
17
let currentDate
18 a48642fb vastja
19 8feb1753 ballakt
var timer
20
var isAnimationRunning = false
21
var data = []
22 a48642fb vastja
23 70a3df53 vastja
var info = []
24 2f227a6c ballakt
let currentInfo = 0
25
26 883a423e Tomáš Ballák
const datasetDictNameDisplayName = {}
27 2f227a6c ballakt
var datasetSelected = []
28 70a3df53 vastja
29 1774c06d Tomáš Ballák
// data only for one day
30
let lockedDay = false
31
32
let loading = 0
33
34
// marks for all datasets
35
const dataSourceMarks = {}
36
37 8feb1753 ballakt
const globalMarkersHolder = {}
38 d5a88af0 Tomáš Ballák
// all marker from which popup was removed
39
// contains: {key:[L.circle,L.pupup]}
40
// key: x and y, x + '' + y string
41
let globalMarkersChanged = {}
42 084a5972 ballakt
43 1774c06d Tomáš Ballák
const loadingY = () => {
44
  loading++
45
}
46
const loadingN = () => {
47
  loading--
48
}
49
50
const changeCurrentTime = (time = null) => {
51
  if (time !== null) {
52
    currentTime = time
53
  } else {
54 863ca316 Martin Sebela
    currentTime = parseInt($('#dropdown-time input[type="radio"]:checked').val())
55 1774c06d Tomáš Ballák
  }
56
}
57
58
const changeCurrentDate = (date = null) => {
59
  if (date) {
60
    currentDate = new Date(date)
61
  } else {
62
    currentDate = new Date($('#date').val())
63
  }
64 863ca316 Martin Sebela
65 1774c06d Tomáš Ballák
  $('#date').val(currentDateToString())
66 863ca316 Martin Sebela
  $('#player-date span').html(`${currentDate.getDate()}. ${currentDate.getMonth() + 1}. ${currentDate.getFullYear()}`)
67
68 1774c06d Tomáš Ballák
  data = []
69
}
70
const currentDayToString = () => {
71
  const day = currentDate.getDate()
72
  return day > 9 ? `${day}` : `0${day}`
73
}
74
const currentMonthToString = () => {
75
  const month = currentDate.getMonth() + 1
76
  return month > 9 ? `${month}` : `0${month}`
77
}
78
const currentDateToString = () => `${currentDate.getFullYear()}-${currentMonthToString()}-${currentDayToString()}`
79
const addDayToCurrentDate = (day) => {
80
  currentDate.setDate(currentDate.getDate() + day)
81
  changeCurrentDate(currentDate)
82
}
83
const toggleDayLock = () => {
84
  lockedDay = !lockedDay
85
  $('#player-date').toggleClass('lock')
86
}
87 c892003d Martin Sebela
88 2f227a6c ballakt
const fetchByNameDate = async (baseRoute, name, date, currentTime) => {
89
  const headers = new Headers()
90
  const myRequest = new Request(baseRoute + '/' + name + '/' + date + '/' + currentTime, {
91
    method: 'GET',
92
    headers: headers
93
  })
94
  const beforeJson = await fetch(myRequest)
95
  return beforeJson.json()
96
}
97 c892003d Martin Sebela
98 2f227a6c ballakt
const fetchDataSourceMarks = async (positionRoute, datasetName) => {
99
  const headers = new Headers()
100
  const myRequest = new Request(positionRoute + '/' + datasetName, {
101
    method: 'GET',
102
    headers: headers
103
  })
104
  const beforeJson = await fetch(myRequest)
105
  return beforeJson.json()
106
}
107 084a5972 ballakt
108 2f227a6c ballakt
const genPopUpControlButtons = (currentPage, numPages, onNextClick, onPreviousClick) => ({
109
  previousButton: '<button id="previous-info-btn" class="circle-button" onclick="previousInfo()"></button>',
110 c892003d Martin Sebela
  nextButton: '<button id="next-info-btn" class="circle-button next" onclick="nextInfo()"></button>',
111 2f227a6c ballakt
  posInfo: `<div id="count-info">${currentPage} z ${numPages}</div>`
112
})
113 c892003d Martin Sebela
114 084a5972 ballakt
const genPopUpControls = (controls) => {
115 2f227a6c ballakt
  return `<div class="popup-controls">${controls ? controls.reduce((sum, item) => sum + item, '') : ''}</div>`
116 084a5972 ballakt
}
117 c892003d Martin Sebela
118 883a423e Tomáš Ballák
const genMultipleDatasetsPopUp = (sum, currentPos, maxPos, datasetName) => {
119 c892003d Martin Sebela
  const popupHeader = `<strong id="dataset-info">${datasetName}</strong>`
120
  const popupData = `<div id="number-info"><span id="digit-info">${sum}</span></div>`
121 2f227a6c ballakt
  const { previousButton, nextButton, posInfo } = genPopUpControlButtons(currentPos, maxPos)
122 c892003d Martin Sebela
123 2f227a6c ballakt
  return `
124 c892003d Martin Sebela
  ${popupHeader}
125
  ${popupData}
126 2f227a6c ballakt
  ${genPopUpControls([previousButton, posInfo, nextButton])}
127
  `
128
}
129 c892003d Martin Sebela
130 2f227a6c ballakt
const prepareLayerPopUp = (lat, lng, num, className) => L.popup({
131
  autoPan: false,
132
  className: className
133
}).setLatLng([lat / num, lng / num])
134
135 bb2d43b5 Martin Sebela
const genPopUp = (datasetName, place, count, sum, currentPos, maxPos) => {
136
  const popupHeader = `
137
    <strong>${datasetName}</strong>
138
    <div id="place-info">${place}</div>`
139
  const popupData = `
140
    <div id="number-info">
141
      <span id="digit-info">${count}</span>
142
      <span id="total-info">${(sum && (sum != count)) ? '/' + sum : ''}</span>
143
    </div>`
144 2f227a6c ballakt
  const { previousButton, nextButton, posInfo } = genPopUpControlButtons(currentPos, maxPos)
145 bb2d43b5 Martin Sebela
146 084a5972 ballakt
  return `
147 bb2d43b5 Martin Sebela
  ${popupHeader}
148
  ${popupData}
149 2f227a6c ballakt
  ${genPopUpControls(maxPos > 1 ? [previousButton, posInfo, nextButton] : null)}
150 084a5972 ballakt
  `
151
}
152 c892003d Martin Sebela
153 1cf1413d ballakt
const onCheckboxClicked = async (checkbox) => {
154
  if ($(checkbox).prop('checked')) {
155
    loadCurrentTimeHeatmap(dataSourceRoute, positionsSourceRoute)
156
    changeUrl()
157 1774c06d Tomáš Ballák
  } else {
158 1cf1413d ballakt
    loadCheckboxDatasetNameData()
159 c892003d Martin Sebela
160 1cf1413d ballakt
    data.forEach((item, index) => {
161
      Object.keys(item).forEach((datasetName) => {
162
        if (datasetName === $(checkbox).val()) {
163
          delete data[index][datasetName]
164
        }
165
      })
166
      drawHeatmap(data[currentTime])
167
    })
168 c892003d Martin Sebela
169 1cf1413d ballakt
    changeUrl()
170
  }
171
}
172 c892003d Martin Sebela
173 1cf1413d ballakt
const debounce = (func, delay) => {
174
  let inDebounce
175
  return function () {
176
    const context = this
177
    const args = arguments
178
    clearTimeout(inDebounce)
179
    inDebounce = setTimeout(() => func.apply(context, args), delay)
180
  }
181
}
182 bb2d43b5 Martin Sebela
183 1cf1413d ballakt
const onValueChangeRegister = () => {
184
  $('#date').change(function () {
185 1774c06d Tomáš Ballák
    changeCurrentDate($(this).val())
186 1cf1413d ballakt
    loadCurrentTimeHeatmap(dataSourceRoute, positionsSourceRoute)
187 bb2d43b5 Martin Sebela
    changeUrl()
188 1cf1413d ballakt
  })
189 bb2d43b5 Martin Sebela
190 c892003d Martin Sebela
  $('#dropdown-time input[type="radio"]').each(function () {
191 1cf1413d ballakt
    $(this).change(function () {
192 1774c06d Tomáš Ballák
      changeHour(parseInt($(this).val()))
193 1cf1413d ballakt
      drawHeatmap(data[currentTime])
194
    })
195
  })
196 bb2d43b5 Martin Sebela
197 c892003d Martin Sebela
  $('#dropdown-dataset input[type="checkbox"]').each(function () {
198 1cf1413d ballakt
    $(this).change(
199
      debounce(() => onCheckboxClicked(this), 1000)
200
    )
201
  })
202
}
203 bb2d43b5 Martin Sebela
204 70a3df53 vastja
/**
205
 * Initialize leaflet map on start position which can be default or set based on user action
206
 */
207 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
208
function initMap () {
209 90d3db28 Tomáš Ballák
  startX = localStorage.getItem('lat') || startX
210
  startY = localStorage.getItem('lng') || startY
211
  startZoom = localStorage.getItem('zoom') || startZoom
212 72a438f3 vastja
213 8feb1753 ballakt
  mymap = L.map('heatmap').setView([startX, startY], startZoom)
214 3fc08f2d vastja
215 c236b33a msebela
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
216
    attribution: '',
217
    maxZoom: 19
218 8feb1753 ballakt
  }).addTo(mymap)
219 3ae59f75 vastja
220 8feb1753 ballakt
  mymap.on('click', showInfo)
221 c236b33a msebela
}
222 c892003d Martin Sebela
223 2f227a6c ballakt
const getInfoLength = () => {
224
  const infoKeys = Object.keys(info)
225
  if (infoKeys.length === 1) {
226
    // return number of records in one dataset (one dataset in area)
227
    return info[infoKeys[0]].items.length
228
  }
229
  // return number of datasets (agregation of all datasets in area)
230
  return infoKeys.length
231
}
232 c892003d Martin Sebela
233 2f227a6c ballakt
const getElFromObjectInfo = (position) => {
234
  const keys = Object.keys(info)
235
  return info[keys[position]]
236
}
237 c892003d Martin Sebela
238 2f227a6c ballakt
const hasInfoMultipleDatasets = () => {
239
  return Object.keys(info).length > 1
240
}
241 c892003d Martin Sebela
242 8feb1753 ballakt
function showInfo (e) {
243 3ae59f75 vastja
  info = []
244 2f227a6c ballakt
  currentInfo = 0
245 3ae59f75 vastja
246
  // https://wiki.openstreetmap.org/wiki/Zoom_levels
247
  // Todo change to variable - it is used in heatmap init
248 2f227a6c ballakt
  const stile = 40075016.686 * Math.cos(startX) / Math.pow(2, mymap.getZoom())
249
  const radius = 25 * stile / 256
250
251
  let i = 0
252
  let lat = 0
253
  let lng = 0
254
255
  let total = 0
256
257
  const datasetsInRadius = {}
258
259
  Object.keys(data[currentTime]).forEach((key) => {
260
    const namedData = data[currentTime][key]
261
    namedData.items.forEach(element => {
262
      if (e.latlng.distanceTo(new L.LatLng(element.x, element.y)) < radius) {
263
        lat += element.x
264
        lng += element.y
265
        info[i] = { place: element.place, number: element.number, datasetName: key }
266
        total += parseInt(element.number)
267
        i++
268
        datasetsInRadius[key] = true
269
      }
270
    })
271 8feb1753 ballakt
  })
272 3ae59f75 vastja
273 2f227a6c ballakt
  // Process info for more then one dataset
274 8feb1753 ballakt
275 2f227a6c ballakt
  info = info.reduce((acc, item) => {
276
    if (!acc[item.datasetName]) {
277
      acc[item.datasetName] = {
278
        items: [],
279
        number: 0,
280
        datasetName: item.datasetName
281
      }
282
    }
283 c892003d Martin Sebela
284 2f227a6c ballakt
    acc[item.datasetName].items.push(item)
285
    acc[item.datasetName].number += Number(item.number)
286
    return acc
287
  }, {})
288
289
  // There is one dataset
290
291
  const numDatasets = Object.keys(datasetsInRadius).length
292
293 d5a88af0 Tomáš Ballák
  if (!numDatasets) {
294
    return
295
  }
296 2f227a6c ballakt
297
  if (numDatasets === 1) {
298
    const infoDict = getElFromObjectInfo(0)
299
    const info_ = infoDict.items
300
    const { place, number } = info_[currentInfo]
301
    prepareLayerPopUp(lat, lng, i, `popup-${infoDict.datasetName}`)
302 883a423e Tomáš Ballák
      .setContent(genPopUp(datasetDictNameDisplayName[infoDict.datasetName], place, number, total, currentInfo + 1, info_.length))
303 2f227a6c ballakt
      .openOn(mymap)
304 c892003d Martin Sebela
305 2f227a6c ballakt
    if (info_.length === 1) {
306 8feb1753 ballakt
      $('#previous-info-btn').prop('disabled', true)
307
      $('#next-info-btn').prop('disabled', true)
308
      $('.popup-controls').hide()
309 3ae59f75 vastja
    }
310 1774c06d Tomáš Ballák
  } else {
311 2f227a6c ballakt
    const { datasetName, number } = getElFromObjectInfo(currentInfo)
312 c892003d Martin Sebela
313 2f227a6c ballakt
    prepareLayerPopUp(lat, lng, i, `popup-${datasetName}`)
314 883a423e Tomáš Ballák
      .setContent(genMultipleDatasetsPopUp(number, currentInfo + 1, getInfoLength(), datasetDictNameDisplayName[datasetName]))
315 2f227a6c ballakt
      .openOn(mymap)
316 3ae59f75 vastja
  }
317
}
318
319 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
320
function previousInfo () {
321 2f227a6c ballakt
  const infoLength = getInfoLength()
322
  const previousCurrentInfo = currentInfo
323 c892003d Martin Sebela
324 2f227a6c ballakt
  currentInfo = (currentInfo + infoLength - 1) % infoLength
325
  displayInfoText(previousCurrentInfo)
326 3ae59f75 vastja
}
327
328 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
329
function nextInfo () {
330 2f227a6c ballakt
  const infoLength = getInfoLength()
331
  const previousCurrentInfo = currentInfo
332 c892003d Martin Sebela
333 2f227a6c ballakt
  currentInfo = (currentInfo + 1) % infoLength
334
  displayInfoText(previousCurrentInfo)
335 3ae59f75 vastja
}
336 c892003d Martin Sebela
337 2f227a6c ballakt
function displayInfoText (previousInfoNum) {
338
  const previousInfo = hasInfoMultipleDatasets() ? getElFromObjectInfo(previousInfoNum) : getElFromObjectInfo(0).items[previousInfoNum]
339
  const info_ = hasInfoMultipleDatasets() ? getElFromObjectInfo(currentInfo) : getElFromObjectInfo(0).items[currentInfo]
340
  const infoLength = getInfoLength()
341 883a423e Tomáš Ballák
  const datasetInfo = $('#dataset-info')
342 c892003d Martin Sebela
343 883a423e Tomáš Ballák
  if (datasetInfo) {
344
    $(datasetInfo).html(datasetDictNameDisplayName[info_.datasetName])
345
  }
346 1774c06d Tomáš Ballák
347 2f227a6c ballakt
  $('#place-info').html(info_.place ? info_.place : info_.datasetName)
348
  $('#digit-info').html(info_.number)
349
  $('#count-info').html(currentInfo + 1 + ' z ' + infoLength)
350 c892003d Martin Sebela
351 2f227a6c ballakt
  $('.leaflet-popup').removeClass(`popup-${previousInfo.datasetName}`)
352
  $('.leaflet-popup').addClass(`popup-${info_.datasetName}`)
353 3ae59f75 vastja
}
354 351696d5 Martin Sebela
355 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
356 72a438f3 vastja
function setMapView (latitude, longitude, zoom) {
357 90d3db28 Tomáš Ballák
  localStorage.setItem('lat', latitude)
358
  localStorage.setItem('lng', longitude)
359
  localStorage.setItem('zoom', zoom)
360 8feb1753 ballakt
  mymap.setView([latitude, longitude], zoom)
361 3fc08f2d vastja
}
362
363 70a3df53 vastja
/**
364
 * Change animation start from playing to stopped or the other way round
365
 */
366 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
367
function changeAnimationState () {
368 a48642fb vastja
  isAnimationRunning = !isAnimationRunning
369 c892003d Martin Sebela
370 a48642fb vastja
  if (isAnimationRunning) {
371 863ca316 Martin Sebela
    $('#animate-btn').removeClass('play').addClass('pause')
372 1774c06d Tomáš Ballák
    timer = setInterval(function () { next() }, 800)
373
  } else {
374 8feb1753 ballakt
    clearTimeout(timer)
375 863ca316 Martin Sebela
    $('#animate-btn').removeClass('pause').addClass('play')
376 351696d5 Martin Sebela
  }
377
}
378
379 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
380 1774c06d Tomáš Ballák
async function previous () {
381
  if (loading) {
382
    return
383
  }
384 8feb1753 ballakt
  currentTime = (currentTime + 23) % 24
385 1774c06d Tomáš Ballák
  changeHour(currentTime)
386 8feb1753 ballakt
  mymap.closePopup()
387 1774c06d Tomáš Ballák
  if (!lockedDay && (currentTime === 23)) {
388
    addDayToCurrentDate(-1)
389
    await loadCurrentTimeHeatmap(dataSourceRoute, positionsSourceRoute)
390
  } else {
391
    drawHeatmap(data[currentTime])
392
  }
393 a48642fb vastja
}
394
395 1774c06d Tomáš Ballák
async function next () {
396
  if (loading) {
397
    return
398
  }
399 8feb1753 ballakt
  currentTime = (currentTime + 1) % 24
400 1774c06d Tomáš Ballák
  changeHour(currentTime)
401 8feb1753 ballakt
  mymap.closePopup()
402 1774c06d Tomáš Ballák
  if (!lockedDay && (currentTime === 0)) {
403
    addDayToCurrentDate(1)
404
    await loadCurrentTimeHeatmap(dataSourceRoute, positionsSourceRoute)
405
  } else {
406
    drawHeatmap(data[currentTime])
407
  }
408 8b840eb7 vastja
}
409 c892003d Martin Sebela
410 70a3df53 vastja
/**
411 c892003d Martin Sebela
 * Change browser url based on animation step.
412 70a3df53 vastja
 */
413 8feb1753 ballakt
function changeUrl () {
414 8b840eb7 vastja
  window.history.pushState(
415 8feb1753 ballakt
    '',
416 8b840eb7 vastja
    document.title,
417 1774c06d Tomáš Ballák
    window.location.origin + window.location.pathname + `?date=${currentDateToString()}&time=${currentTime}${datasetSelected.reduce((acc, current) => acc + '&type=' + current, '')}`
418 8feb1753 ballakt
  )
419 4e8c0e5b Martin Sebela
}
420
421 8feb1753 ballakt
function updateHeaderControls () {
422 1cf1413d ballakt
  $(`#time_${currentTime}`).prop('checked', true)
423 bb2d43b5 Martin Sebela
  $('#dropdownMenuButtonTime').html((currentTime < 10 ? '0' : '') + `${currentTime}:00`)
424 a48642fb vastja
}
425 351696d5 Martin Sebela
426 8feb1753 ballakt
function setTimeline () {
427 863ca316 Martin Sebela
  $('#player-time').text(currentTime + ':00')
428
  $('#player-time').attr('class', 'time hour-' + currentTime)
429 351696d5 Martin Sebela
}
430 863ca316 Martin Sebela
431 1774c06d Tomáš Ballák
const onChangeHour = (hour) => {
432
  changeHour(hour)
433
  drawHeatmap(data[currentTime])
434
}
435 863ca316 Martin Sebela
436 1774c06d Tomáš Ballák
const changeHour = (hour) => {
437
  changeCurrentTime(hour)
438 c892003d Martin Sebela
  updateHeaderControls()
439
  setTimeline()
440
  changeUrl()
441
}
442
443 70a3df53 vastja
/**
444
 * Load and display heatmap layer for current data
445
 * @param {string} opendataRoute route to dataset source
446
 * @param {string} positionsRoute  route to dataset postitions source
447
 */
448 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
449 2f227a6c ballakt
async function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
450 1cf1413d ballakt
  loadCheckboxDatasetNameData()
451 c892003d Martin Sebela
452 8feb1753 ballakt
  dataSourceRoute = opendataRoute
453 1cf1413d ballakt
  positionsSourceRoute = positionsRoute
454 2f227a6c ballakt
  const allPromises = []
455
  data[currentTime] = {}
456 1774c06d Tomáš Ballák
457 2f227a6c ballakt
  const dataSelectedHandler = async (datasetName) => {
458 1774c06d Tomáš Ballák
    if (!(datasetName in dataSourceMarks)) {
459
      dataSourceMarks[datasetName] = await fetchDataSourceMarks(positionsRoute, datasetName)
460
    }
461
    const datasetData = await fetchByNameDate(dataSourceRoute, datasetName, currentDateToString(), currentTime)
462 2f227a6c ballakt
    data[currentTime][datasetName] = datasetData
463
  }
464 1774c06d Tomáš Ballák
  datasetSelected.forEach((datasetName) => {
465 2f227a6c ballakt
    allPromises.push(dataSelectedHandler(datasetName))
466 8feb1753 ballakt
  })
467 c892003d Martin Sebela
468 1774c06d Tomáš Ballák
  loadingY()
469 2f227a6c ballakt
  Promise.all(allPromises).then(
470
    () => {
471 1774c06d Tomáš Ballák
      loadingN()
472 2f227a6c ballakt
      drawDataSourceMarks(dataSourceMarks)
473
      drawHeatmap(data[currentTime])
474 1774c06d Tomáš Ballák
      preload(currentTime, 1, currentDateToString())
475
      preload(currentTime, -1, currentDateToString())
476 2f227a6c ballakt
    }
477
  )
478 a48642fb vastja
}
479
480 8feb1753 ballakt
function drawDataSourceMarks (data) {
481 61ff7718 vastja
  if (marksLayer != null) {
482 1cf1413d ballakt
    mymap.removeLayer(marksLayer)
483 61ff7718 vastja
  }
484 c892003d Martin Sebela
485 8feb1753 ballakt
  marksLayer = L.layerGroup()
486 c892003d Martin Sebela
487 2f227a6c ballakt
  Object.keys(data).forEach((key_) => {
488
    for (var key in data[key_]) {
489
      const { x, y, name } = data[key_][key]
490
      const pop =
491
          prepareLayerPopUp(x, y, 1, `popup-${key_}`)
492 883a423e Tomáš Ballák
            .setContent(genPopUp(datasetDictNameDisplayName[key_], name, 0, 0, 1, 1))
493 2f227a6c ballakt
      const newCircle =
494
        L.circle([x, y], { radius: 2, fillOpacity: 0.8, color: '#004fb3', fillColor: '#004fb3', bubblingMouseEvents: true })
495
          .bindPopup(pop)
496
      globalMarkersHolder[x + '' + y] = [newCircle, pop] // add new marker to global holders
497
      marksLayer.addLayer(
498
        newCircle
499
      )
500
    }
501
  })
502 61ff7718 vastja
503 8feb1753 ballakt
  marksLayer.setZIndex(-1).addTo(mymap)
504 61ff7718 vastja
}
505
506 2f227a6c ballakt
async function preload (time, change, date) {
507 1774c06d Tomáš Ballák
  loadingY()
508 2f227a6c ballakt
  for (let nTime = time + change; nTime >= 0 && nTime <= 23; nTime = nTime + change) {
509
    if (!data[nTime]) {
510
      data[nTime] = {}
511
    }
512 c892003d Martin Sebela
513 1cf1413d ballakt
    datasetSelected.forEach(async (datasetName) => {
514
      if (!data[nTime][datasetName]) {
515
        data[nTime][datasetName] = await fetchByNameDate(dataSourceRoute, datasetName, date, nTime)
516
      }
517
    })
518 a48642fb vastja
  }
519 1774c06d Tomáš Ballák
  loadingN()
520 3fc08f2d vastja
}
521
522 2f227a6c ballakt
function drawHeatmap (dataRaw) {
523 03c02899 vastja
  // Todo still switched
524 2f227a6c ballakt
  const dataDict = dataRaw
525
  const mergedPoints = []
526
  let max = 0
527 1774c06d Tomáš Ballák
528 d5a88af0 Tomáš Ballák
  if (Object.keys(globalMarkersChanged).length) {
529
    Object.keys(globalMarkersChanged).forEach(function (key) {
530
      globalMarkersChanged[key][0].bindPopup(globalMarkersChanged[key][1])
531
    })
532
    globalMarkersChanged = {}
533
  }
534 c892003d Martin Sebela
535 2f227a6c ballakt
  Object.keys(dataDict).forEach((key) => {
536
    const data = dataDict[key]
537
    max = Math.max(max, data.max)
538 c892003d Martin Sebela
539 2f227a6c ballakt
    if (data != null) {
540 8feb1753 ballakt
    // Bind back popups for markers (we dont know if there is any data for this marker or not)
541 2f227a6c ballakt
      const points = data.items.map((point) => {
542
        const { x, y, number } = point
543
        const key = x + '' + y
544
        const holder = globalMarkersHolder[key]
545 c892003d Martin Sebela
546 2f227a6c ballakt
        if (!globalMarkersChanged[key] && number) {
547 8feb1753 ballakt
        // There is data for this marker => unbind popup with zero value
548 2f227a6c ballakt
          holder[0] = holder[0].unbindPopup()
549
          globalMarkersChanged[key] = holder
550
        }
551 c892003d Martin Sebela
552 2f227a6c ballakt
        return [x, y, number]
553
      })
554
      mergedPoints.push(...points)
555 1774c06d Tomáš Ballák
    } else {
556 2f227a6c ballakt
      if (heatmapLayer != null) {
557
        mymap.removeLayer(heatmapLayer)
558 084a5972 ballakt
      }
559 a48642fb vastja
    }
560 2f227a6c ballakt
  })
561 c892003d Martin Sebela
562 2f227a6c ballakt
  if (heatmapLayer != null) {
563
    mymap.removeLayer(heatmapLayer)
564
  }
565 c892003d Martin Sebela
566 2f227a6c ballakt
  if (mergedPoints.length) {
567
    heatmapLayer = L.heatLayer(mergedPoints, { max: max, minOpacity: 0.5, radius: 35, blur: 30 }).addTo(mymap)
568 a48642fb vastja
  }
569 03c02899 vastja
}
570 3fc08f2d vastja
571 70a3df53 vastja
/**
572
 * Checks dataset availibility
573 81980e82 ballakt
 * @param {string} route authority for datasets availibility checks
574 70a3df53 vastja
 */
575 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
576
function checkDataSetsAvailability (route) {
577 03c02899 vastja
  $.ajax({
578 8feb1753 ballakt
    type: 'POST',
579 03c02899 vastja
    // Todo it might be good idea to change db collections format
580 1774c06d Tomáš Ballák
    url: route + '/' + currentDateToString(),
581 8feb1753 ballakt
    success: function (result) {
582
      updateAvailableDataSets(result)
583 03c02899 vastja
    }
584 8feb1753 ballakt
  })
585 03c02899 vastja
}
586
587 8feb1753 ballakt
function updateAvailableDataSets (available) {
588 2f227a6c ballakt
  let leastOneOptionEnabled = false
589 c892003d Martin Sebela
590
  $('#dropdown-dataset .dropdown-item').each(function () {
591 2f227a6c ballakt
    const input = $(this).find('input')
592
    const inputVal = input[0].value
593 c892003d Martin Sebela
594 2f227a6c ballakt
    if (!(inputVal in available)) {
595
      $(this).addClass('disabled')
596
      $(input).prop('checked', false)
597 1774c06d Tomáš Ballák
    } else {
598 2f227a6c ballakt
      leastOneOptionEnabled = true
599
      $(this).removeClass('disabled')
600 5d599617 vastja
    }
601 8feb1753 ballakt
  })
602 dfe43218 vastja
603 94c6eb49 Martin Sebela
  $('#btn-update-heatmap').prop('disabled', !leastOneOptionEnabled)
604 03c02899 vastja
}
605 0a828a5a Martin Sebela
606 8feb1753 ballakt
function formatDate (date) {
607
  var day = String(date.getDate())
608
  var month = String(date.getMonth() + 1)
609 0a828a5a Martin Sebela
610
  if (day.length === 1) {
611 8feb1753 ballakt
    day = '0' + day
612 0a828a5a Martin Sebela
  }
613
614
  if (month.length === 1) {
615 8feb1753 ballakt
    month = '0' + month
616 0a828a5a Martin Sebela
  }
617
618 8feb1753 ballakt
  return date.getFullYear() + '-' + month + '-' + day
619 0a828a5a Martin Sebela
}
620
621 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
622
function initDatepicker (availableDatesSource) {
623
  var availableDates = ''
624 0a828a5a Martin Sebela
625
  $.ajax({
626
    type: 'GET',
627
    url: availableDatesSource,
628 8feb1753 ballakt
    success: function (result) {
629
      availableDates = String(result).split(',')
630 0a828a5a Martin Sebela
    }
631 a7e04778 Martin Sebela
  }).then(function () {
632
    $('#date').datepicker({
633
      format: 'yyyy-mm-dd',
634
      language: 'cs',
635 8feb1753 ballakt
      beforeShowDay: function (date) {
636 a7e04778 Martin Sebela
        if (availableDates.indexOf(formatDate(date)) < 0) {
637 8feb1753 ballakt
          return { enabled: false, tooltip: 'Žádná data' }
638 1774c06d Tomáš Ballák
        } else {
639 8feb1753 ballakt
          return { enabled: true }
640 a7e04778 Martin Sebela
        }
641
      },
642
      autoclose: true
643 8feb1753 ballakt
    })
644
  })
645
}
646 dd652e61 Martin Sebela
647 81980e82 ballakt
function initLocationsMenu () {
648
  var locationsWrapper = '.locations'
649
  var locationsDisplayClass = 'show'
650 dd652e61 Martin Sebela
651 81980e82 ballakt
  if ($(window).width() <= 480) {
652
    $(locationsWrapper).removeClass(locationsDisplayClass)
653 1774c06d Tomáš Ballák
  } else {
654 81980e82 ballakt
    $(locationsWrapper).addClass(locationsDisplayClass)
655 dd652e61 Martin Sebela
  }
656 4e003182 Martin Sebela
}
657
658 2f227a6c ballakt
function onDocumentReady () {
659 c892003d Martin Sebela
  $('#dropdown-dataset').on('click', function (e) {
660 2f227a6c ballakt
    e.stopPropagation()
661
  })
662 1cf1413d ballakt
663 94c6eb49 Martin Sebela
  $('#btn-update-heatmap').prop('name', '')
664 1774c06d Tomáš Ballák
  changeCurrentTime()
665
  setTimeline()
666
  changeCurrentDate()
667 1cf1413d ballakt
  onValueChangeRegister()
668
}
669 c892003d Martin Sebela
670 1cf1413d ballakt
const loadCheckboxDatasetNameData = () => {
671 2f227a6c ballakt
  datasetSelected = []
672 c892003d Martin Sebela
  $('#dropdown-dataset .dropdown-item').each(function () {
673 2f227a6c ballakt
    const input = $(this).find('input')
674
    const inputVal = input[0].value
675 c892003d Martin Sebela
676 2f227a6c ballakt
    if (input[0].checked) {
677
      datasetSelected.push(inputVal)
678
    }
679 c892003d Martin Sebela
680 883a423e Tomáš Ballák
    datasetDictNameDisplayName[inputVal] = $(input).data('dataset-display-name')
681 2f227a6c ballakt
  })
682
}