Projekt

Obecné

Profil

Stáhnout (10 KB) Statistiky
| Větev: | Revize:
1 8feb1753 ballakt
/* global L */
2
/* global $ */
3
var mymap
4
var heatmapLayer = null
5
var marksLayer = null
6 03c02899 vastja
7 8feb1753 ballakt
var startX = 49.7248
8
var startY = 13.3521
9
var startZoom = 17
10 3fc08f2d vastja
11 8feb1753 ballakt
var dataSourceRoute
12
var currentTime
13
var name
14
var date
15 a48642fb vastja
16 8feb1753 ballakt
var timer
17
var isAnimationRunning = false
18
var data = []
19 a48642fb vastja
20 084a5972 ballakt
// holds all instances of markers for bind/unbind popup purpose
21
// contains: {key:[L.circle,L.pupup]}
22
// key: x and y, x + '' + y string
23 8feb1753 ballakt
const globalMarkersHolder = {}
24 084a5972 ballakt
25 8feb1753 ballakt
// all marker from which popup was removed
26 084a5972 ballakt
// contains: {key:[L.circle,L.pupup]}
27
// key: x and y, x + '' + y string
28 8feb1753 ballakt
let globalMarkersChanged = {}
29 084a5972 ballakt
30
const genPopUpControls = (controls) => {
31
  return `<div class="popup-controls">${controls.reduce((sum, item) => sum + item, '')}</div>`
32
}
33
const genPopUp = (place, number, sum, currentPos, maxPos) => {
34 8feb1753 ballakt
  const header = `<strong>Zařízení a počet:</strong><div id="place-info">${place}</div>`
35
  const currentNum = `<span id="digit-info">${number}</span>`
36 90d3db28 Tomáš Ballák
  // eslint-disable-next-line eqeqeq
37
  const sumNum = `<span id="total-info" style="font-size: large">${(sum && (sum != number)) ? '/' + sum : ''}</span>`
38 8feb1753 ballakt
  const digitInfo = `<div id="number-info">${currentNum}${sumNum}</div>`
39
  let previousButton = '<button id="previous-info-btn" class="circle-button" onclick="previousInfo()"></button>'
40
  let nextButton = '<button id="next-info-btn" onclick="nextInfo()" class="circle-button next"></button>'
41
  let posInfo = `<div id="count-info">${currentPos} z ${maxPos}</div>`
42 084a5972 ballakt
43
  if (!sum) {
44 8feb1753 ballakt
    previousButton = ''
45
    nextButton = ''
46
    posInfo = ''
47 084a5972 ballakt
  }
48
  return `
49
  ${header}
50
  ${digitInfo}
51
  ${genPopUpControls([previousButton, posInfo, nextButton])}
52
  `
53
}
54 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
55
function initMap () {
56 90d3db28 Tomáš Ballák
  startX = localStorage.getItem('lat') || startX
57
  startY = localStorage.getItem('lng') || startY
58
  startZoom = localStorage.getItem('zoom') || startZoom
59 72a438f3 vastja
60 8feb1753 ballakt
  mymap = L.map('heatmap').setView([startX, startY], startZoom)
61 3fc08f2d vastja
62 c236b33a msebela
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
63
    attribution: '',
64
    maxZoom: 19
65 8feb1753 ballakt
  }).addTo(mymap)
66 3ae59f75 vastja
67 8feb1753 ballakt
  mymap.on('click', showInfo)
