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
    $('#dropdown-time input[type="radio"]:checked').each(function () {
55
      currentTime = parseInt($(this).val())
56
    })
57
  }
58
}
59
60
const changeCurrentDate = (date = null) => {
61
  if (date) {
62
    currentDate = new Date(date)
63
  } else {
64
    currentDate = new Date($('#date').val())
65
  }
66
  $('#player-date span').html(`${currentDate.getDate()}. ${currentDate.getMonth() + 1}. ${currentDate.getFullYear()}`)
67
  $('#date').val(currentDateToString())
68
  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 8feb1753 ballakt
    $('#play-pause').attr('class', 'pause')
372 1774c06d Tomáš Ballák
    timer = setInterval(function () { next() }, 800)
373
  } else {
374 8feb1753 ballakt
    clearTimeout(timer)
375
    $('#play-pause').attr('class', '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
  $('#timeline').text(currentTime + ':00')
428
  $('#timeline').attr('class', 'time hour-' + currentTime)
429 351696d5 Martin Sebela
}
430 1774c06d Tomáš Ballák
const onChangeHour = (hour) => {
431
  changeHour(hour)
432
  drawHeatmap(data[currentTime])
433
}
434
const changeHour = (hour) => {
435
  changeCurrentTime(hour)
436 c892003d Martin Sebela
  updateHeaderControls()
437
  setTimeline()
438
  changeUrl()
439
}
440
441 70a3df53 vastja
/**
442
 * Load and display heatmap layer for current data
443
 * @param {string} opendataRoute route to dataset source
444
 * @param {string} positionsRoute  route to dataset postitions source
445
 */
446 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
447 2f227a6c ballakt
async function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
448 1cf1413d ballakt
  loadCheckboxDatasetNameData()
449 c892003d Martin Sebela
450 8feb1753 ballakt
  dataSourceRoute = opendataRoute
451 1cf1413d ballakt
  positionsSourceRoute = positionsRoute
452 2f227a6c ballakt
  const allPromises = []
453
  data[currentTime] = {}
454 1774c06d Tomáš Ballák
455 2f227a6c ballakt
  const dataSelectedHandler = async (datasetName) => {
456 1774c06d Tomáš Ballák
    if (!(datasetName in dataSourceMarks)) {
457
      dataSourceMarks[datasetName] = await fetchDataSourceMarks(positionsRoute, datasetName)
458
    }
459
    const datasetData = await fetchByNameDate(dataSourceRoute, datasetName, currentDateToString(), currentTime)
460 2f227a6c ballakt
    data[currentTime][datasetName] = datasetData
461
  }
462 1774c06d Tomáš Ballák
  datasetSelected.forEach((datasetName) => {
463 2f227a6c ballakt
    allPromises.push(dataSelectedHandler(datasetName))
464 8feb1753 ballakt
  })
465 c892003d Martin Sebela
466 1774c06d Tomáš Ballák
  loadingY()
467 2f227a6c ballakt
  Promise.all(allPromises).then(
468
    () => {
469 1774c06d Tomáš Ballák
      loadingN()
470 2f227a6c ballakt
      drawDataSourceMarks(dataSourceMarks)
471
      drawHeatmap(data[currentTime])
472 1774c06d Tomáš Ballák
      preload(currentTime, 1, currentDateToString())
473
      preload(currentTime, -1, currentDateToString())
474 2f227a6c ballakt
    }
475
  )
476 a48642fb vastja
}
477
478 8feb1753 ballakt
function drawDataSourceMarks (data) {
479 61ff7718 vastja
  if (marksLayer != null) {
480 1cf1413d ballakt
    mymap.removeLayer(marksLayer)
481 61ff7718 vastja
  }
482 c892003d Martin Sebela
483 8feb1753 ballakt
  marksLayer = L.layerGroup()
484 c892003d Martin Sebela
485 2f227a6c ballakt
  Object.keys(data).forEach((key_) => {
486
    for (var key in data[key_]) {
487
      const { x, y, name } = data[key_][key]
488
      const pop =
489
          prepareLayerPopUp(x, y, 1, `popup-${key_}`)
490 883a423e Tomáš Ballák
            .setContent(genPopUp(datasetDictNameDisplayName[key_], name, 0, 0, 1, 1))
491 2f227a6c ballakt
      const newCircle =
492
        L.circle([x, y], { radius: 2, fillOpacity: 0.8, color: '#004fb3', fillColor: '#004fb3', bubblingMouseEvents: true })
493
          .bindPopup(pop)
494
      globalMarkersHolder[x + '' + y] = [newCircle, pop] // add new marker to global holders
495
      marksLayer.addLayer(
496
        newCircle
497
      )
498
    }
499
  })
500 61ff7718 vastja
501 8feb1753 ballakt
  marksLayer.setZIndex(-1).addTo(mymap)
502 61ff7718 vastja
}
503
504 2f227a6c ballakt
async function preload (time, change, date) {
505 1774c06d Tomáš Ballák
  loadingY()
506 2f227a6c ballakt
  for (let nTime = time + change; nTime >= 0 && nTime <= 23; nTime = nTime + change) {
507
    if (!data[nTime]) {
508
      data[nTime] = {}
509
    }
510 c892003d Martin Sebela
511 1cf1413d ballakt
    datasetSelected.forEach(async (datasetName) => {
512
      if (!data[nTime][datasetName]) {
513
        data[nTime][datasetName] = await fetchByNameDate(dataSourceRoute, datasetName, date, nTime)
514
      }
515
    })
516 a48642fb vastja
  }
517 1774c06d Tomáš Ballák
  loadingN()
518 3fc08f2d vastja
}
519
520 2f227a6c ballakt
function drawHeatmap (dataRaw) {
521 03c02899 vastja
  // Todo still switched
522 2f227a6c ballakt
  const dataDict = dataRaw
523
  const mergedPoints = []
524
  let max = 0
525 1774c06d Tomáš Ballák
526 d5a88af0 Tomáš Ballák
  if (Object.keys(globalMarkersChanged).length) {
527
    Object.keys(globalMarkersChanged).forEach(function (key) {
528
      globalMarkersChanged[key][0].bindPopup(globalMarkersChanged[key][1])
529
    })
530
    globalMarkersChanged = {}
531
  }
532 c892003d Martin Sebela
533 2f227a6c ballakt
  Object.keys(dataDict).forEach((key) => {
534
    const data = dataDict[key]
535
    max = Math.max(max, data.max)
536 c892003d Martin Sebela
537 2f227a6c ballakt
    if (data != null) {
538 8feb1753 ballakt
    // Bind back popups for markers (we dont know if there is any data for this marker or not)
539 2f227a6c ballakt
      const points = data.items.map((point) => {
540
        const { x, y, number } = point
541
        const key = x + '' + y
542
        const holder = globalMarkersHolder[key]
543 c892003d Martin Sebela
544 2f227a6c ballakt
        if (!globalMarkersChanged[key] && number) {
545 8feb1753 ballakt
        // There is data for this marker => unbind popup with zero value
546 2f227a6c ballakt
          holder[0] = holder[0].unbindPopup()
547
          globalMarkersChanged[key] = holder
548
        }
549 c892003d Martin Sebela
550 2f227a6c ballakt
        return [x, y, number]
551
      })
552
      mergedPoints.push(...points)
553 1774c06d Tomáš Ballák
    } else {
554 2f227a6c ballakt
      if (heatmapLayer != null) {
555
        mymap.removeLayer(heatmapLayer)
556 084a5972 ballakt
      }
557 a48642fb vastja
    }
558 2f227a6c ballakt
  })
559 c892003d Martin Sebela
560 2f227a6c ballakt
  if (heatmapLayer != null) {
561
    mymap.removeLayer(heatmapLayer)
562
  }
563 c892003d Martin Sebela
564 2f227a6c ballakt
  if (mergedPoints.length) {
565
    heatmapLayer = L.heatLayer(mergedPoints, { max: max, minOpacity: 0.5, radius: 35, blur: 30 }).addTo(mymap)
566 a48642fb vastja
  }
567 03c02899 vastja
}
568 3fc08f2d vastja
569 70a3df53 vastja
/**
570
 * Checks dataset availibility
571 81980e82 ballakt
 * @param {string} route authority for datasets availibility checks
572 70a3df53 vastja
 */
