{"version":3,"sources":["components/map/ol-map/OLMap.jsx","components/map/ol-controls/time-slider/TimeSliderControl.jsx","components/map/ol-progressbar/OlProgressBar.jsx","components/map/ol-controls/time-slider/play.svg","components/map/ol-controls/time-slider/pause.svg"],"names":["OLMap","Component","constructor","props","super","this","map","addMapLayer","bind","addMapControl","setMapLayerVisible","addOverlayToMap","moveOverlay","mapClick","updateTimeDimensions","panTo","addCameras","showStationTextOnHover","showStationTextOnTouch","updateSize","parser","WMTSCapabilities","progressBarHandler","lastStationHover","componentDidMount","proj4","defs","register","center","Array","isArray","zoom","parseInt","target","detachWindow","retrieveDetachDiv","Map","moveTolerance","layers","interactions","defaults","mouseWheelZoom","disableMouseWheelZoom","view","View","projection","transform","minZoom","on","componentWillUnmount","un","layername","visible","getLayers","getArray","forEach","layer","get","setVisible","evt","pointerEvent","pointerType","container","overlay","Overlay","element","offset","stopEvent","positioning","autoPanAnimation","duration","setPosition","undefined","addOverlay","coordinates","addStationTextStyle","text","Text","font","offsetY","backgroundFill","Fill","color","e","dragging","pixel","getEventPixel","originalEvent","feature","forEachFeatureAtPixel","f","hitTolerance","station","name","showName","set","getStyle","setText","showInsteadOfContinue","generateStationFeature","Feature","geometry","Point","longitude","latitude","concat","eoi","type","originalColor","latestAQI","style","Style","image","Icon","anchor","anchorXUnits","anchorYUnits","scale","src","window","location","origin","setStyle","addStationsToMap","list","features","stationComponents","latestAQIComponents","Object","entries","_ref","key","value","c","push","vs","SourceVector","stationVectorLayer","LayerVector","source","zIndex","timeLoaded","Date","_ref2","sv","component","toLowerCase","replace","lv","cameras","camera","road","description","cameraUrl","url","cameraVectorLayer","addGeoDataWmts","wmts","result","read","options","optionsFromCapabilities","matrixSet","TileLayer","opacity","WMTS","addMetsWms","layernames","wms","WMSCapabilities","newLayer","TileWMS","crossOrigin","params","LAYERS","TIME","TRANSPARENT","serverType","getSource","addLoading","addDone","addMetsWmts","dims","Contents","Layer","Dimension","today","Value","length","show","useInterimTilesOnError","default","Default","values","addLayer","control","addControl","setVisibleLayers","activeLayers","filter","l","includes","time","updateDimensions","updateParams","isNow","now","timeDate","getHours","getDate","getFeatures","lat","long","arguments","getView","setCenter","setZoom","render","React","createElement","id","className","TimeSliderControl","weekday","Localization","timeSliderSunday","timeSliderMonday","timeSliderTuesday","timeSliderWednesday","timeSliderThursday","timeSliderFriday","timeSliderSaturday","index","totalPins","px","intervalWidth","times","day","date","getDay","timesThisDay","t","Math","floor","dayName","substring","timelist","cutArray","days","wdDict","WeekdayDictionaryNOR","indexOf","hour","dayNames","d","sliderDates","timeobj","timeParam","answer","i","doublecheckDate","getUTCDate","getUTCMonth","getUTCFullYear","setLanguage","sliderOnChange","togglePlay","setupTimeslider","writeCleanTime","state","isLoading","newTimes","sliderValue","isPlaying","playingIntervalId","componentDidUpdate","prevProps","prevState","onTimeSliderChange","clearInterval","newIntervalId","setInterval","setState","_objectSpread","restructureTime","getSliderNow","toString","console","log","returnText","Spinner","numPins","Pause","Play","onClick","position","left","pinOffset","dayLabel","width","data-t","classes","htmlFor","timesliderName","step","min","max","onChange","OlProgressBar","loading","done","progressBar","createRef","update","current","visibility","toFixed","setTimeout","ref","module","exports"],"mappings":"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","file":"static/js/1.d453c7ba.chunk.js","sourcesContent":["import React, { Component } from 'react';\nimport { Map, View } from 'ol';\nimport { transform } from 'ol/proj';\nimport proj4 from 'proj4/dist/proj4-src';\nimport { register } from 'ol/proj/proj4';\nimport WMTS, { optionsFromCapabilities } from 'ol/source/WMTS';\nimport TileWMS from 'ol/source/TileWMS';\nimport TileLayer from 'ol/layer/Tile';\nimport LayerVector from 'ol/layer/Vector';\nimport SourceVector from 'ol/source/Vector';\nimport Point from 'ol/geom/Point';\nimport Feature from 'ol/Feature';\nimport Style from 'ol/style/Style';\nimport Icon from 'ol/style/Icon';\nimport Text from 'ol/style/Text';\nimport Fill from 'ol/style/Fill';\nimport Overlay from 'ol/Overlay';\nimport {defaults} from 'ol/interaction';\n\nimport WMTSCapabilities from 'ol/format/WMTSCapabilities';\nimport WMSCapabilities from 'ol/format/WMSCapabilities';\n\nexport default class OLMap extends Component {\n  constructor(props) {\n    super(props);\n    this.map = null;\n    this.addMapLayer = this.addMapLayer.bind(this);\n    this.addMapControl = this.addMapControl.bind(this);\n    this.setMapLayerVisible = this.setMapLayerVisible.bind(this);\n    this.addOverlayToMap = this.addOverlayToMap.bind(this);\n    this.moveOverlay = this.moveOverlay.bind(this);\n    this.mapClick = this.mapClick.bind(this);\n    this.updateTimeDimensions = this.updateTimeDimensions.bind(this);\n    this.panTo = this.panTo.bind(this);\n    this.addCameras = this.addCameras.bind(this);\n    this.showStationTextOnHover = this.showStationTextOnHover.bind(this);\n    this.showStationTextOnTouch = this.showStationTextOnTouch.bind(this);\n    this.updateSize = this.updateSize.bind(this);\n    this.parser = new WMTSCapabilities();\n    this.progressBarHandler = props.progressBarHandler;\n    this.lastStationHover = null;\n  }\n\n  componentDidMount() {\n    proj4.defs(\n      'EPSG:32633',\n      '+proj=utm +zone=33 +ellps=WGS84 +datum=WGS84 +units=m +no_defs',\n    );\n\n    register(proj4);\n    let center = this.props.center;\n    if (!Array.isArray(center)) {\n      center = [0, 0];\n    }\n\n    let zoom = 14;\n    if (this.props.zoom) {\n      zoom = parseInt(this.props.zoom, 10);\n    }\n\n    let target = null;\n    if (this.props.detachWindow && this.props.retrieveDetachDiv) {\n      target = this.props.retrieveDetachDiv('olmap');\n    }\n\n    if (target === null) {\n      target = 'olmap';\n    }\n\n    this.map = new Map({\n      target: 'olmap',\n      moveTolerance: 5,\n      layers: [],\n      interactions: defaults({ mouseWheelZoom: !!!this.props.disableMouseWheelZoom}),\n      view: new View({\n        projection: 'EPSG:32633',\n        center: transform([center[0], center[1]], 'EPSG:4326', 'EPSG:32633'),\n        minZoom: 6,\n        zoom,\n      }),\n    });\n\n    this.map.on('click', this.mapClick, false);\n\n    // Hover should show the station name.\n    this.map.on('pointermove', this.showStationTextOnHover);\n  }\n\n  componentWillUnmount() {\n    this.map.un('click', this.mapClick, false);\n    this.map = null;\n  }\n\n  setMapLayerVisible(layername, visible) {\n    this.map\n      .getLayers()\n      .getArray()\n      .forEach((layer) => {\n        if (layer.get('name') === layername) {\n          layer.setVisible(visible);\n        }\n      });\n  }\n\n  updateSize() {\n    this.map.updateSize();\n  }\n\n  mapClick(evt) {\n    // Show station name on click for touch first.\n    if (\n      evt.pointerEvent.pointerType === 'touch'\n      && this.showStationTextOnTouch(evt)\n    ) {\n      return;\n    }\n\n    if (this.props.mapClick) {\n      this.props.mapClick(evt, this.map);\n    }\n  }\n\n  addOverlayToMap(container) {\n    const overlay = new Overlay({\n      element: container,\n      offset: [0, 10],\n      // autoPan: true,\n      stopEvent: false,\n      positioning: 'top-center',\n      autoPanAnimation: {\n        duration: 250,\n      },\n    });\n\n    overlay.setPosition(undefined);\n\n    this.map.addOverlay(overlay);\n\n    return overlay;\n  }\n\n  moveOverlay(overlay, coordinates) {\n    overlay.setPosition(coordinates);\n  }\n\n  addStationTextStyle(text) {\n    return new Text({\n      text,\n      font: '16px sans-serif',\n      offsetY: 9,\n      backgroundFill: new Fill({\n        color: '#ffffff',\n      }),\n    });\n  }\n\n  showStationTextOnHover(e) {\n    if (e.dragging) return;\n    // Don't do this for touch.\n    if (e.pointerEvent.pointerType === 'touch') return;\n\n    const pixel = this.map.getEventPixel(e.originalEvent);\n    const feature = this.map.forEachFeatureAtPixel(pixel, f => f, {\n      hitTolerance: 3,\n    });\n\n    if (feature && feature.get('type') === 'station') {\n      const station = {\n        name: feature.get('name'),\n        showName: feature.get('showName'),\n        feature,\n      };\n      if (\n        this.lastStationHover !== null\n        && feature !== this.lastStationHover.feature\n      ) {\n        this.lastStationHover.feature.set('showName', false);\n        this.lastStationHover.feature\n          .getStyle()\n          .setText(this.addStationTextStyle(''));\n        this.lastStationHover = null;\n      }\n\n      if (!station.showName) {\n        feature.set('showName', true);\n        feature.getStyle().setText(this.addStationTextStyle(station.name));\n        this.lastStationHover = station;\n      }\n    } else if (this.lastStationHover) {\n      this.lastStationHover.feature.set('showName', false);\n      this.lastStationHover.feature\n        .getStyle()\n        .setText(this.addStationTextStyle(''));\n      this.lastStationHover = null;\n    }\n  }\n\n  showStationTextOnTouch(e) {\n    if (e.dragging) return;\n\n    const pixel = this.map.getEventPixel(e.originalEvent);\n    const feature = this.map.forEachFeatureAtPixel(pixel, f => f, {\n      hitTolerance: 3,\n    });\n    let showInsteadOfContinue = false;\n    if (feature && feature.get('type') === 'station') {\n      const station = {\n        name: feature.get('name'),\n        showName: feature.get('showName'),\n        feature,\n      };\n      if (\n        this.lastStationHover !== null\n        && feature !== this.lastStationHover.feature\n      ) {\n        this.lastStationHover.feature.set('showName', false);\n        this.lastStationHover.feature\n          .getStyle()\n          .setText(this.addStationTextStyle(''));\n        this.lastStationHover = null;\n      }\n      if (!station.showName) {\n        feature.set('showName', true);\n        feature.getStyle().setText(this.addStationTextStyle(station.name));\n        this.lastStationHover = station;\n        showInsteadOfContinue = true;\n      } else {\n        showInsteadOfContinue = false;\n      }\n    } else if (this.lastStationHover) {\n      this.lastStationHover.feature.set('showName', false);\n      this.lastStationHover.feature\n        .getStyle()\n        .setText(this.addStationTextStyle(''));\n      this.lastStationHover = null;\n      showInsteadOfContinue = false;\n    }\n\n    return showInsteadOfContinue;\n  }\n\n  generateStationFeature(station, color) {\n    const feature = new Feature({\n      // http://lyzidiamond.com/posts/4326-vs-3857\n      geometry: new Point(\n        transform(\n          [station.longitude, station.latitude],\n          'EPSG:4326',\n          'EPSG:32633',\n        ),\n      ),\n      name: `${station.station}`,\n\n      eoi: `${station.eoi}`,\n      showName: false,\n      type: 'station',\n      latitude: station.latitude,\n      longitude: station.longitude,\n      originalColor: station.latestAQI.color\n        ? station.latestAQI.color\n        : '#cfd8dc',\n    });\n    const style = new Style({\n      text: this.addStationTextStyle(''),\n      image: new Icon(\n        /** @type {olx.style.IconOptions} */ ({\n          anchor: [0.5, 1], // Hopefully middle bottom of icon\n          anchorXUnits: 'fraction',\n          anchorYUnits: 'fraction',\n          scale: 0.2,\n          color,\n          src: `${window.location.origin}/icons/icon.png`, // Relative link to the public folder.\n        }),\n      ),\n    });\n    feature.setStyle(style);\n    return feature;\n  }\n\n  addStationsToMap(list, visible) {\n    const features = [];\n    const stationComponents = {};\n    list.forEach((station) => {\n      if (station.latestAQIComponents) {\n        Object.entries(station.latestAQIComponents).forEach(([key, value]) => {\n          let c = stationComponents[key];\n          if (!c) {\n            c = [];\n            stationComponents[key] = c;\n          }\n          c.push(this.generateStationFeature(station, value.color));\n        });\n      }\n\n      features.push(this.generateStationFeature(station, station.latestAQI.color\n        ? station.latestAQI.color\n        : '#cfd8dc'));\n    });\n    const vs = new SourceVector({\n      features,\n    });\n\n    const stationVectorLayer = new LayerVector({\n      source: vs,\n      name: 'stations_aqi',\n      zIndex: 20000,\n      timeLoaded: new Date(),\n      visible,\n      // declutter: true,\n    });\n\n    this.addMapLayer(stationVectorLayer);\n\n    Object.entries(stationComponents).forEach(([key, value]) => {\n      const sv = new SourceVector({ features: value });\n      const component = key.toLowerCase().replace('.', ''); // Handle components like PM2.5\n      const lv = new LayerVector({\n        source: sv,\n        name: `stations_${component}_concentration`,\n        zIndex: 20000,\n        timeLoaded: new Date(),\n        visible,\n        // declutter: true,\n      });\n      this.addMapLayer(lv);\n    });\n  }\n\n  addCameras(cameras) {\n    const features = [];\n    cameras.forEach((camera) => {\n      const feature = new Feature({\n        // http://lyzidiamond.com/posts/4326-vs-3857\n        geometry: new Point(\n          transform(\n            [camera.longitude, camera.latitude],\n            'EPSG:4326',\n            'EPSG:32633',\n          ),\n        ),\n        name: `${camera.road}, ${camera.description}`,\n        cameraUrl: camera.url,\n        camera: true,\n      });\n      const style = new Style({\n        image: new Icon(\n          /** @type {olx.style.IconOptions} */ ({\n            anchor: [0.5, 1], // Hopefully middle bottom of icon\n            anchorXUnits: 'fraction',\n            anchorYUnits: 'fraction',\n            scale: 0.4,\n            color: '#885EAD',\n            src: `${window.location.origin}/icons/camera.png`, // Relative link to the public folder.\n          }),\n        ),\n      });\n      feature.setStyle(style);\n      features.push(feature);\n    });\n    const vs = new SourceVector({\n      features,\n    });\n\n    const cameraVectorLayer = new LayerVector({\n      source: vs,\n      name: 'Cameras',\n      zIndex: 10000,\n      timeLoaded: new Date(),\n      visible: false,\n    });\n\n    this.addMapLayer(cameraVectorLayer);\n  }\n\n  addGeoDataWmts(wmts) {\n    const result = this.parser.read(wmts);\n    const options = optionsFromCapabilities(result, {\n      layer: 'Geocache_UTM33_WGS84_GeocacheGraatone',\n      matrixSet: 'default028mm',\n    });\n\n    this.addMapLayer(\n      new TileLayer({\n        opacity: 1,\n        zIndex: -1,\n        source: new WMTS(\n          /** @type {!module:ol/source/WMTS~Options} */ (options),\n        ),\n        name: 'base',\n      }),\n    );\n  }\n\n  addMetsWms(layernames, wms) {\n    const parser = new WMSCapabilities();\n\n    const result = parser.read(wms);\n\n    layernames.forEach((layer) => {\n      const newLayer = new TileLayer({\n        name: layer.name,\n        zIndex: 100,\n        source: new TileWMS({\n          url: 'https://halo-wms.met.no/halo/default.map',\n          crossOrigin: 'anonymous',\n          params: {\n            LAYERS: layer.name,\n            TIME: '2017-12-09T00%3A00%3A00.000Z',\n            TRANSPARENT: 'true',\n          },\n          serverType: 'mapserver',\n        }),\n        visible: false,\n      });\n      newLayer.getSource().on('tileloadstart', () => {\n        try {\n          this.progressBarHandler.addLoading();\n        } catch (e) {\n          // This error occurs when we leave the page before tiles have loaded properly. Ignore.\n          // console.log(e);\n        }\n      });\n      newLayer.getSource().on('tileloadend', () => {\n        try {\n          this.progressBarHandler.addDone();\n        } catch (e) {\n          // This error occurs when we leave the page before tiles have loaded properly. Ignore.\n          // console.log(e);\n        }\n      });\n      newLayer.getSource().on('tileloaderror', () => {\n        try {\n          this.progressBarHandler.addDone();\n        } catch (e) {\n          // This error occurs when we leave the page before tiles have loaded properly. Ignore.\n          // console.log(e);\n        }\n      });\n      this.addMapLayer(newLayer);\n    });\n    return {\n      // default: dims.Default,\n      // // values: dims.Value,\n    };\n  }\n\n  addMetsWmts(layernames, wmts) {\n    const parser = new WMTSCapabilities();\n    const result = parser.read(wmts);\n\n    const dims = result.Contents.Layer[0].Dimension[0];\n\n    const today = new Date();\n    if (\n      new Date(dims.Value[0]) > today\n      || today > new Date(dims.Value[dims.Value.length - 1])\n    ) {\n      // Bad today date. Data out of range. Return null.\n      return null;\n    }\n\n    layernames.forEach((layer) => {\n      const options = optionsFromCapabilities(result, {\n        layer: layer.name,\n        matrixSet: 'utm33_norway',\n      });\n      const newLayer = new TileLayer({\n        opacity: 0.7,\n        source: new WMTS(\n          /** @type {!module:ol/source/WMTS~Options} */ (options),\n        ),\n        name: layer.name,\n        visible: layer.show,\n        useInterimTilesOnError: false,\n      });\n      newLayer.getSource().on('tileloadstart', () => {\n        try {\n          this.progressBarHandler.addLoading();\n        } catch (e) {\n          // This error occurs when we leave the page before tiles have loaded properly. Ignore.\n          // console.log(e);\n        }\n      });\n      newLayer.getSource().on('tileloadend', () => {\n        try {\n          this.progressBarHandler.addDone();\n        } catch (e) {\n          // This error occurs when we leave the page before tiles have loaded properly. Ignore.\n          // console.log(e);\n        }\n      });\n      newLayer.getSource().on('tileloaderror', () => {\n        try {\n          this.progressBarHandler.addDone();\n        } catch (e) {\n          // This error occurs when we leave the page before tiles have loaded properly. Ignore.\n          // console.log(e);\n        }\n      });\n      this.addMapLayer(newLayer);\n    });\n    return {\n      default: dims.Default,\n      values: dims.Value,\n    };\n  }\n\n  // Call this by:\n  // (constructor) this.map = React.createRef();\n  // (render) <OLMap ref=[this.map] ...\n  // (function) this.map.current.addMapLayer(layer);\n  addMapLayer(layer) {\n    this.map.addLayer(layer);\n  }\n\n  addMapControl(control) {\n    this.map.addControl(control);\n  }\n\n  setVisibleLayers(activeLayers) {\n    this.map\n      .getLayers()\n      .getArray()\n      .filter(l => l.get('name') !== 'base')\n      .forEach((layer) => {\n        layer.setVisible(activeLayers.includes(layer.get('name')));\n      });\n  }\n\n  updateTimeDimensions(time) {\n    this.map\n      .getLayers()\n      .getArray()\n      .forEach((layer) => {\n        if (layer.get('name') !== 'base' && layer.get('name') !== 'Stations') {\n          try {\n            layer.getSource().updateDimensions({ time });\n          } catch (e) {\n            try {\n              layer.getSource().updateParams({ TIME: time });\n            } catch (e) {\n              // console.log(\"WMS :'(\")\n            }\n          }\n        }\n        if (layer.get('name') === 'Stations') {\n          let isNow = false;\n          const now = layer.get('timeLoaded') || new Date();\n          const timeDate = new Date(time);\n\n          if (\n            now.getHours() === timeDate.getHours()\n            && now.getDate() === timeDate.getDate()\n          ) {\n            isNow = true;\n          }\n\n          layer\n            .getSource()\n            .getFeatures()\n            .forEach((feature) => {\n              const style = new Style({\n                image: new Icon(\n                  /** @type {olx.style.IconOptions} */ ({\n                    anchor: [0.5, 1], // Hopefully middle bottom of icon\n                    anchorXUnits: 'fraction',\n                    anchorYUnits: 'fraction',\n                    scale: 0.2,\n                    color: isNow ? feature.get('originalColor') : '#cfd8dc',\n                    src: `${window.location.origin}/icons/icon.png`, // Relative link to the public folder.\n                  }),\n                ),\n              });\n              feature.setStyle(style);\n            });\n        }\n      });\n  }\n\n  panTo(lat, long, zoom = -1) {\n    this.map\n      .getView()\n      .setCenter(transform([long, lat], 'EPSG:4326', 'EPSG:32633'));\n    if (zoom > -1) {\n      this.map.getView().setZoom(zoom);\n    }\n  }\n\n  render() {\n    return <div id=\"olmap\" className=\"ol-map-wrapper\" />;\n  }\n}\n","import React, { Component } from 'react';\nimport Spinner from 'components/elements/spinner/Spinner';\nimport './TimeSliderControl.scss';\nimport Play from './play.svg'\nimport Pause from './pause.svg'\nimport Localization, { setLanguage } from 'languages/components/map/MapLan';\nimport { isMobile } from 'react-device-detect';\n\nclass TimeSliderControl extends Component {\n  static WeekdayDictionaryNOR() {\n    const weekday = new Array(7);\n    weekday[0] = Localization.timeSliderSunday;\n    weekday[1] = Localization.timeSliderMonday;\n    weekday[2] = Localization.timeSliderTuesday;\n    weekday[3] = Localization.timeSliderWednesday;\n    weekday[4] = Localization.timeSliderThursday;\n    weekday[5] = Localization.timeSliderFriday;\n    weekday[6] = Localization.timeSliderSaturday;\n\n    return weekday;\n  }\n\n  static pinOffset(index, totalPins, px) {\n    const intervalWidth = 100.0 / totalPins;\n\n    const temp = (intervalWidth * index) - (intervalWidth);\n    return `calc(${temp}% - ${px}px)`;\n  }\n\n  static dayLabel(time, times) {\n    const day = new Date(time.date).getDay();\n    const timesThisDay = times.filter(t => new Date(t.date).getDay() === day);\n    if (timesThisDay.length > 4) {\n      const middleIndex = Math.floor(timesThisDay.length / 2);\n\n      const middleDay = timesThisDay[middleIndex];\n\n      if (middleDay === time) {\n        if (timesThisDay.length < 12) {\n          return time.dayName.substring(0, 3);\n        }\n\n        return time.dayName;\n      }\n    }\n    return '';\n  }\n\n\n  static restructureTime(times) {\n    const timelist = [];\n    const cutArray = [];\n    const days = [];\n\n    const wdDict = TimeSliderControl.WeekdayDictionaryNOR();\n\n    times.forEach((t) => {\n      const date = new Date(t);\n      const day = date.getDay();\n\n      cutArray.push(t);\n      if (days.indexOf(day) === -1) {\n        days.push(date.getDay());\n      }\n\n      timelist.push({\n        date: t,\n        hour: date.getHours(),\n        day,\n        dayName: wdDict[day],\n      });\n    });\n    const dayNames = [];\n    days.forEach((d) => {\n      dayNames.push(wdDict[d]);\n    });\n\n    const obj = {\n      days: dayNames,\n      sliderDates: cutArray,\n      timelist,\n    };\n\n    return obj;\n  }\n\n  static getSliderNow(timeobj, timeParam) {\n    let now = new Date();\n\n    // Override if we get date from url\n    if (timeParam) {\n      try {\n        const paramDate = new Date(timeParam);\n        now = paramDate;\n      } catch (e) {\n        // Bad date, ignore param\n      }\n    }\n\n    const day = now.getDay();\n    const hour = now.getHours();\n\n    // Index for the slider.\n    let index = 0;\n\n    let answer = null;\n    for (let i = 0; i < timeobj.timelist.length; i++) {\n      if (timeobj.timelist[i].day === day\n        && timeobj.timelist[i].hour === hour) {\n        // We know that day number (0 = sunday) matches and the hour matches.\n        // But we need to check that the date is the same as well.\n        // The time set we have may be for a week or more ago. Doublecheck that we are up to speed.\n        const doublecheckDate = new Date(timeobj.timelist[i].date);\n        if (doublecheckDate.getUTCDate() === now.getUTCDate()\n            && doublecheckDate.getUTCMonth() === now.getUTCMonth()\n            && doublecheckDate.getUTCFullYear() === now.getUTCFullYear()) {\n          answer = i;\n          break;\n        }\n      }\n    }\n\n    // If we found it, send back the index. Otherwise start slider at first value.\n    if (answer !== null) {\n      index = answer;\n    }\n\n    return index;\n  }\n\n\n  constructor(props) {\n    super(props);\n\n    setLanguage();\n    this.sliderOnChange = this.sliderOnChange.bind(this);\n    this.togglePlay = this.togglePlay.bind(this);\n    this.setupTimeslider = this.setupTimeslider.bind(this);\n    this.writeCleanTime = this.writeCleanTime.bind(this);\n\n    this.state = {\n      isLoading: true,\n      timeobj: {},\n      newTimes: [],\n      sliderValue: -1,\n      isPlaying: false,\n      playingIntervalId: undefined\n    };\n\n  }\n\n\n\n  componentDidUpdate(prevProps, prevState) {\n    if (prevProps.times.length !== this.props.times.length) {\n      this.setupTimeslider();\n    }\n    if (this.props.times.length > 0\n      && this.props.map\n      && prevState.sliderValue !== this.state.sliderValue) {\n      this.props.map.updateTimeDimensions(this.state.newTimes[this.state.sliderValue]);\n      if (this.props.onTimeSliderChange) {\n        this.props.onTimeSliderChange(this.state.newTimes[this.state.sliderValue]);\n      }\n    }\n  }\n  componentDidMount() {\n   // MET has complained of too high ressource usage of this feature - so we do not enable auto play per default\n   // if (!isMobile) {\n   //   this.togglePlay();\n   // }\n  }\n  \n  componentWillUnmount() {\n    if (this.state.playingIntervalId) {\n       clearInterval(this.state.playingIntervalId);\n    }\n }\n\n  togglePlay() {\n    let newIntervalId = undefined;\n    if (this.state.isPlaying) {\n      clearInterval(this.state.playingIntervalId);\n    }\n    else {\n        newIntervalId =     \n        setInterval(() => {\n          if (this.state.sliderValue < this.state.newTimes.length - 1) {\n             this.setState(prevState => ({  \n                ...prevState,\n                sliderValue: prevState.sliderValue < prevState.newTimes.length - 1 ? prevState.sliderValue + 1 : prevState.sliderValue\n              }));\n          }\n          else {\n            if (this.state.isPlaying) {\n              this.togglePlay();\n            }\n          }\n         \n        }, 1000  ); \n    }\n    this.setState({\n      ...this.state,\n      playingIntervalId: newIntervalId, \n      isPlaying: !this.state.isPlaying\n    });\n  }\n  setupTimeslider() {\n    const timeobj = TimeSliderControl.restructureTime(this.props.times);\n    const newTimes = timeobj.sliderDates;\n    this.setState({ isLoading: false, timeobj, newTimes });\n\n    const now = TimeSliderControl.getSliderNow(timeobj, this.props.timeParam);\n    this.sliderOnChange(now.toString());\n  }\n\n\n  sliderOnChange(index) {\n    console.log(index);\n    this.setState({ sliderValue: parseInt(index, 10) });\n  }\n\n  writeCleanTime(hour, index) {\n    let returnText = '';\n    if (index === this.state.sliderValue) {\n      returnText = hour < 10 ? `0${hour}` : `${hour}`;\n    }\n    return returnText;\n  }\n\n  render() {\n    if (this.state.isLoading) {\n      return <Spinner />;\n    }\n    const numPins = this.state.timeobj.timelist.length;\n    const intervalWidth = 100.0 / numPins;\n\n    return (\n      <div className=\"c_timeline\">\n       <img className=\"c_play\" src={this.state.isPlaying ? Pause : Play} onClick={this.togglePlay}/>\n        <div className=\"c_timeline__days\">\n          {this.state.timeobj.timelist.map((t, i) => <span key={t.date} style={{ position: 'absolute', left: TimeSliderControl.pinOffset(i + 1, numPins, 3) }}>{TimeSliderControl.dayLabel(t, this.state.timeobj.timelist)}</span>)}\n        </div>\n        <div className=\"c_timeline__pins\" style={{ width: `calc(88% + ${intervalWidth}%)` }}>\n          <div className=\"pins__big\">\n            {this.state.timeobj.timelist.map((t, i) => <span style={{ left: TimeSliderControl.pinOffset(i + 1, numPins, 3) }} data-t={t.date} key={t.date} className={t.hour === 0 ? 'active' : ''} />)}\n          </div>\n          <div className=\"pins__progress\">\n            {this.state.timeobj.timelist.map((t, i) => \n            {\n              let classes = i === this.state.sliderValue ? 'active' : '';\n              if (i < this.state.sliderValue) {\n                classes = `${classes} past`\n              }\n              return (<span style={{ left: TimeSliderControl.pinOffset(i + 1, numPins, 1) }} data-t={t.date} key={t.date} className={classes}><span>{this.writeCleanTime(t.hour, i)}</span></span>)\n            })}\n          </div>\n          <div className=\"pins__now_marker\">\n            {this.state.timeobj.timelist.map((t, i) => \n            {\n              let classes = i === this.state.sliderValue ? 'active' : '';\n              return (<span style={{ left: TimeSliderControl.pinOffset(i + 1, numPins, 9) }} data-t={t.date} key={t.date} className={classes}><span></span></span>)\n            })}\n          </div>\n\n          <div className=\"pins__small\">\n            {this.state.timeobj.timelist.map((t, i) => \n            {\n              let classes = i === this.state.sliderValue ? 'active' : '';\n              if (i % 2 == 1) {\n                classes = `${classes} unequal`\n              }\n              return (<span style={{ left: TimeSliderControl.pinOffset(i + 1, numPins, 1) }} data-t={t.date} key={t.date} className={classes}><span>{this.writeCleanTime(t.hour, i)}</span></span>)\n            })}\n          </div>\n          <div className=\"pins__intervals\">\n            {this.state.timeobj.timelist.map((t, i) => {\n              const style = { left: TimeSliderControl.pinOffset(i + 1, numPins, 13) };\n              if (t.hour % 2 === 0) {\n                return <span style={style} data-t={t.date} key={t.date}>{t.hour < 10 ? `0${t.hour}` : t.hour}</span>;\n              }\n              return <span style={style}  data-t={t.date} key={t.date} />;\n            })}\n          </div>\n        </div>\n        <div className=\"c_timeline__slider\">\n          <label id=\"c_timeslider__label\" htmlFor=\"c_timeslider__id\">\n            {Localization.timesliderName}\n          </label>\n          <input\n            id=\"c_timeslider__id\"\n            className=\"slider__range\"\n            type=\"range\"\n            step=\"1\"\n            min=\"0\"\n            value={this.state.sliderValue}\n            max={this.state.newTimes.length - 1}\n            onChange={e => this.sliderOnChange(e.target.value)}\n          />\n        </div>\n      </div>\n    );\n  }\n}\n\nexport default TimeSliderControl;\n","import React, { Component } from 'react';\nimport './OlProgressBar.scss';\n\nclass OlProgressBar extends Component {\n  constructor(props) {\n    super(props);\n    this.loading = 0;\n    this.done = 0;\n\n    this.progressBar = React.createRef();\n    this.addLoading = this.addLoading.bind(this);\n    this.addDone = this.addDone.bind(this);\n    this.update = this.update.bind(this);\n  }\n\n  addLoading() {\n    try {\n      if (this.loading === 0) {\n        this.progressBar.current.style.visibility = 'visible';\n      }\n      this.loading += 1;\n      this.update();\n    } catch (e) {\n      // Ignore\n    }\n  }\n\n  addDone() {\n    try {\n      this.done += 1;\n      this.update();\n    } catch (e) {\n      // Ignore\n    }\n  }\n\n  update() {\n    const width = `${(this.done / this.loading * 100).toFixed(1)}%`;\n    this.progressBar.current.style.width = width;\n\n    if (this.loading === this.done) {\n      this.loading = 0;\n      this.done = 0;\n      setTimeout(() => {\n        if (this.progressBar.current) {\n          this.progressBar.current.style.visibility = 'hidden';\n          this.progressBar.current.style.width = 0;\n        }\n      }, 750);\n    }\n  }\n\n  render() {\n    return <div id=\"progressbar\" className=\"c_ol-progressbar\" ref={this.progressBar} />;\n  }\n}\n\nexport default OlProgressBar;\n","module.exports = __webpack_public_path__ + \"static/media/play.438abd6d.svg\";","module.exports = __webpack_public_path__ + \"static/media/pause.73b23d49.svg\";"],"sourceRoot":""}