68 c236b33a msebela
}
69 3fc08f2d vastja
70 8feb1753 ballakt
var info = []
71
var currenInfo = 0
72 3ae59f75 vastja
73 8feb1753 ballakt
function showInfo (e) {
74 3ae59f75 vastja
  info = []
75 8feb1753 ballakt
  currenInfo = 0
76 3ae59f75 vastja
77
  // https://wiki.openstreetmap.org/wiki/Zoom_levels
78
  // Todo change to variable - it is used in heatmap init
79 8feb1753 ballakt
  var stile = 40075016.686 * Math.cos(startX) / Math.pow(2, mymap.getZoom())
80
  var radius = 25 * stile / 256
81 3ae59f75 vastja
82 8feb1753 ballakt
  var i = 0
83
  var lat = 0
84
  var lng = 0
85 3ae59f75 vastja
86 8feb1753 ballakt
  var total = 0
87
  data[currentTime].items.forEach(element => {
88 3ae59f75 vastja
    if (e.latlng.distanceTo(new L.LatLng(element.x, element.y)) < radius) {
89
      lat += element.x
90 8feb1753 ballakt
      lng += element.y
91
      info[i] = { place: element.place, number: element.number }
92
      total += parseInt(element.number)
93
      i++
94 3ae59f75 vastja
    }
95 8feb1753 ballakt
  })
96 3ae59f75 vastja
97
  if (info.length > 0) {
98 8feb1753 ballakt
    const { place, number } = info[currenInfo]
99
    L.popup({
100 dfcface9 Tomáš Ballák
      autoPan: false
101 8feb1753 ballakt
    })
102
      .setLatLng([lat / i, lng / i])
103
      .setContent(genPopUp(place, number, total, currenInfo + 1, info.length))
104
      .openOn(mymap)
105
106
    if (info.length === 1) {
107
      $('#previous-info-btn').prop('disabled', true)
108
      $('#next-info-btn').prop('disabled', true)
109
      $('.popup-controls').hide()
110 3ae59f75 vastja
    }
111
  }
112
}
113
114 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
115
function previousInfo () {
116
  currenInfo = (currenInfo + info.length - 1) % info.length
117
  displayInfoText()
118 3ae59f75 vastja
}
119
120 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
121
function nextInfo () {
122 3ae59f75 vastja
  currenInfo = (currenInfo + 1) % info.length
123 8feb1753 ballakt
  displayInfoText()
124 3ae59f75 vastja
}
125
126 8feb1753 ballakt
function displayInfoText () {
127 bc7738cd Martin Sebela
  $('#place-info').html(info[currenInfo].place)
128 61ff7718 vastja
  $('#digit-info').html(info[currenInfo].number)
129 8feb1753 ballakt
  $('#count-info').html(currenInfo + 1 + ' z ' + info.length)
130 3ae59f75 vastja
}
131 351696d5 Martin Sebela
132 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
133 72a438f3 vastja
function setMapView (latitude, longitude, zoom) {
134 90d3db28 Tomáš Ballák
  localStorage.setItem('lat', latitude)
135
  localStorage.setItem('lng', longitude)
136
  localStorage.setItem('zoom', zoom)
137 8feb1753 ballakt
  mymap.setView([latitude, longitude], zoom)
138 3fc08f2d vastja
}
139
140 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
141
function changeAnimationState () {
142 a48642fb vastja
  isAnimationRunning = !isAnimationRunning
143
  if (isAnimationRunning) {
144 8feb1753 ballakt
    $('#play-pause').attr('class', 'pause')
145 a48642fb vastja
    timer = setInterval(
146 8feb1753 ballakt
      function () {
147
        next()
148 a48642fb vastja
      },
149
      800
150 8feb1753 ballakt
    )
151
  } else {
152
    clearTimeout(timer)
153
    $('#play-pause').attr('class', 'play')
154 351696d5 Martin Sebela
  }
155
}
156
157 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
158
function previous () {
159
  currentTime = (currentTime + 23) % 24
160
  drawHeatmap(data[currentTime])
161
  setTimeline()
162
  mymap.closePopup()
163
  updateHeaderControls()
164
  changeUrl()
165 a48642fb vastja
}
166
167 8feb1753 ballakt
function next () {
168
  currentTime = (currentTime + 1) % 24
169
  drawHeatmap(data[currentTime])
170
  setTimeline()
171
  mymap.closePopup()
172
  updateHeaderControls()
173
  changeUrl()
174 8b840eb7 vastja
}
175
176 8feb1753 ballakt
function changeUrl () {
177 8b840eb7 vastja
  window.history.pushState(
178 8feb1753 ballakt
    '',
179 8b840eb7 vastja
    document.title,
180 8feb1753 ballakt
    window.location.origin + window.location.pathname + `?data_set[date]=${$('#date').val()}&data_set[time]=${currentTime}&data_set[type]=${$('#type').children('option:selected').val()}`
181
  )
182 4e8c0e5b Martin Sebela
}
183
184 8feb1753 ballakt
function updateHeaderControls () {
185
  document.getElementById('time').value = currentTime
186 a48642fb vastja
}
187 351696d5 Martin Sebela
188 8feb1753 ballakt
function setTimeline () {
189
  $('#timeline').text(currentTime + ':00')
190
  $('#timeline').attr('class', 'time hour-' + currentTime)
191 351696d5 Martin Sebela
}
192
193 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
194
function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
195
  dataSourceRoute = opendataRoute
