commit c892003da41260319546e04049b552216503bc51
Author: Martin Sebela <msebela@zcu.cz>
Date:   Wed Oct 14 22:38:40 2020 +0200

    Re #8159 - CSS improvements, timeline clickable, code refactoring

diff --git a/website/public/css/style.css b/website/public/css/style.css
index 603e295..9c88502 100644
--- a/website/public/css/style.css
+++ b/website/public/css/style.css
@@ -893,6 +893,7 @@ hr {
   position: relative;
   padding: 0 10px;
   border-radius: 100px;
+  cursor: pointer;
   background-color: rgba(11, 21, 90, 0.7);
 }
 
@@ -1101,7 +1102,7 @@ p.logos-partners a:first-of-type img {
 .leaflet-popup-content-wrapper, .leaflet-popup-tip {
   font-family: 'Be Vietnam', sans-serif;
   text-align: center;
-  color: white;
+  color: #ffffff;
 }
 
 .leaflet-popup-content-wrapper .leaflet-popup-content strong {
@@ -1166,6 +1167,9 @@ header.map .nav-item:nth-child(3), header.map .nav-item:last-child {
 }
 
 header.map .nav-item .btn-secondary {
+  display: flex;
+  justify-content: center;
+  align-items: center;
   outline: none;
   border-radius: 50px;
   height: 40px;
@@ -1177,10 +1181,6 @@ header.map .nav-item .btn-secondary {
   -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.17);
   -moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.17);
   box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.17);
-  text-align: center;
-  display: flex;
-  justify-content: center;
-  align-items: center;
 }
 
 @media (max-width: 991.98px) {
@@ -1229,38 +1229,11 @@ header.map .nav-item input:focus {
   color: #000;
 }
 
-header.map .nav-item select:hover {
-  cursor: pointer;
-  background: rgba(255, 255, 255, 0.2);
-}
-
-header.map .nav-item select:hover option {
-  background: #0048A9;
-}
-
-header.map .nav-item select:focus {
-  background: #0048A9;
-  color: white;
-}
-
-.custom-dropdown-item {
-  margin: 0px !important;
-}
-
-.custom-dropdown-item .disabled {
-  cursor: not-allowed !important;
-}
-
-.custom-control-label {
-  font-weight: 300 !important;
-  margin: 0px !important;
+.dropdown {
+  min-width: 200px;
 }
 
-.custom-dropdown {
-  cursor: not-allowed;
-}
-
-input[type=radio]:checked ~ label {
+.dropdown input[type="radio"]:checked ~ label {
   font-weight: 800;
 }
 
@@ -1280,17 +1253,23 @@ input[type=radio]:checked ~ label {
   width: 100%;
   max-height: 300px;
   overflow-y: auto;
+  z-index: 1001;
+}
+
+.dropdown .dropdown-item:active {
+  background: #0048A9;
 }
 
 .dropdown .dropdown-item label {
   width: 100% !important;
+  margin-left: 0;
   cursor: pointer;
 }
 
-.dropdown #dataset-dropdown-time .dropdown-item:nth-of-type(even) {
+.dropdown #dropdown-time .dropdown-item:nth-of-type(even) {
   background: rgba(0, 0, 0, 0.05);
 }
 
-.dropdown #dataset-dropdown-time .dropdown-item:nth-of-type(even):active {
-  background: #007bff;
+.dropdown #dropdown-time .dropdown-item:nth-of-type(even):active {
+  background: #0048A9;
 }
diff --git a/website/public/css/style.scss b/website/public/css/style.scss
index 9f61df5..e480d16 100755
--- a/website/public/css/style.scss
+++ b/website/public/css/style.scss
@@ -6,6 +6,7 @@
 
 $primary-bg-color: #0048A9;
 $primary-bg-color-darker: #004fb3;
+$input-bg-hover: #336dba;
 $secondary-bg-color: #0b155a;
 
 $primary-text-color: #ffffff;
@@ -717,7 +718,7 @@ hr {
 }
 
 
-// PŘEHRÁVAČ HEATMAPY
+// DOLNÍ OVLÁDACÍ PANEL HEATMAPY
 .player {
   width: 100%;
   display: flex;
@@ -850,6 +851,7 @@ hr {
     position: relative;
     padding: 0 10px;
     border-radius: 100px;
+    cursor: pointer;
     background-color: rgba(11, 21, 90, .7);
 
     @include media-breakpoint-down(md) {
@@ -955,7 +957,6 @@ hr {
   background: url($images-dir + 'footer-bg.svg') no-repeat;
 
   @include media-breakpoint-down(md) {
-    
     width: 320px;
     height: 143px;
     background-size: 100%;
@@ -1003,11 +1004,12 @@ p.logos-partners {
   }
 }
 
-// INFORMACE O KONKRÉTNÍM BODĚ V HEATMAPĚ
+
+// POPUP O KONKRÉTNÍM BODĚ V HEATMAPĚ
 .leaflet-popup-content-wrapper, .leaflet-popup-tip {
   font-family: 'Be Vietnam', sans-serif;
   text-align: center;
-  color: white;
+  color: $primary-text-color;
 }
 
 .leaflet-popup-content-wrapper {
@@ -1074,6 +1076,9 @@ header.map .nav-item {
   }
 
   .btn-secondary {
+    display: flex;
+    justify-content: center;
+    align-items: center;
     outline: none;
     border-radius: 50px;
     height: 40px;
@@ -1085,10 +1090,6 @@ header.map .nav-item {
     -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.17);
     -moz-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.17);
     box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.17);
-    text-align: center;
-    display: flex;
-    justify-content: center;
-    align-items: center;
 
     @include media-breakpoint-down(md) {
       width: 100%;
@@ -1098,7 +1099,7 @@ header.map .nav-item {
       margin-bottom: -10px;
     }
 
-    &:after{
+    &:after {
       padding-bottom: 4px;
       content: '↺';
       font-weight: 400;
@@ -1136,42 +1137,17 @@ header.map .nav-item {
       color: #000;
     }
   }
+}
 
-  select {
-    &:hover {
-      cursor: pointer;
-      background: rgba(255, 255, 255, .2);
 
-      option {
-        background: $primary-bg-color;
-      }
-    }
+// MENU PRO VÝBĚR ČASU/DATOVÝCH SAD
+.dropdown {
+  min-width: 200px;
 
-    &:focus {
-      background: $primary-bg-color;
-      color: white;
-    }
+  input[type="radio"]:checked ~ label {
+    font-weight: 800;
   }
-}
-.custom-dropdown-item {
-  margin: 0px !important;
-}
-.custom-dropdown-item .disabled {
-  cursor: not-allowed !important;
-}
-.custom-control-label {
-  font-weight: 300 !important;
-  margin: 0px !important;
-}
-.custom-dropdown {
-  cursor: not-allowed;
-}
 
-input[type=radio]:checked~label {
-  font-weight: 800;
-}
-
-.dropdown {
   .btn {
     width: 100%;
     text-align: left;
@@ -1180,7 +1156,7 @@ input[type=radio]:checked~label {
     background: $primary-bg-color;
 
     &:hover {
-      background: #336dba;
+      background: $input-bg-hover;
     }
   }
 
@@ -1188,18 +1164,26 @@ input[type=radio]:checked~label {
     width: 100%;
     max-height: 300px;
     overflow-y: auto;
+    z-index: 1001;
   }
 
-  .dropdown-item label {
-    width: 100% !important;
-    cursor: pointer;
+  .dropdown-item {
+    &:active {
+      background: $primary-bg-color;
+    }
+    
+    label {
+      width: 100% !important;
+      margin-left: 0;
+      cursor: pointer;
+    }
   }
 
-  #dataset-dropdown-time .dropdown-item:nth-of-type(even) {
+  #dropdown-time .dropdown-item:nth-of-type(even) {
     background: rgba(0,0,0,.05);
 
     &:active {
-      background: #007bff;
+      background: $primary-bg-color;
     }
   }
 }
\ No newline at end of file
diff --git a/website/public/js/zcu-heatmap.js b/website/public/js/zcu-heatmap.js
index cdaee17..619a472 100644
--- a/website/public/js/zcu-heatmap.js
+++ b/website/public/js/zcu-heatmap.js
@@ -29,6 +29,7 @@ const globalMarkersHolder = {}
 // key: x and y, x + '' + y string
 let globalMarkersChanged = {}
 
+
 const fetchByNameDate = async (baseRoute, name, date, currentTime) => {
   const headers = new Headers()
   const myRequest = new Request(baseRoute + '/' + name + '/' + date + '/' + currentTime, {
@@ -38,6 +39,8 @@ const fetchByNameDate = async (baseRoute, name, date, currentTime) => {
   const beforeJson = await fetch(myRequest)
   return beforeJson.json()
 }
+
+
 const fetchDataSourceMarks = async (positionRoute, datasetName) => {
   const headers = new Headers()
   const myRequest = new Request(positionRoute + '/' + datasetName, {
@@ -48,29 +51,38 @@ const fetchDataSourceMarks = async (positionRoute, datasetName) => {
   return beforeJson.json()
 }
 
+
 const genPopUpControlButtons = (currentPage, numPages, onNextClick, onPreviousClick) => ({
   previousButton: '<button id="previous-info-btn" class="circle-button" onclick="previousInfo()"></button>',
-  nextButton: '<button id="next-info-btn" onclick="nextInfo()" class="circle-button next"></button>',
+  nextButton: '<button id="next-info-btn" class="circle-button next" onclick="nextInfo()"></button>',
   posInfo: `<div id="count-info">${currentPage} z ${numPages}</div>`
 })
+
+
 const genPopUpControls = (controls) => {
   return `<div class="popup-controls">${controls ? controls.reduce((sum, item) => sum + item, '') : ''}</div>`
 }
+
+
 const genMultipleDatasetsPopUp = (sum, currentPos, maxPos, datasetName) => {
-  const header = `<strong id="dataset-info">${datasetName}</strong>`
-  const digitInfo = `<div id="number-info"><span id="digit-info">${sum}</span></div>`
+  const popupHeader = `<strong id="dataset-info">${datasetName}</strong>`
+  const popupData = `<div id="number-info"><span id="digit-info">${sum}</span></div>`
   const { previousButton, nextButton, posInfo } = genPopUpControlButtons(currentPos, maxPos)
+
   return `
-  ${header}
-  ${digitInfo}
+  ${popupHeader}
+  ${popupData}
   ${genPopUpControls([previousButton, posInfo, nextButton])}
   `
 }
+
+
 const prepareLayerPopUp = (lat, lng, num, className) => L.popup({
   autoPan: false,
   className: className
 }).setLatLng([lat / num, lng / num])
 
+
 const genPopUp = (datasetName, place, count, sum, currentPos, maxPos) => {
   const popupHeader = `
     <strong>${datasetName}</strong>
@@ -88,12 +100,16 @@ const genPopUp = (datasetName, place, count, sum, currentPos, maxPos) => {
   ${genPopUpControls(maxPos > 1 ? [previousButton, posInfo, nextButton] : null)}
   `
 }
+
+
 const onCheckboxClicked = async (checkbox) => {
   if ($(checkbox).prop('checked')) {
     loadCurrentTimeHeatmap(dataSourceRoute, positionsSourceRoute)
     changeUrl()
-  } else {
+  }
+  else {
     loadCheckboxDatasetNameData()
+
     data.forEach((item, index) => {
       Object.keys(item).forEach((datasetName) => {
         if (datasetName === $(checkbox).val()) {
@@ -102,9 +118,12 @@ const onCheckboxClicked = async (checkbox) => {
       })
       drawHeatmap(data[currentTime])
     })
+
     changeUrl()
   }
 }
+
+
 const debounce = (func, delay) => {
   let inDebounce
   return function () {
@@ -115,6 +134,7 @@ const debounce = (func, delay) => {
   }
 }
 
+
 const onValueChangeRegister = () => {
   $('#date').change(function () {
     data = []
@@ -124,7 +144,7 @@ const onValueChangeRegister = () => {
     changeUrl()
   })
 
-  $('#dataset-dropdown-time input[type="radio"]').each(function () {
+  $('#dropdown-time input[type="radio"]').each(function () {
     $(this).change(function () {
       currentTime = parseInt($(this).val())
       updateHeaderControls()
@@ -134,13 +154,14 @@ const onValueChangeRegister = () => {
     })
   })
 
-  $('input[type=checkbox]').each(function () {
+  $('#dropdown-dataset input[type="checkbox"]').each(function () {
     $(this).change(
       debounce(() => onCheckboxClicked(this), 1000)
     )
   })
 }
 
+
 /**
  * Initialize leaflet map on start position which can be default or set based on user action
  */
@@ -159,6 +180,8 @@ function initMap () {
 
   mymap.on('click', showInfo)
 }
+
+
 const getInfoLength = () => {
   const infoKeys = Object.keys(info)
   if (infoKeys.length === 1) {
@@ -168,13 +191,19 @@ const getInfoLength = () => {
   // return number of datasets (agregation of all datasets in area)
   return infoKeys.length
 }
+
+
 const getElFromObjectInfo = (position) => {
   const keys = Object.keys(info)
   return info[keys[position]]
 }
+
+
 const hasInfoMultipleDatasets = () => {
   return Object.keys(info).length > 1
 }
+
+
 function showInfo (e) {
   info = []
   currentInfo = 0
@@ -216,6 +245,7 @@ function showInfo (e) {
         datasetName: item.datasetName
       }
     }
+
     acc[item.datasetName].items.push(item)
     acc[item.datasetName].number += Number(item.number)
     return acc
@@ -236,49 +266,62 @@ function showInfo (e) {
     prepareLayerPopUp(lat, lng, i, `popup-${infoDict.datasetName}`)
       .setContent(genPopUp(datasetDictNameDisplayName[infoDict.datasetName], place, number, total, currentInfo + 1, info_.length))
       .openOn(mymap)
+
     if (info_.length === 1) {
       $('#previous-info-btn').prop('disabled', true)
       $('#next-info-btn').prop('disabled', true)
       $('.popup-controls').hide()
     }
-  } else {
+  }
+  else {
     const { datasetName, number } = getElFromObjectInfo(currentInfo)
+
     prepareLayerPopUp(lat, lng, i, `popup-${datasetName}`)
       .setContent(genMultipleDatasetsPopUp(number, currentInfo + 1, getInfoLength(), datasetDictNameDisplayName[datasetName]))
       .openOn(mymap)
   }
 }
 
+
 // eslint-disable-next-line no-unused-vars
 function previousInfo () {
   const infoLength = getInfoLength()
   const previousCurrentInfo = currentInfo
+
   currentInfo = (currentInfo + infoLength - 1) % infoLength
   displayInfoText(previousCurrentInfo)
 }
 
+
 // eslint-disable-next-line no-unused-vars
 function nextInfo () {
   const infoLength = getInfoLength()
   const previousCurrentInfo = currentInfo
+
   currentInfo = (currentInfo + 1) % infoLength
   displayInfoText(previousCurrentInfo)
 }
+
+
 function displayInfoText (previousInfoNum) {
   const previousInfo = hasInfoMultipleDatasets() ? getElFromObjectInfo(previousInfoNum) : getElFromObjectInfo(0).items[previousInfoNum]
   const info_ = hasInfoMultipleDatasets() ? getElFromObjectInfo(currentInfo) : getElFromObjectInfo(0).items[currentInfo]
   const infoLength = getInfoLength()
   const datasetInfo = $('#dataset-info')
+
   if (datasetInfo) {
     $(datasetInfo).html(datasetDictNameDisplayName[info_.datasetName])
   }
+  
   $('#place-info').html(info_.place ? info_.place : info_.datasetName)
   $('#digit-info').html(info_.number)
   $('#count-info').html(currentInfo + 1 + ' z ' + infoLength)
+
   $('.leaflet-popup').removeClass(`popup-${previousInfo.datasetName}`)
   $('.leaflet-popup').addClass(`popup-${info_.datasetName}`)
 }
 
+
 // eslint-disable-next-line no-unused-vars
 function setMapView (latitude, longitude, zoom) {
   localStorage.setItem('lat', latitude)
@@ -287,26 +330,25 @@ function setMapView (latitude, longitude, zoom) {
   mymap.setView([latitude, longitude], zoom)
 }
 
+
 /**
  * Change animation start from playing to stopped or the other way round
  */
 // eslint-disable-next-line no-unused-vars
 function changeAnimationState () {
   isAnimationRunning = !isAnimationRunning
+
   if (isAnimationRunning) {
     $('#play-pause').attr('class', 'pause')
-    timer = setInterval(
-      function () {
-        next()
-      },
-      800
-    )
-  } else {
+    timer = setInterval(function() { next() }, 800)
+  }
+  else {
     clearTimeout(timer)
     $('#play-pause').attr('class', 'play')
   }
 }
 
+
 // eslint-disable-next-line no-unused-vars
 function previous () {
   currentTime = (currentTime + 23) % 24
@@ -317,6 +359,7 @@ function previous () {
   changeUrl()
 }
 
+
 function next () {
   currentTime = (currentTime + 1) % 24
   drawHeatmap(data[currentTime])
@@ -325,28 +368,41 @@ function next () {
   updateHeaderControls()
   changeUrl()
 }
-const typeUrlReducer = (accumulator, currentValue) => accumulator + currentValue
+
+
 /**
- * Change browser url based on animation step
+ * Change browser url based on animation step.
  */
 function changeUrl () {
   window.history.pushState(
     '',
     document.title,
-    window.location.origin + window.location.pathname + `?date=${$('#date').val()}&time=${currentTime}${datasetSelected.reduce((acc, current) => acc + '&type[]=' + current, '')}`
+    window.location.origin + window.location.pathname + `?date=${$('#date').val()}&time=${currentTime}${datasetSelected.reduce((acc, current) => acc + '&type=' + current, '')}`
   )
 }
 
+
 function updateHeaderControls () {
   $(`#time_${currentTime}`).prop('checked', true)
   $('#dropdownMenuButtonTime').html((currentTime < 10 ? '0' : '') + `${currentTime}:00`)
 }
 
+
 function setTimeline () {
   $('#timeline').text(currentTime + ':00')
   $('#timeline').attr('class', 'time hour-' + currentTime)
 }
 
+
+function changeHour(hour) {
+  currentTime = hour
+  updateHeaderControls()
+  setTimeline()
+  drawHeatmap(data[currentTime])
+  changeUrl()
+}
+
+
 /**
  * Load and display heatmap layer for current data
  * @param {string} opendataRoute route to dataset source
@@ -355,12 +411,13 @@ function setTimeline () {
 // eslint-disable-next-line no-unused-vars
 async function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
   loadCheckboxDatasetNameData()
+
   dataSourceRoute = opendataRoute
   positionsSourceRoute = positionsRoute
   const dataSourceMarks = {}
   const allPromises = []
   const date = $('#date').val()
-  currentTime = parseInt($('#dataset-dropdown-time input[type="radio"]:checked').val())
+  currentTime = parseInt($('#dropdown-time input[type="radio"]:checked').val())
 
   setTimeline()
   data[currentTime] = {}
@@ -370,9 +427,11 @@ async function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
     dataSourceMarks[datasetName] = marks
     data[currentTime][datasetName] = datasetData
   }
+
   await datasetSelected.forEach((datasetName) => {
     allPromises.push(dataSelectedHandler(datasetName))
   })
+
   Promise.all(allPromises).then(
     () => {
       drawDataSourceMarks(dataSourceMarks)
@@ -383,11 +442,14 @@ async function loadCurrentTimeHeatmap (opendataRoute, positionsRoute) {
   )
 }
 
+
 function drawDataSourceMarks (data) {
   if (marksLayer != null) {
     mymap.removeLayer(marksLayer)
   }
+
   marksLayer = L.layerGroup()
+
   Object.keys(data).forEach((key_) => {
     for (var key in data[key_]) {
       const { x, y, name } = data[key_][key]
@@ -407,11 +469,13 @@ function drawDataSourceMarks (data) {
   marksLayer.setZIndex(-1).addTo(mymap)
 }
 
+
 async function preload (time, change, date) {
   for (let nTime = time + change; nTime >= 0 && nTime <= 23; nTime = nTime + change) {
     if (!data[nTime]) {
       data[nTime] = {}
     }
+
     datasetSelected.forEach(async (datasetName) => {
       if (!data[nTime][datasetName]) {
         data[nTime][datasetName] = await fetchByNameDate(dataSourceRoute, datasetName, date, nTime)
@@ -420,48 +484,58 @@ async function preload (time, change, date) {
   }
 }
 
+
 function drawHeatmap (dataRaw) {
   // Todo still switched
   const dataDict = dataRaw
   const mergedPoints = []
   let max = 0
+  
   if (Object.keys(globalMarkersChanged).length) {
     Object.keys(globalMarkersChanged).forEach(function (key) {
       globalMarkersChanged[key][0].bindPopup(globalMarkersChanged[key][1])
     })
     globalMarkersChanged = {}
   }
+
   Object.keys(dataDict).forEach((key) => {
     const data = dataDict[key]
     max = Math.max(max, data.max)
+
     if (data != null) {
     // Bind back popups for markers (we dont know if there is any data for this marker or not)
       const points = data.items.map((point) => {
         const { x, y, number } = point
         const key = x + '' + y
         const holder = globalMarkersHolder[key]
+
         if (!globalMarkersChanged[key] && number) {
         // There is data for this marker => unbind popup with zero value
           holder[0] = holder[0].unbindPopup()
           globalMarkersChanged[key] = holder
         }
+
         return [x, y, number]
       })
       mergedPoints.push(...points)
-    } else {
+    }
+    else {
       if (heatmapLayer != null) {
         mymap.removeLayer(heatmapLayer)
       }
     }
   })
+
   if (heatmapLayer != null) {
     mymap.removeLayer(heatmapLayer)
   }
+
   if (mergedPoints.length) {
     heatmapLayer = L.heatLayer(mergedPoints, { max: max, minOpacity: 0.5, radius: 35, blur: 30 }).addTo(mymap)
   }
 }
 
+
 /**
  * Checks dataset availibility
  * @param {string} route authority for datasets availibility checks
@@ -478,16 +552,20 @@ function checkDataSetsAvailability (route) {
   })
 }
 
+
 function updateAvailableDataSets (available) {
   let leastOneOptionEnabled = false
   // datasetSelected = []
-  $('#dataset-dropdown .dropdown-item').each(function () {
+
+  $('#dropdown-dataset .dropdown-item').each(function () {
     const input = $(this).find('input')
     const inputVal = input[0].value
+
     if (!(inputVal in available)) {
       $(this).addClass('disabled')
       $(input).prop('checked', false)
-    } else {
+    }
+    else {
       leastOneOptionEnabled = true
       $(this).removeClass('disabled')
     }
@@ -496,6 +574,7 @@ function updateAvailableDataSets (available) {
   $('#btn-update-heatmap').prop('disabled', !leastOneOptionEnabled)
 }
 
+
 function formatDate (date) {
   var day = String(date.getDate())
   var month = String(date.getMonth() + 1)
@@ -511,6 +590,7 @@ function formatDate (date) {
   return date.getFullYear() + '-' + month + '-' + day
 }
 
+
 // eslint-disable-next-line no-unused-vars
 function initDatepicker (availableDatesSource) {
   var availableDates = ''
@@ -528,7 +608,8 @@ function initDatepicker (availableDatesSource) {
       beforeShowDay: function (date) {
         if (availableDates.indexOf(formatDate(date)) < 0) {
           return { enabled: false, tooltip: 'Žádná data' }
-        } else {
+        }
+        else {
           return { enabled: true }
         }
       },
@@ -537,17 +618,20 @@ function initDatepicker (availableDatesSource) {
   })
 }
 
+
 function initLocationsMenu () {
   var locationsWrapper = '.locations'
   var locationsDisplayClass = 'show'
 
   if ($(window).width() <= 480) {
     $(locationsWrapper).removeClass(locationsDisplayClass)
-  } else {
+  }
+  else {
     $(locationsWrapper).addClass(locationsDisplayClass)
   }
 }
 
+
 function openDatepicker () {
   if ($(window).width() <= 990) {
     $('.navbar-collapse').collapse()
@@ -555,22 +639,28 @@ function openDatepicker () {
 
   $('#date').datepicker('show')
 }
+
+
 function onDocumentReady () {
-  $('#dataset-dropdown').on('click', function (e) {
+  $('#dropdown-dataset').on('click', function (e) {
     e.stopPropagation()
   })
 
   $('#btn-update-heatmap').prop('name', '')
   onValueChangeRegister()
 }
+
+
 const loadCheckboxDatasetNameData = () => {
   datasetSelected = []
-  $('#dataset-dropdown .dropdown-item').each(function () {
+  $('#dropdown-dataset .dropdown-item').each(function () {
     const input = $(this).find('input')
     const inputVal = input[0].value
+
     if (input[0].checked) {
       datasetSelected.push(inputVal)
     }
+
     datasetDictNameDisplayName[inputVal] = $(input).data('dataset-display-name')
   })
 }
diff --git a/website/templates/base.html.twig b/website/templates/base.html.twig
index ba81c40..be6825e 100644
--- a/website/templates/base.html.twig
+++ b/website/templates/base.html.twig
@@ -1,27 +1,28 @@
 <!DOCTYPE html>
 <html lang="cs">
-    <head>
-        <meta charset="utf-8">
+  <head>
+    <meta charset="utf-8">
         
-        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-        <meta name="description" content="Heatmapa kampusu Západočeské univerzity v Plzni">
-        <meta name="keywords" content="heatmap, opendata, západočeská univerzita, zču, plzeň">
-        <meta name="author" content="Tým BHVS &ndash; Tomáš Ballák, Petr Hlaváč, Jakub Vašta, Martin Šebela">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta name="description" content="Heatmapa kampusu Západočeské univerzity v Plzni">
+    <meta name="keywords" content="heatmap, opendata, otevřená data, západočeská univerzita, zču, plzeň">
+    <meta name="author" content="Tým BHVS &ndash; Tomáš Ballák, Petr Hlaváč, Jakub Vašta, Martin Šebela">
 
-        <meta property="og:url" content="https://heatmap.zcu.cz">
-        <meta property="og:type" content="website">
-        <meta property="og:title" content="Heatmapa kampusu Západočeské univerzity v Plzni">
-        <meta property="og:description" content="Hodina po hodině, den po dni.">
-        <meta property="og:image" content="https://heatmap.zcu.cz/img/banner.jpg">
+    <meta property="og:url" content="https://heatmap.zcu.cz">
+    <meta property="og:type" content="website">
+    <meta property="og:title" content="Heatmapa kampusu Západočeské univerzity v Plzni">
+    <meta property="og:description" content="Hodina po hodině, den po dni.">
+    <meta property="og:image" content="https://heatmap.zcu.cz/img/banner.jpg">
 
-        <link rel="shortcut icon" href="favicon.ico">
+    <link rel="shortcut icon" href="favicon.ico">
 
-        <title>{% block title %}{% endblock %}</title>
-        {% block stylesheets %}{% endblock %}
-    </head>
-    <body{% block bodyClass %}{% endblock %}>
-        {% block body %}{% endblock %}
-        {% block javascripts %}{% endblock %}
-        {% block style %}{% endblock %}
-    </body>
+    <title>{% block title %}{% endblock %}</title>
+    
+    {% block stylesheets %}{% endblock %}
+    {% block style %}{% endblock %}
+ </head>
+ <body{% block bodyClass %}{% endblock %}>
+    {% block body %}{% endblock %}
+    {% block javascripts %}{% endblock %}
+  </body>
 </html>
diff --git a/website/templates/heatmap.html.twig b/website/templates/heatmap.html.twig
index 1378d3d..1aa4764 100644
--- a/website/templates/heatmap.html.twig
+++ b/website/templates/heatmap.html.twig
@@ -2,10 +2,10 @@
 
 {% block title %}Heatmap.ZČU{% endblock %}
 {% block stylesheets %}
-  <link rel="stylesheet" href="{{ asset('css/leaflet.css') }}">
-  <link rel="stylesheet" href="{{ asset('css/bootstrap.min.css') }}">
-  <link rel="stylesheet" href="{{ asset('css/style.css') }}">
-  <link rel="stylesheet" href="{{ asset('css/bootstrap-datepicker3.css') }}">
+<link rel="stylesheet" href="{{ asset('css/leaflet.css') }}">
+    <link rel="stylesheet" href="{{ asset('css/bootstrap.min.css') }}">
+    <link rel="stylesheet" href="{{ asset('css/style.css') }}">
+    <link rel="stylesheet" href="{{ asset('css/bootstrap-datepicker3.css') }}">
 {% endblock %}
 
 {% block body %}
@@ -47,7 +47,7 @@
                 <button type="button" class="btn dropdown-toggle" id="dropdownMenuButtonTime" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                   {{ current_time }}
                 </button>
-                <div id="dataset-dropdown-time" class="dropdown-menu" aria-labelledby="dropdownMenuButtonTime">
+                <div id="dropdown-time" class="dropdown-menu" aria-labelledby="dropdownMenuButtonTime">
                   {% for hour in form.time.children %}
                   <div class="dropdown-item custom-dropdown-item">
                     {{ form_widget(hour, {attr: {class: 'd-none'}}) }}
@@ -62,7 +62,7 @@
                 <button type="button" class="btn dropdown-toggle font-weight-bold" id="dropdownMenuButtonDataset" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                   Vyberte datovou sadu
                 </button>
-                <div id="dataset-dropdown" class="dropdown-menu" aria-labelledby="dropdownMenuButtonDataset">
+                <div id="dropdown-dataset" class="dropdown-menu" aria-labelledby="dropdownMenuButtonDataset">
                   {% for dataset in form.type.children %}
                   <div class="dropdown-item custom-dropdown-item">
                     <div class="custom-control custom-checkbox custom-checkbox-{{dataset.vars.value}}">
@@ -84,9 +84,8 @@
             <li class="nav-item">
               {{ form_widget(form.submit,
                 {
-                  'name' : '',
-                  'label' : '',
                   'type' : 'submit',
+                  'name' : '',
                   'id' : 'btn-update-heatmap',
                   'attr' : {
                     'class': 'btn btn-secondary'
@@ -126,7 +125,7 @@
         <div class="time hour-0" id="timeline">0:00</div>
 
         {% for i in 0..23 %}
-        <div class="hour"></div>
+        <div class="hour" title="{{ i }}:00" onclick="changeHour('{{ i }}')"></div>
         {% endfor %}
         <div class="end-dot"></div>
       </div>
@@ -138,7 +137,6 @@
 {% endblock %}
 
 {% block javascripts %}
-
     <script src="{{ asset('js/vendor/jquery-3.4.1.min.js') }}"></script>
     <script src="{{ asset('js/vendor/bootstrap.min.js') }}"></script>
     <script src="{{ asset('js/vendor/bootstrap-datepicker.min.js') }}"></script>
@@ -147,50 +145,49 @@
     <script src="{{ asset('js/vendor/leaflet-heat.js') }}"></script>
     <script src="{{ asset('js/zcu-heatmap.js') }}"></script>
     <script>
-        initDatepicker("{{ path('dates') }}");
+      initDatepicker("{{ path('dates') }}");
+      initLocationsMenu();
+      initMap();
+
+      $(document).ready(function() {
+        onDocumentReady();
+        checkDataSetsAvailability("{{ path('available') }}")
+        {% if submitted %}
+        loadCurrentTimeHeatmap("{{ path('opendata') }}", "{{ path('positions') }}");
+        {% endif %}
+      });
+      
+      $(window).resize(function() {
         initLocationsMenu();
-        initMap();
-
-        $(document).ready(function() {
-          onDocumentReady();
-          checkDataSetsAvailability("{{ path('available') }}")
-          {% if submitted %}
-          loadCurrentTimeHeatmap("{{ path('opendata') }}", "{{ path('positions') }}");
-          {% endif %}
-        });
-        
-        $(window).resize(function() {
-          initLocationsMenu();
-        });
+      });
   </script>
-
 {% endblock %}
 
 {% block style %}
-  <style type="text/css">
-    {% for dataset_name, dataset_color in dataset_colors %}
-      .custom-control-input-{{ dataset_name }}:focus~.custom-control-label::before {
-        border-color: {{ dataset_color }} !important;
-        box-shadow: 0 0 0 0.2rem rgba(192,192,192, 0.4) !important;
-      }
-
-      .custom-control-input-{{ dataset_name }}:checked~.custom-control-label::before {
-        border-color: {{ dataset_color }} !important;
-        background-color: {{ dataset_color }} !important;
-      }
-
-      .custom-control-input-{{ dataset_name }}:focus:not(:checked)~.custom-control-label::before {
-        border-color: {{ dataset_color }} !important;
-      }
-
-      .custom-control-input-{{ dataset_name }}:not(:disabled):active~.custom-control-label::before {
-        background-color: {{ dataset_color }} !important;
-        border-color: {{ dataset_color }} !important;
-      }
-
-      .popup-{{ dataset_name }} > .leaflet-popup-content-wrapper, .popup-{{ dataset_name }} .leaflet-popup-tip {
-        background-color: {{ dataset_color }} !important;
-      }
-    {% endfor %}
-  </style>
+<style type="text/css">
+{% for dataset_name, dataset_color in dataset_colors %}
+    .custom-control-input-{{ dataset_name }}:focus~.custom-control-label::before {
+      border-color: {{ dataset_color }} !important;
+      box-shadow: 0 0 0 0.2rem rgba(192,192,192, 0.4) !important;
+    }
+
+    .custom-control-input-{{ dataset_name }}:checked~.custom-control-label::before {
+      border-color: {{ dataset_color }} !important;
+      background-color: {{ dataset_color }} !important;
+    }
+
+    .custom-control-input-{{ dataset_name }}:focus:not(:checked)~.custom-control-label::before {
+      border-color: {{ dataset_color }} !important;
+    }
+
+    .custom-control-input-{{ dataset_name }}:not(:disabled):active~.custom-control-label::before {
+      background-color: {{ dataset_color }} !important;
+      border-color: {{ dataset_color }} !important;
+    }
+
+    .popup-{{ dataset_name }} > .leaflet-popup-content-wrapper, .popup-{{ dataset_name }} .leaflet-popup-tip {
+      background-color: {{ dataset_color }} !important;
+    }
+{% endfor %}
+</style>
 {% endblock %}
\ No newline at end of file
