Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 8feb1753

Přidáno uživatelem Tomáš Ballák před asi 4 roky(ů)

Feature gui changes haeder + linter for js

Zobrazit rozdíly:

website/public/js/zcu-heatmap.js
1
var mymap;
2
var heatmapLayer = null;
3
var marksLayer = null;
1
/* global L */
2
/* global $ */
3
var mymap
4
var heatmapLayer = null
5
var marksLayer = null
4 6

  
5
var startX = 49.7248;
6
var startY = 13.3521;
7
var startZoom = 17;
7
var startX = 49.7248
8
var startY = 13.3521
9
var startZoom = 17
8 10

  
9
var dataSourceRoute;
10
var currentTime;
11
var name;
12
var date;
11
var dataSourceRoute
12
var currentTime
13
var name
14
var date
13 15

  
14
var timer;
15
var isAnimationRunning = false;
16
var data = [];
16
var timer
17
var isAnimationRunning = false
18
var data = []
17 19

  
18 20
// holds all instances of markers for bind/unbind popup purpose
19 21
// contains: {key:[L.circle,L.pupup]}
20 22
// key: x and y, x + '' + y string
21
const globalMarkersHolder = {};
23
const globalMarkersHolder = {}
22 24

  
23
//all marker from which popup was removed 
25
// all marker from which popup was removed
24 26
// contains: {key:[L.circle,L.pupup]}
25 27
// key: x and y, x + '' + y string
26
let globalMarkersChanged = {};
28
let globalMarkersChanged = {}
27 29

  
28 30
const genPopUpControls = (controls) => {
29 31
  return `<div class="popup-controls">${controls.reduce((sum, item) => sum + item, '')}</div>`
30 32
}
31 33
const genPopUp = (place, number, sum, currentPos, maxPos) => {
32
  const header = `<strong>Zařízení a počet:</strong><div id="place-info">${place}</div>`;
33
  const currentNum = `<span id="digit-info">${number}</span>`;
34
  const sumNum = `<span id="total-info" style="font-size: large">${sum ? '/'+sum : '' }</span>`;
35
  const digitInfo = `<div id="number-info">${currentNum}${sumNum}</div>`;
36
  let previousButton = `<button id="previous-info-btn" class="circle-button" onclick="previousInfo()"></button>`;
37
  let nextButton = `<button id="next-info-btn" onclick="nextInfo()" class="circle-button next"></button>`;
38
  let posInfo = `<div id="count-info">${currentPos} z ${maxPos}</div>`;
34
  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
  const sumNum = `<span id="total-info" style="font-size: large">${sum ? '/' + sum : ''}</span>`
37
  const digitInfo = `<div id="number-info">${currentNum}${sumNum}</div>`
38
  let previousButton = '<button id="previous-info-btn" class="circle-button" onclick="previousInfo()"></button>'
39
  let nextButton = '<button id="next-info-btn" onclick="nextInfo()" class="circle-button next"></button>'
40
  let posInfo = `<div id="count-info">${currentPos} z ${maxPos}</div>`
39 41

  
40 42
  if (!sum) {
41
    previousButton = '';
42
    nextButton = '';
43
    posInfo = '';
43
    previousButton = ''
44
    nextButton = ''
45
    posInfo = ''
44 46
  }
45 47
  return `
46 48
  ${header}
......
48 50
  ${genPopUpControls([previousButton, posInfo, nextButton])}
49 51
  `
50 52
}
51
function initMap() {
52
  mymap = L.map('heatmap').setView([startX, startY], startZoom);
53
// eslint-disable-next-line no-unused-vars
54
function initMap () {
55
  mymap = L.map('heatmap').setView([startX, startY], startZoom)
53 56

  
54 57
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
55 58
    attribution: '',
56 59
    maxZoom: 19
57
  }).addTo(mymap);
58

  
59
  mymap.on('click', showInfo);
60
  }).addTo(mymap)
60 61

  
62
  mymap.on('click', showInfo)