573 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
574
function checkDataSetsAvailability (route) {
575 03c02899 vastja
  $.ajax({
576 8feb1753 ballakt
    type: 'POST',
577 03c02899 vastja
    // Todo it might be good idea to change db collections format
578 1774c06d Tomáš Ballák
    url: route + '/' + currentDateToString(),
579 8feb1753 ballakt
    success: function (result) {
580
      updateAvailableDataSets(result)
581 03c02899 vastja
    }
582 8feb1753 ballakt
  })
583 03c02899 vastja
}
584
585 8feb1753 ballakt
function updateAvailableDataSets (available) {
586 2f227a6c ballakt
  let leastOneOptionEnabled = false
587 c892003d Martin Sebela
588
  $('#dropdown-dataset .dropdown-item').each(function () {
589 2f227a6c ballakt
    const input = $(this).find('input')
590
    const inputVal = input[0].value
591 c892003d Martin Sebela
592 2f227a6c ballakt
    if (!(inputVal in available)) {
593
      $(this).addClass('disabled')
594
      $(input).prop('checked', false)
595 1774c06d Tomáš Ballák
    } else {
596 2f227a6c ballakt
      leastOneOptionEnabled = true
597
      $(this).removeClass('disabled')
598 5d599617 vastja
    }
599 8feb1753 ballakt
  })
600 dfe43218 vastja
601 94c6eb49 Martin Sebela
  $('#btn-update-heatmap').prop('disabled', !leastOneOptionEnabled)
602 03c02899 vastja
}
603 0a828a5a Martin Sebela
604 8feb1753 ballakt
function formatDate (date) {
605
  var day = String(date.getDate())
606
  var month = String(date.getMonth() + 1)
607 0a828a5a Martin Sebela
608
  if (day.length === 1) {
609 8feb1753 ballakt
    day = '0' + day
610 0a828a5a Martin Sebela
  }
611
612
  if (month.length === 1) {
613 8feb1753 ballakt
    month = '0' + month
614 0a828a5a Martin Sebela
  }
615
616 8feb1753 ballakt
  return date.getFullYear() + '-' + month + '-' + day
617 0a828a5a Martin Sebela
}
618
619 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
620
function initDatepicker (availableDatesSource) {
621
  var availableDates = ''
622 0a828a5a Martin Sebela
623
  $.ajax({
624
    type: 'GET',
625
    url: availableDatesSource,
626 8feb1753 ballakt
    success: function (result) {
627
      availableDates = String(result).split(',')
628 0a828a5a Martin Sebela
    }
629 a7e04778 Martin Sebela
  }).then(function () {
630
    $('#date').datepicker({
631
      format: 'yyyy-mm-dd',
632
      language: 'cs',
633 8feb1753 ballakt
      beforeShowDay: function (date) {
634 a7e04778 Martin Sebela
        if (availableDates.indexOf(formatDate(date)) < 0) {
635 8feb1753 ballakt
          return { enabled: false, tooltip: 'Žádná data' }
636 1774c06d Tomáš Ballák
        } else {
637 8feb1753 ballakt
          return { enabled: true }
638 a7e04778 Martin Sebela
        }
639
      },
640
      autoclose: true
641 8feb1753 ballakt
    })
642
  })
643
}
644 dd652e61 Martin Sebela
645 81980e82 ballakt
function initLocationsMenu () {
646
  var locationsWrapper = '.locations'
647
  var locationsDisplayClass = 'show'
648 dd652e61 Martin Sebela
649 81980e82 ballakt
  if ($(window).width() <= 480) {
650
    $(locationsWrapper).removeClass(locationsDisplayClass)
651 1774c06d Tomáš Ballák
  } else {
652 81980e82 ballakt
    $(locationsWrapper).addClass(locationsDisplayClass)
653 dd652e61 Martin Sebela
  }
654 4e003182 Martin Sebela
}
655
656 2f227a6c ballakt
function onDocumentReady () {
657 c892003d Martin Sebela
  $('#dropdown-dataset').on('click', function (e) {
658 2f227a6c ballakt
    e.stopPropagation()
659
  })
660 1cf1413d ballakt
661 94c6eb49 Martin Sebela
  $('#btn-update-heatmap').prop('name', '')
662 1774c06d Tomáš Ballák
  changeCurrentTime()
663
  setTimeline()
664
  changeCurrentDate()
665 1cf1413d ballakt
  onValueChangeRegister()
666
}
667 c892003d Martin Sebela
668 1cf1413d ballakt
const loadCheckboxDatasetNameData = () => {
669 2f227a6c ballakt
  datasetSelected = []
670 c892003d Martin Sebela
  $('#dropdown-dataset .dropdown-item').each(function () {
671 2f227a6c ballakt
    const input = $(this).find('input')
672
    const inputVal = input[0].value
673 c892003d Martin Sebela
674 2f227a6c ballakt
    if (input[0].checked) {
675
      datasetSelected.push(inputVal)
676
    }
677 c892003d Martin Sebela
678 883a423e Tomáš Ballák
    datasetDictNameDisplayName[inputVal] = $(input).data('dataset-display-name')
679 2f227a6c ballakt
  })
680
}