196
  data = []
197 64bc2934 vastja
198 8feb1753 ballakt
  name = $('#type').children('option:selected').val()
199 03ccdd65 vastja
  date = $('#date').val()
200 8feb1753 ballakt
  currentTime = parseInt($('#time').children('option:selected').val())
201
  setTimeline()
202 61ff7718 vastja
  $.ajax({
203
    type: 'POST',
204
    url: positionsRoute + '/' + name,
205 8feb1753 ballakt
    success: function (result) {
206
      drawDataSourceMarks(result)
207 084a5972 ballakt
      $.ajax({
208 8feb1753 ballakt
        type: 'POST',
209
        url: dataSourceRoute + '/' + name + '/' + date + '/' + currentTime,
210
        success: function (result) {
211
          data[currentTime] = result
212
          drawHeatmap(data[currentTime])
213 084a5972 ballakt
        }
214
      })
215 61ff7718 vastja
    }
216 8feb1753 ballakt
  })
217 a48642fb vastja
218 8feb1753 ballakt
  preload(currentTime, 1)
219
  preload(currentTime, -1)
220 a48642fb vastja
}
221
222 8feb1753 ballakt
function drawDataSourceMarks (data) {
223 61ff7718 vastja
  if (marksLayer != null) {
224 8feb1753 ballakt
    L.removeLayer(marksLayer)
225 61ff7718 vastja
  }
226 8feb1753 ballakt
  marksLayer = L.layerGroup()
227 61ff7718 vastja
  for (var key in data) {
228 8feb1753 ballakt
    const { x, y, name } = data[key]
229
    const pop =
230
      L.popup({ autoPan: false })
231 084a5972 ballakt
        .setLatLng([x, y])
232 8feb1753 ballakt
        .setContent(genPopUp(name, 0, 0, 1, 1))
233
    const newCircle =
234
      L.circle([x, y], { radius: 2, fillOpacity: 0.8, color: '#004fb3', fillColor: '#004fb3', bubblingMouseEvents: true })
235
        .bindPopup(pop)
236
    globalMarkersHolder[x + '' + y] = [newCircle, pop] // add new marker to global holders
237 084a5972 ballakt
    marksLayer.addLayer(
238
      newCircle
239 8feb1753 ballakt
    )
240 61ff7718 vastja
  }
241
242 8feb1753 ballakt
  marksLayer.setZIndex(-1).addTo(mymap)
243 61ff7718 vastja
}
244
245 8feb1753 ballakt
function preload (time, change) {
246
  var ntime = time + change
247
  if (ntime >= 0 && ntime <= 23) {
248
    $.ajax({
249
      type: 'POST',
250
      url: dataSourceRoute + '/' + name + '/' + date + '/' + ntime,
251
      success: function (result) {
252
        data[ntime] = result
253
        preload(ntime, change)
254
      }
255
    })
256 a48642fb vastja
  }
257 3fc08f2d vastja
}
258
259 8feb1753 ballakt
function drawHeatmap (data) {
260 03c02899 vastja
  // Todo still switched
261 8feb1753 ballakt
  if (data.items != null) {
262
    // Bind back popups for markers (we dont know if there is any data for this marker or not)
263
    if (Object.keys(globalMarkersChanged).length) {
264
      Object.keys(globalMarkersChanged).forEach(function (key) {
265
        globalMarkersChanged[key][0].bindPopup(globalMarkersChanged[key][1])
266
      })
267
      globalMarkersChanged = {}
268 084a5972 ballakt
    }
269 8feb1753 ballakt
    const points = data.items.map((point) => {
270
      const { x, y, number } = point
271
      const key = x + '' + y
272
      const holder = globalMarkersHolder[key]
273
      if (!globalMarkersChanged[key] && number) {
274
        // There is data for this marker => unbind popup with zero value
275
        holder[0] = holder[0].unbindPopup()
276
        globalMarkersChanged[key] = holder
277 084a5972 ballakt
      }
278 8feb1753 ballakt
      return [x, y, number]
279
    })
280 a48642fb vastja
    if (heatmapLayer != null) {
281 8feb1753 ballakt
      mymap.removeLayer(heatmapLayer)
282 a48642fb vastja
    }
283 8feb1753 ballakt
    heatmapLayer = L.heatLayer(points, { max: data.max, minOpacity: 0.5, radius: 35, blur: 30 }).addTo(mymap)
284
  } else {
285 a48642fb vastja
    if (heatmapLayer != null) {
286 8feb1753 ballakt
      mymap.removeLayer(heatmapLayer)
287 a48642fb vastja
    }
288
  }
289
290 03c02899 vastja
  // var heat_01 = ...
291
  // on background map.addLayer(heat_01) -> map.removeLayer(heat_01);
292 64bc2934 vastja
  // $(.leaflet-heatmap-layer).css('opacity', 'value');
293 03c02899 vastja
}
294 3fc08f2d vastja
295 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
296
function checkDataSetsAvailability (route) {
297 03c02899 vastja
  $.ajax({
298 8feb1753 ballakt
    type: 'POST',
299 03c02899 vastja
    // Todo it might be good idea to change db collections format
300 03ccdd65 vastja
    url: route + '/' + $('#date').val(),
301 8feb1753 ballakt
    success: function (result) {
302
      updateAvailableDataSets(result)
303 03c02899 vastja
    }
304 8feb1753 ballakt
  })
305 03c02899 vastja
}
306
307 8feb1753 ballakt
var allOptionsDisabled = false
308 2dd5d57f vastja
309 8feb1753 ballakt
function updateAvailableDataSets (available) {
310
  var isOptionEnabled = true
311
  $('#type > option').each(function () {
312
    if ((this.value in available) === false) {
313
      $(this).prop('disabled', true)
314
      $(this).prop('selected', false)
315
    } else {
316 5d599617 vastja
      $(this).prop('disabled', false)
317 2dd5d57f vastja
      if (allOptionsDisabled) {
318 8feb1753 ballakt
        $(this).prop('selected', true)
319
        allOptionsDisabled = false
320 2dd5d57f vastja
      }
321 8feb1753 ballakt
      isOptionEnabled = false
322 5d599617 vastja
    }
323 8feb1753 ballakt
  })
324
  allOptionsDisabled = isOptionEnabled
325 dfe43218 vastja
326 8feb1753 ballakt
  $('#submit-btn').prop('disabled', isOptionEnabled)
327 03c02899 vastja
}
328 0a828a5a Martin Sebela
329 8feb1753 ballakt
function formatDate (date) {
330
  var day = String(date.getDate())
331
  var month = String(date.getMonth() + 1)
332 0a828a5a Martin Sebela
333
  if (day.length === 1) {
334 8feb1753 ballakt
    day = '0' + day
335 0a828a5a Martin Sebela
  }
336
337
  if (month.length === 1) {
338 8feb1753 ballakt
    month = '0' + month
339 0a828a5a Martin Sebela
  }
340
341 8feb1753 ballakt
  return date.getFullYear() + '-' + month + '-' + day
342 0a828a5a Martin Sebela
}
343
344 8feb1753 ballakt
// eslint-disable-next-line no-unused-vars
345
function initDatepicker (availableDatesSource) {
346
  var availableDates = ''
347 0a828a5a Martin Sebela
348
  $.ajax({
349
    type: 'GET',
350
    url: availableDatesSource,
351 8feb1753 ballakt
    success: function (result) {
352
      availableDates = String(result).split(',')
353 0a828a5a Martin Sebela
    }
354 a7e04778 Martin Sebela
  }).then(function () {
355
    $('#date').datepicker({
356
      format: 'yyyy-mm-dd',
357
      language: 'cs',
358 8feb1753 ballakt
      beforeShowDay: function (date) {
359 a7e04778 Martin Sebela
        if (availableDates.indexOf(formatDate(date)) < 0) {
360 8feb1753 ballakt
          return { enabled: false, tooltip: 'Žádná data' }
361
        } else {
362
          return { enabled: true }
363 a7e04778 Martin Sebela
        }
364
      },
365
      autoclose: true
366 8feb1753 ballakt
    })
367
  })
368
}
369 dd652e61 Martin Sebela
370
function initLocationsMenu() {
371
  var locationsWrapper = '.locations';
372
  var locationsDisplayClass = 'show';
373
374
  if ($(window).width() <= 480) {  
375
    $(locationsWrapper).removeClass(locationsDisplayClass);
376
  }
377
  else {
378
    $(locationsWrapper).addClass(locationsDisplayClass);
379
  }
380
}