61 63
}
62 64

  
63
var info = [];
64
var currenInfo = 0;
65
var infoLength = 0;
66

  
67
function showInfo(e) {
65
var info = []
66
var currenInfo = 0
68 67

  
68
function showInfo (e) {
69 69
  info = []
70
  currenInfo = 0;
70
  currenInfo = 0
71 71

  
72 72
  // https://wiki.openstreetmap.org/wiki/Zoom_levels
73 73
  // Todo change to variable - it is used in heatmap init
74
  var stile =  40075016.686 * Math.cos(startX) / Math.pow(2, mymap.getZoom()) ;
75
  var radius = 25 * stile / 256;
74
  var stile = 40075016.686 * Math.cos(startX) / Math.pow(2, mymap.getZoom())
75
  var radius = 25 * stile / 256
76 76

  
77
  var i = 0;
78
  var lat = 0;
79
  var lng = 0;
77
  var i = 0
78
  var lat = 0
79
  var lng = 0
80 80

  
81
  var total = 0;
82
  data[currentTime]['items'].forEach(element => {
81
  var total = 0
82
  data[currentTime].items.forEach(element => {
83 83
    if (e.latlng.distanceTo(new L.LatLng(element.x, element.y)) < radius) {
84 84
      lat += element.x
85
      lng += element.y;
86
      info[i] = {'place' : element.place, 'number' : element.number};
87
      total += parseInt(element.number);
88
      i++;
85
      lng += element.y
86
      info[i] = { place: element.place, number: element.number }
87
      total += parseInt(element.number)
88
      i++
89 89
    }
90
  });
90
  })
91 91

  
92
  
93 92
  if (info.length > 0) {
94
    const { place, number } = info[currenInfo];
95
    var popup = L.popup({
93
    const { place, number } = info[currenInfo]
94
    L.popup({
96 95
      autoPan: false
97
                  })
98
                  .setLatLng([lat / i, lng / i])
99
                  .setContent(genPopUp(place, number, total, currenInfo+1,info.length))
100
                  .openOn(mymap);
101
    
102
    if (info.length == 1) {
103
      $('#previous-info-btn').prop('disabled', true);
104
      $('#next-info-btn').prop('disabled', true);
105
      $('.popup-controls').hide();
96
    })
97
      .setLatLng([lat / i, lng / i])
98
      .setContent(genPopUp(place, number, total, currenInfo + 1, info.length))
99
      .openOn(mymap)
100

  
101
    if (info.length === 1) {
102
      $('#previous-info-btn').prop('disabled', true)
103
      $('#next-info-btn').prop('disabled', true)
104
      $('.popup-controls').hide()
106 105
    }
107 106
  }
108

  
109 107
}
110 108

  
111
function previousInfo() {
112
  currenInfo = (currenInfo + info.length - 1) % info.length;
113
  displayInfoText();
109
// eslint-disable-next-line no-unused-vars
110
function previousInfo () {
111
  currenInfo = (currenInfo + info.length - 1) % info.length
112
  displayInfoText()
114 113
}
115 114

  
116
function nextInfo() {
115
// eslint-disable-next-line no-unused-vars
116
function nextInfo () {
117 117
  currenInfo = (currenInfo + 1) % info.length
118
  displayInfoText();
118
  displayInfoText()
119 119
}
120 120

  
121
function displayInfoText() {
121
function displayInfoText () {
122 122
  $('#place-info').html(info[currenInfo].place)
123 123
  $('#digit-info').html(info[currenInfo].number)
124
  $('#count-info').html(currenInfo + 1 + ' z ' + info.length);
124
  $('#count-info').html(currenInfo + 1 + ' z ' + info.length)
125 125
}
126 126

  
127
function setMapView(latitude = startX, longitude = startY, zoom = startZoom) {
128
  mymap.setView([latitude, longitude], zoom);
127
// eslint-disable-next-line no-unused-vars
128
function setMapView (latitude = startX, longitude = startY, zoom = startZoom) {
129
  mymap.setView([latitude, longitude], zoom)
129 130
}
130 131

  
131
function changeAnimationState() {
132

  
132
// eslint-disable-next-line no-unused-vars
133
function changeAnimationState () {
133 134
  isAnimationRunning = !isAnimationRunning
134 135
  if (isAnimationRunning) {
135
    $('#play-pause').attr('class', 'pause');
136
    $('#play-pause').attr('class', 'pause')
136 137
    timer = setInterval(
137
      function() {
138
        next();
138
      function () {
139
        next()
139 140
      },
140 141
      800
141
    );
142
    )
143
  } else {
144
    clearTimeout(timer)
145
    $('#play-pause').attr('class', 'play')
142 146
  }
143
  else {
144
    clearTimeout(timer);
145
    $('#play-pause').attr('class', 'play');
146
  }
147

  
148

  
149 147
}
150 148

  
151
function previous() {
152
  currentTime = (currentTime + 23) % 24;
153
  drawHeatmap(data[currentTime]);
154
  setTimeline();
155
  mymap.closePopup();
156
  updateHeaderControls();
157
  changeUrl();
149
// eslint-disable-next-line no-unused-vars
150
function previous () {
151
  currentTime = (currentTime + 23) % 24
152
  drawHeatmap(data[currentTime])
153
  setTimeline()
154
  mymap.closePopup()
155
  updateHeaderControls()
156
  changeUrl()
158 157
}
159 158

  
160
function next() {
161
  currentTime = (currentTime + 1) % 24;
162
  drawHeatmap(data[currentTime]);
163
  setTimeline();
164
  mymap.closePopup();
165
  updateHeaderControls();
166
  changeUrl();
159
function next () {
160
  currentTime = (currentTime + 1) % 24
161
  drawHeatmap(data[currentTime])
162
  setTimeline()
163
  mymap.closePopup()
164
  updateHeaderControls()
165
  changeUrl()
167 166
}
168 167

  
169
function changeUrl() {
168
function changeUrl () {
170 169
  window.history.pushState(
171
    "",
170
    '',
172 171
    document.title,
173
    window.location.origin + window.location.pathname + `?data_set[date]=${$('#date').val()}&data_set[time]=${currentTime}&data_set[type]=${$('#type').children("option:selected").val()}`
174
  );
172
    window.location.origin + window.location.pathname + `?data_set[date]=${$('#date').val()}&data_set[time]=${currentTime}&data_set[type]=${$('#type').children('option:selected').val()}`
173
  )
175 174
}
176 175

  
177
function updateHeaderControls() {
178
  document.getElementById('time').value = currentTime;
176
function updateHeaderControls () {
177
  document.getElementById('time').value = currentTime
179 178
}
180 179

  
181
function setTimeline() {
182
  $('#timeline').text(currentTime + ":00");
183
  $('#timeline').attr('class', 'time hour-' + currentTime);
180
function setTimeline () {
181
  $('#timeline').text(currentTime + ':00')
182
  $('#timeline').attr('class', 'time hour-' + currentTime)
184 183
}
185 184

  
186
function loadCurrentTimeHeatmap(opendataRoute, positionsRoute) {
185
// eslint-disable-next-line no-unused-vars
186
function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
187
  dataSourceRoute = opendataRoute
188
  data = []
187 189

  
188
  dataSourceRoute = opendataRoute;
189
  data = [];
190

  
191
  name = $('#type').children("option:selected").val();
190
  name = $('#type').children('option:selected').val()
192 191
  date = $('#date').val()
193
  currentTime = parseInt($('#time').children("option:selected").val());
194
  setTimeline();
192
  currentTime = parseInt($('#time').children('option:selected').val())
193
  setTimeline()
195 194
  $.ajax({
196 195
    type: 'POST',
197 196
    url: positionsRoute + '/' + name,
198
    success: function(result) {
199
      drawDataSourceMarks(result);
197
    success: function (result) {
198
      drawDataSourceMarks(result)
200 199
      $.ajax({
201
        type: "POST",
202
        url: dataSourceRoute + '/' +  name + '/' + date + '/' + currentTime,
203
        success: function(result) {
204
          data[currentTime] = result;
205
          drawHeatmap(data[currentTime]);
200
        type: 'POST',
201
        url: dataSourceRoute + '/' + name + '/' + date + '/' + currentTime,
202
        success: function (result) {
203
          data[currentTime] = result
204
          drawHeatmap(data[currentTime])
206 205
        }
207 206
      })
208 207
    }
209
  });
210

  
211
  preload(currentTime, 1);
212
  preload(currentTime, -1);
208
  })
213 209

  
210
  preload(currentTime, 1)
211
  preload(currentTime, -1)
214 212
}
215 213

  
216
function drawDataSourceMarks(data) {
214
function drawDataSourceMarks (data) {
217 215
  if (marksLayer != null) {
218
    L.removeLayer(marksLayer);
216
    L.removeLayer(marksLayer)
219 217
  }
220
  marksLayer = L.layerGroup();
218
  marksLayer = L.layerGroup()
221 219
  for (var key in data) {
222
    const {x,y,name} = data[key];
223
    const pop = 
224
      L.popup({autoPan: false})
220
    const { x, y, name } = data[key]
221
    const pop =
222
      L.popup({ autoPan: false })
225 223
        .setLatLng([x, y])
226
        .setContent(genPopUp(name, 0, 0, 1,1));
227
    const newCircle = 
228
      L.circle([x, y], {radius: 2,fillOpacity: 0.8, color: '#004fb3',fillColor: '#004fb3', bubblingMouseEvents: true})
229
        .bindPopup(pop);
230
    globalMarkersHolder[x+''+y] = [newCircle, pop]; //add new marker to global holders
224
        .setContent(genPopUp(name, 0, 0, 1, 1))
225
    const newCircle =
226
      L.circle([x, y], { radius: 2, fillOpacity: 0.8, color: '#004fb3', fillColor: '#004fb3', bubblingMouseEvents: true })
227
        .bindPopup(pop)
228
    globalMarkersHolder[x + '' + y] = [newCircle, pop] // add new marker to global holders
231 229
    marksLayer.addLayer(
232 230
      newCircle
233
    );
231
    )
234 232
  }
235 233

  
236
  marksLayer.setZIndex(-1).addTo(mymap);
237

  
234
  marksLayer.setZIndex(-1).addTo(mymap)
238 235
}
239 236

  
240
function preload(time, change) {
241

  
242
  var ntime = time + change; 
243
  if (0 <=  ntime && ntime <= 23) {
244
      $.ajax({
245
        type: "POST",
246
        url: dataSourceRoute + '/' +  name + '/' + date + '/' + ntime,
247
        success: function(result) {
248
          data[ntime] = result;
249
          preload(ntime, change);
250
        }
251
      });
237
function preload (time, change) {
238
  var ntime = time + change
239
  if (ntime >= 0 && ntime <= 23) {
240
    $.ajax({
241
      type: 'POST',
242
      url: dataSourceRoute + '/' + name + '/' + date + '/' + ntime,
243
      success: function (result) {
244
        data[ntime] = result
245
        preload(ntime, change)
246
      }
247
    })
252 248
  }
253

  
254 249
}
255 250

  
256

  
257
function drawHeatmap(data) {
258

  
251
function drawHeatmap (data) {
259 252
  // Todo still switched
260
  if (data['items'] != null) {
261
    //Bind back popups for markers (we dont know if there is any data for this marker or not)
262
    if (Object.keys(globalMarkersChanged).length){
263
      Object.keys(globalMarkersChanged).forEach(function(key) {
264
        globalMarkersChanged[key][0].bindPopup(globalMarkersChanged[key][1]);
265
    });
266
      globalMarkersChanged = {};
253
  if (data.items != null) {
254
    // Bind back popups for markers (we dont know if there is any data for this marker or not)
255
    if (Object.keys(globalMarkersChanged).length) {
256
      Object.keys(globalMarkersChanged).forEach(function (key) {
257
        globalMarkersChanged[key][0].bindPopup(globalMarkersChanged[key][1])
258
      })
259
      globalMarkersChanged = {}
267 260
    }
268
    points = data['items'].map((point) => { 
269
      const {x,y,number} = point;
270
      const key = x+''+y;
271
      const holder = globalMarkersHolder[key];
272
      if (!globalMarkersChanged[key] && number){
273
        //There is data for this marker => unbind popup with zero value
274
        holder[0] = holder[0].unbindPopup();
275
        globalMarkersChanged[key] = holder;
261
    const points = data.items.map((point) => {
262
      const { x, y, number } = point
263
      const key = x + '' + y
264
      const holder = globalMarkersHolder[key]
265
      if (!globalMarkersChanged[key] && number) {
266
        // There is data for this marker => unbind popup with zero value
267
        holder[0] = holder[0].unbindPopup()
268
        globalMarkersChanged[key] = holder
276 269
      }
277
      return [x, y, number]; 
278
    });
270
      return [x, y, number]
271
    })
279 272
    if (heatmapLayer != null) {
280
      mymap.removeLayer(heatmapLayer);
273
      mymap.removeLayer(heatmapLayer)
281 274
    }
282
    heatmapLayer = L.heatLayer(points, {'max' : data['max'], 'minOpacity' : 0.5, 'radius' : 35, 'blur' : 30}).addTo(mymap);
283
  }
284
  else {
275
    heatmapLayer = L.heatLayer(points, { max: data.max, minOpacity: 0.5, radius: 35, blur: 30 }).addTo(mymap)
276
  } else {
285 277
    if (heatmapLayer != null) {
286
      mymap.removeLayer(heatmapLayer);
278
      mymap.removeLayer(heatmapLayer)
287 279
    }
288 280
  }
289 281

  
......
292 284
  // $(.leaflet-heatmap-layer).css('opacity', 'value');
293 285
}
294 286

  
295
function checkDataSetsAvailability(route) {
296

  
287
// eslint-disable-next-line no-unused-vars
288
function checkDataSetsAvailability (route) {
297 289
  $.ajax({
298
    type: "POST",
290
    type: 'POST',
299 291
    // Todo it might be good idea to change db collections format
300 292
    url: route + '/' + $('#date').val(),
301
    success: function(result) {
302
      updateAvailableDataSets(result);
293
    success: function (result) {
294
      updateAvailableDataSets(result)
303 295
    }
304
  });
296
  })
305 297
}
306 298

  
307
var allOptionsDisabled = false;
299
var allOptionsDisabled = false
308 300

  
309
function updateAvailableDataSets(available) {
310
  
311
  var isOptionEnabled = true;
312
  $("#type > option").each(function() {
313
    if((this.value in available) == false) {
314
      $(this).prop('disabled', true);
315
      $(this).prop('selected', false);  
316
    }
317
    else {
301
function updateAvailableDataSets (available) {
302
  var isOptionEnabled = true
303
  $('#type > option').each(function () {
304
    if ((this.value in available) === false) {
305
      $(this).prop('disabled', true)
306
      $(this).prop('selected', false)
307
    } else {
318 308
      $(this).prop('disabled', false)
319 309
      if (allOptionsDisabled) {
320
        $(this).prop('selected', true);
321
        allOptionsDisabled = false;
310
        $(this).prop('selected', true)
311
        allOptionsDisabled = false
322 312
      }
323
      isOptionEnabled = false;
313
      isOptionEnabled = false
324 314
    }
325
  });
326
  allOptionsDisabled = isOptionEnabled;
327

  
328
  $('#submit-btn').prop('disabled', isOptionEnabled);
315
  })
316
  allOptionsDisabled = isOptionEnabled
329 317

  
318
  $('#submit-btn').prop('disabled', isOptionEnabled)
330 319
}
331 320

  
332

  
333
function formatDate(date) {
334
  var day = String(date.getDate());
335
  var month = String(date.getMonth() + 1);
321
function formatDate (date) {
322
  var day = String(date.getDate())
323
  var month = String(date.getMonth() + 1)
336 324

  
337 325
  if (day.length === 1) {
338
    day = '0' + day;
326
    day = '0' + day
339 327
  }
340 328

  
341 329
  if (month.length === 1) {
342
    month = '0' + month;
330
    month = '0' + month
343 331
  }
344 332

  
345
  return date.getFullYear() + '-' + month + '-' + day;
333
  return date.getFullYear() + '-' + month + '-' + day
346 334
}
347 335

  
348
function initDatepicker(availableDatesSource) {
349
  var availableDates = '';
336
// eslint-disable-next-line no-unused-vars
337
function initDatepicker (availableDatesSource) {
338
  var availableDates = ''
350 339

  
351 340
  $.ajax({
352 341
    type: 'GET',
353 342
    url: availableDatesSource,
354
    success: function(result) {
355
      availableDates = String(result).split(',');
343
    success: function (result) {
344
      availableDates = String(result).split(',')
356 345
    }
357 346
  }).then(function () {
358 347
    $('#date').datepicker({
359 348
      format: 'yyyy-mm-dd',
360 349
      language: 'cs',
361
      beforeShowDay: function(date) {
350
      beforeShowDay: function (date) {
362 351
        if (availableDates.indexOf(formatDate(date)) < 0) {
363
          return {enabled: false, tooltip: 'Žádná data'}
364
        }
365
        else {
366
          return {enabled: true}
352
          return { enabled: false, tooltip: 'Žádná data' }
353
        } else {
354
          return { enabled: true }
367 355
        }
368 356
      },
369 357
      autoclose: true
370
    });
371
  });
372
}
358
    })
359
  })
360
}

Také k dispozici: Unified diff