Add arrival time + nearby stations
This commit is contained in:
		
							parent
							
								
									f3d474a9c7
								
							
						
					
					
						commit
						e0ad2fa46c
					
				
					 3 changed files with 242 additions and 492 deletions
				
			
		
							
								
								
									
										351
									
								
								config-route.js
									
										
									
									
									
								
							
							
						
						
									
										351
									
								
								config-route.js
									
										
									
									
									
								
							| 
						 | 
					@ -10,6 +10,7 @@ var toStation = null
 | 
				
			||||||
 * @type {Date | null}
 | 
					 * @type {Date | null}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
var departureDate = null
 | 
					var departureDate = null
 | 
				
			||||||
 | 
					var arrivalInsteadOfDeparture = false
 | 
				
			||||||
var transitKind = {
 | 
					var transitKind = {
 | 
				
			||||||
    ice: true,
 | 
					    ice: true,
 | 
				
			||||||
    ic: true,
 | 
					    ic: true,
 | 
				
			||||||
| 
						 | 
					@ -28,7 +29,11 @@ var starred = []
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
var knownStations = []
 | 
					var knownStations = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var itineraries = null
 | 
					/**
 | 
				
			||||||
 | 
					 * @type {'unavailable' | 'notRequested' | 'waiting' | 'gotData'}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					var nearbyStatus = 'notRequested'
 | 
				
			||||||
 | 
					var nearbyStations = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function goToStation(stationId) {
 | 
					function goToStation(stationId) {
 | 
				
			||||||
    var url = new URL(window.location.href)
 | 
					    var url = new URL(window.location.href)
 | 
				
			||||||
| 
						 | 
					@ -62,26 +67,8 @@ var focusedElement = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _rebuildDebounce = null
 | 
					var _rebuildDebounce = null
 | 
				
			||||||
var _rebuildRequested = false
 | 
					var _rebuildRequested = false
 | 
				
			||||||
function rebuildSuggestions() {
 | 
					function createSuggestion(suggestion, index) {
 | 
				
			||||||
    if (_rebuildDebounce !== null) {
 | 
					    delete suggestion['products']
 | 
				
			||||||
        _rebuildRequested = true
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _rebuildRequested = false
 | 
					 | 
				
			||||||
    _rebuildDebounce = 123
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var suggestionsArea = document.getElementById('suggestionsArea')
 | 
					 | 
				
			||||||
    while (suggestionsArea.childNodes.length > 0) {
 | 
					 | 
				
			||||||
        suggestionsArea.childNodes[0].remove()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var suggestions = knownStations.slice()
 | 
					 | 
				
			||||||
    if (suggestions.length === 0) {
 | 
					 | 
				
			||||||
        suggestions = starred.map(function (s) { return JSON.parse(s) })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suggestions.forEach(function (suggestion, index) {
 | 
					 | 
				
			||||||
    var suggestionDiv = document.createElement('div')
 | 
					    var suggestionDiv = document.createElement('div')
 | 
				
			||||||
    suggestionDiv.classList.add('suggestion')
 | 
					    suggestionDiv.classList.add('suggestion')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,7 +76,9 @@ function rebuildSuggestions() {
 | 
				
			||||||
    suggestionDiv.appendChild(suggestionLi)
 | 
					    suggestionDiv.appendChild(suggestionLi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suggestionLi.classList.add('items')
 | 
					    suggestionLi.classList.add('items')
 | 
				
			||||||
 | 
					    if (index) {
 | 
				
			||||||
        suggestionLi.tabIndex = index + 1
 | 
					        suggestionLi.tabIndex = index + 1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    suggestionLi.style.padding = '2px 0'
 | 
					    suggestionLi.style.padding = '2px 0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function onAction(e) {
 | 
					    function onAction(e) {
 | 
				
			||||||
| 
						 | 
					@ -108,12 +97,24 @@ function rebuildSuggestions() {
 | 
				
			||||||
    var stationNameP = document.createElement('p')
 | 
					    var stationNameP = document.createElement('p')
 | 
				
			||||||
    suggestionLi.appendChild(stationNameP)
 | 
					    suggestionLi.appendChild(stationNameP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        stationNameP.textContent = suggestion.name || suggestion.address
 | 
					    var stationNameSpan = document.createElement('span')
 | 
				
			||||||
        stationNameP.classList.add('pri', 'stationName')
 | 
					    stationNameP.append(stationNameSpan)
 | 
				
			||||||
 | 
					    stationNameSpan.textContent = suggestion.name || suggestion.address
 | 
				
			||||||
 | 
					    stationNameSpan.classList.add('pri', 'stationName')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (suggestion.distance) {
 | 
				
			||||||
 | 
					        stationNameP.append(' ')
 | 
				
			||||||
 | 
					        var stationDistanceSpan = document.createElement('span')
 | 
				
			||||||
 | 
					        stationNameP.append(stationDistanceSpan)
 | 
				
			||||||
 | 
					        stationDistanceSpan.append('(', suggestion.distance.toString(), ' m)')
 | 
				
			||||||
 | 
					        stationDistanceSpan.classList.add('stationDistance')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (window.localStorage) {
 | 
					    if (window.localStorage) {
 | 
				
			||||||
 | 
					        var suggestionDistance = suggestion['distance']
 | 
				
			||||||
 | 
					        delete suggestion['distance']
 | 
				
			||||||
        var suggestionLink = document.createElement('a')
 | 
					        var suggestionLink = document.createElement('a')
 | 
				
			||||||
            suggestionDiv.appendChild(suggestionLink)
 | 
					 | 
				
			||||||
        suggestionLink.classList.add('no-custom-a')
 | 
					        suggestionLink.classList.add('no-custom-a')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var suggestionStar = document.createElement('object')
 | 
					        var suggestionStar = document.createElement('object')
 | 
				
			||||||
| 
						 | 
					@ -143,6 +144,8 @@ function rebuildSuggestions() {
 | 
				
			||||||
            localStorage.setItem('stations/starred', JSON.stringify(starred))
 | 
					            localStorage.setItem('stations/starred', JSON.stringify(starred))
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        setStar()
 | 
					        setStar()
 | 
				
			||||||
 | 
					        suggestionDiv.appendChild(suggestionLink)
 | 
				
			||||||
 | 
					        suggestion['distance'] = suggestionDistance
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // var trainCompanyP = document.createElement('p')
 | 
					    // var trainCompanyP = document.createElement('p')
 | 
				
			||||||
| 
						 | 
					@ -150,9 +153,84 @@ function rebuildSuggestions() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // trainCompanyP.textContent = suggestion.company
 | 
					    // trainCompanyP.textContent = suggestion.company
 | 
				
			||||||
    // trainCompanyP.classList.add('thi')
 | 
					    // trainCompanyP.classList.add('thi')
 | 
				
			||||||
        suggestionsArea.appendChild(suggestionDiv)
 | 
					    return suggestionDiv
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function rebuildSuggestions() {
 | 
				
			||||||
 | 
					    if (_rebuildDebounce !== null) {
 | 
				
			||||||
 | 
					        _rebuildRequested = true
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _rebuildRequested = false
 | 
				
			||||||
 | 
					    _rebuildDebounce = 123
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var suggestionsArea = document.getElementById('suggestionsArea')
 | 
				
			||||||
 | 
					    while (suggestionsArea.childNodes.length > 0) {
 | 
				
			||||||
 | 
					        suggestionsArea.childNodes[0].remove()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var suggestions = knownStations.slice()
 | 
				
			||||||
 | 
					    if (suggestions.length === 0) {
 | 
				
			||||||
 | 
					        suggestions = starred.map(function (s) { return JSON.parse(s) })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    suggestions.forEach(function (suggestion, index) {
 | 
				
			||||||
 | 
					        suggestionsArea.appendChild(createSuggestion(suggestion, index))
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (nearbyStatus !== 'unavailable') {
 | 
				
			||||||
 | 
					        suggestionsArea.appendChild(h4('Nearby stations'))
 | 
				
			||||||
 | 
					        if (nearbyStatus === 'notRequested') {
 | 
				
			||||||
 | 
					            suggestionsArea.appendChild(a('', 'Load nearby stations').event$('click', function (event) {
 | 
				
			||||||
 | 
					                event.preventDefault()
 | 
				
			||||||
 | 
					                var watchId = navigator.geolocation.watchPosition(
 | 
				
			||||||
 | 
					                    function (data) {
 | 
				
			||||||
 | 
					                        var geoUrl = new URL('https://v6.db.transport.rest/locations/nearby')
 | 
				
			||||||
 | 
					                        geoUrl.searchParams.append('latitude', data.coords.latitude.toString())
 | 
				
			||||||
 | 
					                        geoUrl.searchParams.append('longitude', data.coords.longitude.toString())
 | 
				
			||||||
 | 
					                        geoUrl.searchParams.append('results', '10')
 | 
				
			||||||
 | 
					                        fetch(geoUrl)
 | 
				
			||||||
 | 
					                            .then(function (response) {
 | 
				
			||||||
 | 
					                                return response.json()
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                            .then(function (data) {
 | 
				
			||||||
 | 
					                                nearbyStatus = 'gotData'
 | 
				
			||||||
 | 
					                                nearbyStations = data
 | 
				
			||||||
 | 
					                                rebuildSuggestions()
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                            .catch(function () {
 | 
				
			||||||
 | 
					                                nearbyStatus = 'unavailable'
 | 
				
			||||||
 | 
					                                rebuildSuggestions()
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    function (error) {
 | 
				
			||||||
 | 
					                        if (nearbyStations.length === 0) {
 | 
				
			||||||
 | 
					                            nearbyStatus = 'unavailable'
 | 
				
			||||||
 | 
					                            rebuildSuggestions()
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        navigator.geolocation.clearWatch(watchId)
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        enableHighAccuracy: true,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                nearbyStatus = 'waiting'
 | 
				
			||||||
 | 
					                rebuildSuggestions()
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (nearbyStatus === 'waiting') {
 | 
				
			||||||
 | 
					            var waitingP = document.createElement('p')
 | 
				
			||||||
 | 
					            suggestionsArea.append(waitingP)
 | 
				
			||||||
 | 
					            waitingP.append('Loading...')
 | 
				
			||||||
 | 
					            waitingP.classList.add('pri')
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (nearbyStatus === 'gotData') {
 | 
				
			||||||
 | 
					            nearbyStations.forEach(function (suggestion, index) {
 | 
				
			||||||
 | 
					                suggestionsArea.appendChild(createSuggestion(suggestion, suggestions.length + index))
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setTimeout(function () {
 | 
					    setTimeout(function () {
 | 
				
			||||||
        _rebuildDebounce = null
 | 
					        _rebuildDebounce = null
 | 
				
			||||||
        if (_rebuildRequested) {
 | 
					        if (_rebuildRequested) {
 | 
				
			||||||
| 
						 | 
					@ -193,165 +271,6 @@ function reloadSuggestions() {
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @typedef DbJourney
 | 
					 | 
				
			||||||
 * @prop {'journey'} type
 | 
					 | 
				
			||||||
 * @prop {(DbTrip & DbArrDep & {tripId: string})[]} legs
 | 
					 | 
				
			||||||
 * @prop {string} refreshToken
 | 
					 | 
				
			||||||
 * @prop {DbRemark[]} remarks
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @param {{journeys: DbJourney[]}} data
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function onItineraries(data) {
 | 
					 | 
				
			||||||
    var contentDiv = document.createElement('div')
 | 
					 | 
				
			||||||
    document.body.insertBefore(contentDiv, document.querySelector('footer'))
 | 
					 | 
				
			||||||
    contentDiv.classList.add('content')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (var i = 0; i < data.journeys.length; i++) {
 | 
					 | 
				
			||||||
        var itineraryDiv = document.createElement('div')
 | 
					 | 
				
			||||||
        contentDiv.appendChild(itineraryDiv)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var heading = document.createElement('h4')
 | 
					 | 
				
			||||||
        itineraryDiv.appendChild(heading)
 | 
					 | 
				
			||||||
        heading.textContent = `Itinerary ${i + 1}`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var trainsDiv = document.createElement('div')
 | 
					 | 
				
			||||||
        itineraryDiv.appendChild(trainsDiv)
 | 
					 | 
				
			||||||
        trainsDiv.classList.add('itinerary-trains')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        data.journeys[i].legs.forEach(function (train, idx) {
 | 
					 | 
				
			||||||
            var last = idx === data.journeys[i].legs.length - 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var trainDiv = document.createElement('div')
 | 
					 | 
				
			||||||
            trainsDiv.appendChild(trainDiv)
 | 
					 | 
				
			||||||
            trainDiv.classList.add('itinerary-train')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (idx === 0) {
 | 
					 | 
				
			||||||
                var departureTimeP = document.createElement('p')
 | 
					 | 
				
			||||||
                trainDiv.appendChild(departureTimeP)
 | 
					 | 
				
			||||||
                departureTimeP.classList.add('sec', 'departure', 'time')
 | 
					 | 
				
			||||||
                var departureTimePre = document.createElement('pre')
 | 
					 | 
				
			||||||
                departureTimeP.appendChild(departureTimePre)
 | 
					 | 
				
			||||||
                var departure = new Date(train.plannedDeparture)
 | 
					 | 
				
			||||||
                departureTimePre.textContent = departure.toLocaleTimeString([], { 'hour': '2-digit', 'minute': '2-digit' })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var departureHeading = document.createElement('h3')
 | 
					 | 
				
			||||||
                trainDiv.appendChild(departureHeading)
 | 
					 | 
				
			||||||
                departureHeading.classList.add('departure', 'station')
 | 
					 | 
				
			||||||
                if (train.origin.type === 'stop' || train.origin.type === 'station') {
 | 
					 | 
				
			||||||
                    var departureLink = document.createElement('a')
 | 
					 | 
				
			||||||
                    departureHeading.appendChild(departureLink)
 | 
					 | 
				
			||||||
                    departureLink.textContent = train.origin.name
 | 
					 | 
				
			||||||
                    departureLink.classList.add('no-custom-a', 'items')
 | 
					 | 
				
			||||||
                    var departureUrl = new URL('/view-station.html', window.location.origin)
 | 
					 | 
				
			||||||
                    departureUrl.searchParams.set('stationId', train.origin.id)
 | 
					 | 
				
			||||||
                    departureLink.href = departureUrl.toString()
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else {
 | 
					 | 
				
			||||||
                    var departureSpan = document.createElement('span')
 | 
					 | 
				
			||||||
                    departureHeading.append(departureSpan)
 | 
					 | 
				
			||||||
                    departureSpan.innerText = train.origin.name || train.origin.address
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                if (train.departurePlatform || train.plannedDeparturePlatform) {
 | 
					 | 
				
			||||||
                    var departurePlatformP = document.createElement('p')
 | 
					 | 
				
			||||||
                    trainDiv.append(departurePlatformP)
 | 
					 | 
				
			||||||
                    departurePlatformP.classList.add('sec', 'departure', 'platform')
 | 
					 | 
				
			||||||
                    if (train.departurePlatform && train.departurePlatform != train.plannedDeparturePlatform) {
 | 
					 | 
				
			||||||
                        departurePlatformP.classList.add('changed')
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    departurePlatformP.textContent = `${train.departurePlatform || train.plannedDeparturePlatform}`
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var trainP = document.createElement('p')
 | 
					 | 
				
			||||||
            trainDiv.appendChild(trainP)
 | 
					 | 
				
			||||||
            trainP.classList.add('pri', 'train')
 | 
					 | 
				
			||||||
            if (!train.walking) {
 | 
					 | 
				
			||||||
                var trainLink = document.createElement('a')
 | 
					 | 
				
			||||||
                trainP.appendChild(trainLink)
 | 
					 | 
				
			||||||
                trainLink.innerText = train.line.name
 | 
					 | 
				
			||||||
                trainLink.classList.add('no-custom-a', 'items')
 | 
					 | 
				
			||||||
                var trainUrl = new URL('/view-train.html', window.location.origin)
 | 
					 | 
				
			||||||
                trainUrl.searchParams.set('tripId', train.tripId)
 | 
					 | 
				
			||||||
                trainLink.href = trainUrl.toString()
 | 
					 | 
				
			||||||
                trainP.appendChild(document.createTextNode(' '))
 | 
					 | 
				
			||||||
                if (train.line.operator) {
 | 
					 | 
				
			||||||
                    var trainCompany = document.createElement('span')
 | 
					 | 
				
			||||||
                    trainP.appendChild(trainCompany)
 | 
					 | 
				
			||||||
                    trainCompany.textContent = '(' + train.line.operator.name + ')'
 | 
					 | 
				
			||||||
                    trainCompany.classList.add('company')
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                var walkingSpan = document.createElement('span')
 | 
					 | 
				
			||||||
                trainP.append(walkingSpan)
 | 
					 | 
				
			||||||
                walkingSpan.classList.add('walking')
 | 
					 | 
				
			||||||
                walkingSpan.innerText = `Walking (${train.distance} m)`
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var arrivalTimeP = document.createElement('p')
 | 
					 | 
				
			||||||
            trainDiv.appendChild(arrivalTimeP)
 | 
					 | 
				
			||||||
            arrivalTimeP.classList.add('sec', 'arrival', 'time')
 | 
					 | 
				
			||||||
            var arrivalTimePre = document.createElement('pre')
 | 
					 | 
				
			||||||
            arrivalTimeP.appendChild(arrivalTimePre)
 | 
					 | 
				
			||||||
            var arrival = new Date(train.plannedArrival)
 | 
					 | 
				
			||||||
            arrivalTimePre.textContent = arrival.toLocaleTimeString([], { 'hour': '2-digit', 'minute': '2-digit' })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var arrivalHeading = document.createElement('h3')
 | 
					 | 
				
			||||||
            trainDiv.appendChild(arrivalHeading)
 | 
					 | 
				
			||||||
            arrivalHeading.classList.add('arrival', 'station')
 | 
					 | 
				
			||||||
            if (train.destination.type === 'stop' || train.destination.type === 'station') {
 | 
					 | 
				
			||||||
                var arrivalLink = document.createElement('a')
 | 
					 | 
				
			||||||
                arrivalHeading.appendChild(arrivalLink)
 | 
					 | 
				
			||||||
                arrivalLink.textContent = train.destination.name
 | 
					 | 
				
			||||||
                arrivalLink.classList.add('no-custom-a', 'items')
 | 
					 | 
				
			||||||
                var arrivalUrl = new URL('/view-station.html', window.location.origin)
 | 
					 | 
				
			||||||
                arrivalUrl.searchParams.set('stationId', train.destination.id)
 | 
					 | 
				
			||||||
                arrivalLink.href = arrivalUrl.toString()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                var arrivalSpan = document.createElement('span')
 | 
					 | 
				
			||||||
                arrivalHeading.append(arrivalSpan)
 | 
					 | 
				
			||||||
                arrivalSpan.innerText = train.destination.name || train.origin.address
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
            if (train.arrivalPlatform || train.plannedArrivalPlatform) {
 | 
					 | 
				
			||||||
                var arrivalPlatformP = document.createElement('p')
 | 
					 | 
				
			||||||
                trainDiv.append(arrivalPlatformP)
 | 
					 | 
				
			||||||
                arrivalPlatformP.classList.add('sec', 'arrival', 'platform')
 | 
					 | 
				
			||||||
                if (train.arrivalPlatform && train.arrivalPlatform != train.plannedArrivalPlatform) {
 | 
					 | 
				
			||||||
                    arrivalPlatformP.classList.add('changed')
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                arrivalPlatformP.textContent = `${train.arrivalPlatform || train.plannedArrivalPlatform}`
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!last) {
 | 
					 | 
				
			||||||
                var nextTrain = data.journeys[i].legs[idx + 1]
 | 
					 | 
				
			||||||
                var nextDepartureTimeP = document.createElement('p')
 | 
					 | 
				
			||||||
                trainDiv.appendChild(nextDepartureTimeP)
 | 
					 | 
				
			||||||
                nextDepartureTimeP.classList.add('sec', 'next-departure', 'time')
 | 
					 | 
				
			||||||
                var departureTimePre = document.createElement('pre')
 | 
					 | 
				
			||||||
                nextDepartureTimeP.appendChild(departureTimePre)
 | 
					 | 
				
			||||||
                var departure = new Date(nextTrain.plannedDeparture)
 | 
					 | 
				
			||||||
                departureTimePre.textContent = departure.toLocaleTimeString([], { 'hour': '2-digit', 'minute': '2-digit' })
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                if (nextTrain.departurePlatform || nextTrain.plannedDeparturePlatform) {
 | 
					 | 
				
			||||||
                    var departurePlatformP = document.createElement('p')
 | 
					 | 
				
			||||||
                    trainDiv.append(departurePlatformP)
 | 
					 | 
				
			||||||
                    departurePlatformP.classList.add('sec', 'next-departure', 'platform')
 | 
					 | 
				
			||||||
                    if (nextTrain.departurePlatform && nextTrain.departurePlatform != nextTrain.plannedDeparturePlatform) {
 | 
					 | 
				
			||||||
                        departurePlatformP.classList.add('changed')
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    departurePlatformP.textContent = `${nextTrain.departurePlatform || nextTrain.plannedDeparturePlatform}`
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function lsk() {
 | 
					function lsk() {
 | 
				
			||||||
    document.getElementById('stationName').focus()
 | 
					    document.getElementById('stationName').focus()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -361,15 +280,15 @@ function csk() {
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (focusedElement.id === 'stationName') {
 | 
					 | 
				
			||||||
        goToTrain(document.activeElement.value.trim())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
    focusedElement.click()
 | 
					    focusedElement.click()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.addEventListener('load', function (e) {
 | 
					window.addEventListener('load', function (e) {
 | 
				
			||||||
 | 
					    if ('geolocation' in navigator) {}
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        nearbyStatus = 'unavailable'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var sp = new URL(window.location.href).searchParams
 | 
					    var sp = new URL(window.location.href).searchParams
 | 
				
			||||||
    fromStation = sp.get('from')
 | 
					    fromStation = sp.get('from')
 | 
				
			||||||
    var fromJson = JSON.parse(fromStation || 'null')
 | 
					    var fromJson = JSON.parse(fromStation || 'null')
 | 
				
			||||||
| 
						 | 
					@ -388,7 +307,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
        titleH1.textContent = 'Find Route - To'
 | 
					        titleH1.textContent = 'Find Route - To'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (!departureDate) {
 | 
					    else if (!departureDate) {
 | 
				
			||||||
        titleH1.textContent = 'Find Route - Departure Date'
 | 
					        titleH1.textContent = 'Find Route - Date'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        // titleH1.textContent = `${fromJson.name || fromJson.address} - ${toJson.name || toJson.address}`
 | 
					        // titleH1.textContent = `${fromJson.name || fromJson.address} - ${toJson.name || toJson.address}`
 | 
				
			||||||
| 
						 | 
					@ -529,7 +448,14 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
            var a = document.getElementById('search-link')
 | 
					            var a = document.getElementById('search-link')
 | 
				
			||||||
            var url = new URL(window.location.href)
 | 
					            var url = new URL(window.location.href)
 | 
				
			||||||
            url.pathname = 'route.html'
 | 
					            url.pathname = 'route.html'
 | 
				
			||||||
 | 
					            if (arrivalInsteadOfDeparture) {
 | 
				
			||||||
 | 
					                url.searchParams.delete('departureDate')
 | 
				
			||||||
 | 
					                url.searchParams.set('arrivalDate', departureDate.toISOString())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                url.searchParams.delete('arrivalDate')
 | 
				
			||||||
                url.searchParams.set('departureDate', departureDate.toISOString())
 | 
					                url.searchParams.set('departureDate', departureDate.toISOString())
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            url.searchParams.set('from', JSON.stringify(fromJson))
 | 
					            url.searchParams.set('from', JSON.stringify(fromJson))
 | 
				
			||||||
            url.searchParams.set('to', JSON.stringify(toJson))
 | 
					            url.searchParams.set('to', JSON.stringify(toJson))
 | 
				
			||||||
            url.searchParams.set('transitKind', JSON.stringify(transitKind))
 | 
					            url.searchParams.set('transitKind', JSON.stringify(transitKind))
 | 
				
			||||||
| 
						 | 
					@ -544,6 +470,17 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
            updateSearchLink()
 | 
					            updateSearchLink()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        function timeKindRadioChanged(event) {
 | 
				
			||||||
 | 
					            var kind = event.target.id.split('-')[2]
 | 
				
			||||||
 | 
					            if (kind === 'arrival') {
 | 
				
			||||||
 | 
					                arrivalInsteadOfDeparture = true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (kind === 'departure') {
 | 
				
			||||||
 | 
					                arrivalInsteadOfDeparture = false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            updateSearchLink()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var contentDiv = div(
 | 
					        var contentDiv = div(
 | 
				
			||||||
            h4('Route'),
 | 
					            h4('Route'),
 | 
				
			||||||
            p('From').class$('thi'),
 | 
					            p('From').class$('thi'),
 | 
				
			||||||
| 
						 | 
					@ -552,6 +489,26 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
            p(toJson.name || toJson.address).class$('pri'),
 | 
					            p(toJson.name || toJson.address).class$('pri'),
 | 
				
			||||||
            // a('', 'Configure via...'),
 | 
					            // a('', 'Configure via...'),
 | 
				
			||||||
            h4('Date and time'),
 | 
					            h4('Date and time'),
 | 
				
			||||||
 | 
					            div(
 | 
				
			||||||
 | 
					                p(label('Departure time').att$('for', 'time-kind-departure')),
 | 
				
			||||||
 | 
					                input('radio')
 | 
				
			||||||
 | 
					                    .checked$(!arrivalInsteadOfDeparture)
 | 
				
			||||||
 | 
					                    .id$('time-kind-departure')
 | 
				
			||||||
 | 
					                    .att$('name', 'time-kind')
 | 
				
			||||||
 | 
					                    .class$('time-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
 | 
					                    .event$('change', timeKindRadioChanged),
 | 
				
			||||||
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
 | 
					            div(
 | 
				
			||||||
 | 
					                p(label('Arrival time').att$('for', 'time-kind-arrival')),
 | 
				
			||||||
 | 
					                input('radio')
 | 
				
			||||||
 | 
					                    .checked$(arrivalInsteadOfDeparture)
 | 
				
			||||||
 | 
					                    .id$('time-kind-arrival')
 | 
				
			||||||
 | 
					                    .att$('name', 'time-kind')
 | 
				
			||||||
 | 
					                    .class$('time-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
 | 
					                    .event$('change', timeKindRadioChanged),
 | 
				
			||||||
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            p('Date').class$('thi'),
 | 
					            p('Date').class$('thi'),
 | 
				
			||||||
            p(departureDate.toDateString()).class$('pri'),
 | 
					            p(departureDate.toDateString()).class$('pri'),
 | 
				
			||||||
            p(label('Time').att$('for', 'time')).class$('thi'),
 | 
					            p(label('Time').att$('for', 'time')).class$('thi'),
 | 
				
			||||||
| 
						 | 
					@ -559,6 +516,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                input('time')
 | 
					                input('time')
 | 
				
			||||||
                    .id$('time')
 | 
					                    .id$('time')
 | 
				
			||||||
                    .att$('value', departureDate.getHours().toString().padStart(2, '0') + ':' + departureDate.getMinutes().toString().padStart(2, '0'))
 | 
					                    .att$('value', departureDate.getHours().toString().padStart(2, '0') + ':' + departureDate.getMinutes().toString().padStart(2, '0'))
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('input', function(event) {
 | 
					                    .event$('input', function(event) {
 | 
				
			||||||
                        var text = event.target.value
 | 
					                        var text = event.target.value
 | 
				
			||||||
                        var splitted = text.toString().split(':')
 | 
					                        var splitted = text.toString().split(':')
 | 
				
			||||||
| 
						 | 
					@ -568,13 +526,14 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                        updateSearchLink()
 | 
					                        updateSearchLink()
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            h4('Train categories'),
 | 
					            h4('Transport categories'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
                p(label('ICE, RJX, High speed').class$('product-nationalExpress').att$('for', 'transit-kind-ice')),
 | 
					                p(label('ICE, RJX, High speed').class$('product-nationalExpress').att$('for', 'transit-kind-ice')),
 | 
				
			||||||
                input('checkbox')
 | 
					                input('checkbox')
 | 
				
			||||||
                    .checked$(transitKind.ice)
 | 
					                    .checked$(transitKind.ice)
 | 
				
			||||||
                    .id$('transit-kind-ice')
 | 
					                    .id$('transit-kind-ice')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -583,6 +542,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.ic)
 | 
					                    .checked$(transitKind.ic)
 | 
				
			||||||
                    .id$('transit-kind-ic')
 | 
					                    .id$('transit-kind-ic')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -591,6 +551,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.re)
 | 
					                    .checked$(transitKind.re)
 | 
				
			||||||
                    .id$('transit-kind-re')
 | 
					                    .id$('transit-kind-re')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -599,6 +560,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.rb)
 | 
					                    .checked$(transitKind.rb)
 | 
				
			||||||
                    .id$('transit-kind-rb')
 | 
					                    .id$('transit-kind-rb')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -607,6 +569,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.s)
 | 
					                    .checked$(transitKind.s)
 | 
				
			||||||
                    .id$('transit-kind-s')
 | 
					                    .id$('transit-kind-s')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -615,6 +578,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.u)
 | 
					                    .checked$(transitKind.u)
 | 
				
			||||||
                    .id$('transit-kind-u')
 | 
					                    .id$('transit-kind-u')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -623,6 +587,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.tram)
 | 
					                    .checked$(transitKind.tram)
 | 
				
			||||||
                    .id$('transit-kind-tram')
 | 
					                    .id$('transit-kind-tram')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -631,6 +596,7 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.bus)
 | 
					                    .checked$(transitKind.bus)
 | 
				
			||||||
                    .id$('transit-kind-bus')
 | 
					                    .id$('transit-kind-bus')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            div(
 | 
					            div(
 | 
				
			||||||
| 
						 | 
					@ -639,10 +605,11 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                    .checked$(transitKind.ferry)
 | 
					                    .checked$(transitKind.ferry)
 | 
				
			||||||
                    .id$('transit-kind-ferry')
 | 
					                    .id$('transit-kind-ferry')
 | 
				
			||||||
                    .class$('transit-kind')
 | 
					                    .class$('transit-kind')
 | 
				
			||||||
 | 
					                    .class$('items')
 | 
				
			||||||
                    .event$('change', transitKindCheckChanged),
 | 
					                    .event$('change', transitKindCheckChanged),
 | 
				
			||||||
            ).class$('checkbox'),
 | 
					            ).class$('checkbox'),
 | 
				
			||||||
            h4('Start search'),
 | 
					            h4('Start search'),
 | 
				
			||||||
            a('', 'Search').id$('search-link'),
 | 
					            a('', 'Search').id$('search-link').class$('items'),
 | 
				
			||||||
        ).class$('content')
 | 
					        ).class$('content')
 | 
				
			||||||
        document.body.insertBefore(contentDiv, footer)
 | 
					        document.body.insertBefore(contentDiv, footer)
 | 
				
			||||||
        contentDiv.style.display = 'flex'
 | 
					        contentDiv.style.display = 'flex'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										277
									
								
								route.js
									
										
									
									
									
								
							
							
						
						
									
										277
									
								
								route.js
									
										
									
									
									
								
							| 
						 | 
					@ -10,6 +10,10 @@ var toStation = null
 | 
				
			||||||
 * @type {Date | null}
 | 
					 * @type {Date | null}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
var departureDate = null
 | 
					var departureDate = null
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @type {Date | null}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					var arrivalDate = null
 | 
				
			||||||
var transitKind = {
 | 
					var transitKind = {
 | 
				
			||||||
    ice: true,
 | 
					    ice: true,
 | 
				
			||||||
    ic: true,
 | 
					    ic: true,
 | 
				
			||||||
| 
						 | 
					@ -22,132 +26,10 @@ var transitKind = {
 | 
				
			||||||
    tram: true,
 | 
					    tram: true,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @type {{id: string, name: string}[]}
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
var knownStations = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var itineraries = null
 | 
					var itineraries = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function goToStation(stationId) {
 | 
					 | 
				
			||||||
    var url = new URL(window.location.href)
 | 
					 | 
				
			||||||
    if (!fromStation) {
 | 
					 | 
				
			||||||
        url.searchParams.set('from', stationId)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (!toStation) {
 | 
					 | 
				
			||||||
        url.searchParams.set('to', stationId)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // url.searchParams.set('date', new Date().toISOString())
 | 
					 | 
				
			||||||
    window.location.href = url.toString()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function setDepartureDate(departureDate) {
 | 
					 | 
				
			||||||
    var url = new URL(window.location.href)
 | 
					 | 
				
			||||||
    url.searchParams.set('departureDate', departureDate.toISOString())
 | 
					 | 
				
			||||||
    window.location.href = url.toString()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function searchNormalize(str) {
 | 
					 | 
				
			||||||
    return str
 | 
					 | 
				
			||||||
        .toLowerCase()
 | 
					 | 
				
			||||||
        .replaceAll('ă', 'a')
 | 
					 | 
				
			||||||
        .replaceAll('â', 'a')
 | 
					 | 
				
			||||||
        .replaceAll('î', 'i')
 | 
					 | 
				
			||||||
        .replaceAll('ș', 's')
 | 
					 | 
				
			||||||
        .replaceAll('ț', 't')
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var focusedElement = null
 | 
					var focusedElement = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _rebuildDebounce = null
 | 
					 | 
				
			||||||
var _rebuildRequested = false
 | 
					 | 
				
			||||||
function rebuildSuggestions() {
 | 
					 | 
				
			||||||
    if (_rebuildDebounce !== null) {
 | 
					 | 
				
			||||||
        _rebuildRequested = true
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _rebuildRequested = false
 | 
					 | 
				
			||||||
    _rebuildDebounce = 123
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var suggestionsArea = document.getElementById('suggestionsArea')
 | 
					 | 
				
			||||||
    while (suggestionsArea.childNodes.length > 0) {
 | 
					 | 
				
			||||||
        suggestionsArea.childNodes[0].remove()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var suggestions = knownStations.slice()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    suggestions.forEach(function (suggestion, index) {
 | 
					 | 
				
			||||||
        var suggestionLi = document.createElement('li')
 | 
					 | 
				
			||||||
        suggestionsArea.appendChild(suggestionLi)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        setTimeout(function () {
 | 
					 | 
				
			||||||
            suggestionLi.classList.add('items')
 | 
					 | 
				
			||||||
            suggestionLi.tabIndex = index + 1
 | 
					 | 
				
			||||||
            suggestionLi.style.padding = '2px 0'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            function onAction(e) {
 | 
					 | 
				
			||||||
                goToStation(JSON.stringify(suggestion))
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            suggestionLi.addEventListener('click', onAction)
 | 
					 | 
				
			||||||
            suggestionLi.addEventListener('keypress', function (e) {
 | 
					 | 
				
			||||||
                if (e.key == 'Enter') {
 | 
					 | 
				
			||||||
                    onAction(e)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            suggestionLi.addEventListener('focus', function (e) {
 | 
					 | 
				
			||||||
                focusedElement = suggestionLi
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var stationNameP = document.createElement('p')
 | 
					 | 
				
			||||||
            suggestionLi.appendChild(stationNameP)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            stationNameP.textContent = suggestion.name || suggestion.address
 | 
					 | 
				
			||||||
            stationNameP.classList.add('pri', 'stationName')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // var trainCompanyP = document.createElement('p')
 | 
					 | 
				
			||||||
            // suggestionLi.appendChild(trainCompanyP)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // trainCompanyP.textContent = suggestion.company
 | 
					 | 
				
			||||||
            // trainCompanyP.classList.add('thi')
 | 
					 | 
				
			||||||
        }, 0)
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setTimeout(function () {
 | 
					 | 
				
			||||||
        _rebuildDebounce = null
 | 
					 | 
				
			||||||
        if (_rebuildRequested) {
 | 
					 | 
				
			||||||
            rebuildSuggestions()
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }, 500)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var fetchAbortController = new AbortController()
 | 
					 | 
				
			||||||
function reloadSuggestions() {
 | 
					 | 
				
			||||||
	var stationNameInput = document.getElementById('stationName')
 | 
					 | 
				
			||||||
	var stationName = searchNormalize(stationNameInput.value.trim())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var locationsUrl = new URL('https://v6.db.transport.rest/locations')
 | 
					 | 
				
			||||||
	locationsUrl.searchParams.set('query', stationName)
 | 
					 | 
				
			||||||
	locationsUrl.searchParams.set('limit', '25')
 | 
					 | 
				
			||||||
	locationsUrl.searchParams.set('fuzzy', 'true')
 | 
					 | 
				
			||||||
	locationsUrl.searchParams.set('stops', 'true')
 | 
					 | 
				
			||||||
	locationsUrl.searchParams.set('addresses', 'true')
 | 
					 | 
				
			||||||
	locationsUrl.searchParams.set('poi', 'true')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fetchAbortController.abort()
 | 
					 | 
				
			||||||
	fetchAbortController = new AbortController()
 | 
					 | 
				
			||||||
	fetch(locationsUrl.toString(), { signal: fetchAbortController.signal })
 | 
					 | 
				
			||||||
		.then(function (response) {
 | 
					 | 
				
			||||||
			return response.json()
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
		.then(function (data) {
 | 
					 | 
				
			||||||
			if (data) {
 | 
					 | 
				
			||||||
				knownStations = Object.values(data)
 | 
					 | 
				
			||||||
				rebuildSuggestions()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @typedef DbJourney
 | 
					 * @typedef DbJourney
 | 
				
			||||||
 * @prop {'journey'} type
 | 
					 * @prop {'journey'} type
 | 
				
			||||||
| 
						 | 
					@ -339,7 +221,7 @@ function onItineraries(data) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function lsk() {
 | 
					function lsk() {
 | 
				
			||||||
    document.getElementById('stationName').focus()
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function csk() {
 | 
					function csk() {
 | 
				
			||||||
| 
						 | 
					@ -347,13 +229,8 @@ function csk() {
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (focusedElement.id === 'stationName') {
 | 
					 | 
				
			||||||
        goToTrain(document.activeElement.value.trim())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
    focusedElement.click()
 | 
					    focusedElement.click()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.addEventListener('load', function (e) {
 | 
					window.addEventListener('load', function (e) {
 | 
				
			||||||
    var sp = new URL(window.location.href).searchParams
 | 
					    var sp = new URL(window.location.href).searchParams
 | 
				
			||||||
| 
						 | 
					@ -365,16 +242,14 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
    if (departureDateStr) {
 | 
					    if (departureDateStr) {
 | 
				
			||||||
        departureDate = new Date(departureDateStr)
 | 
					        departureDate = new Date(departureDateStr)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    var arrivalDateStr = sp.get('arrivalDate')
 | 
				
			||||||
 | 
					    if (arrivalDateStr) {
 | 
				
			||||||
 | 
					        arrivalDate = new Date(arrivalDateStr)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var titleH1 = document.querySelector("header > h1")
 | 
					    var titleH1 = document.querySelector("header > h1")
 | 
				
			||||||
    if (!fromStation) {
 | 
					    if (!fromJson || !toJson) {
 | 
				
			||||||
        titleH1.textContent = 'Find Route - From'
 | 
					        titleH1.textContent = 'Find Route'
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (!toStation) {
 | 
					 | 
				
			||||||
        titleH1.textContent = 'Find Route - To'
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (!departureDate) {
 | 
					 | 
				
			||||||
        titleH1.textContent = 'Find Route - Departure Date'
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        titleH1.textContent = `${fromJson.name || fromJson.address} - ${toJson.name || toJson.address}`
 | 
					        titleH1.textContent = `${fromJson.name || fromJson.address} - ${toJson.name || toJson.address}`
 | 
				
			||||||
| 
						 | 
					@ -387,113 +262,11 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var footer = document.querySelector('footer')
 | 
					    var footer = document.querySelector('footer')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!fromStation || !toStation) {
 | 
					    if (!fromStation || !toStation || (!departureDate && !arrivalDate)) {
 | 
				
			||||||
        // Build station selection UI
 | 
					        // Send to config page
 | 
				
			||||||
        document.body.insertBefore(
 | 
					        var url = new URL(window.location.href)
 | 
				
			||||||
            h4(
 | 
					        url.pathname = '/config-route.html'
 | 
				
			||||||
                label('Station Name').att$('for', 'stationName'),
 | 
					        window.location.href = url.toString()
 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            footer,
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        // var stationNameH4 = document.createElement('h4')
 | 
					 | 
				
			||||||
        // document.body.insertBefore(stationNameH4, footer)
 | 
					 | 
				
			||||||
        // var stationNameLabel = document.createElement('label')
 | 
					 | 
				
			||||||
        // stationNameH4.appendChild(stationNameLabel)
 | 
					 | 
				
			||||||
        // stationNameLabel.htmlFor = 'stationName'
 | 
					 | 
				
			||||||
        // stationNameLabel.textContent = 'Station Name'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        document.body.insertBefore(
 | 
					 | 
				
			||||||
            input('search').id$('stationName').att$('name', 'stationName').class$('items'),
 | 
					 | 
				
			||||||
            footer,
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        // var stationNameInput = document.createElement('input')
 | 
					 | 
				
			||||||
        // document.body.insertBefore(stationNameInput, footer)
 | 
					 | 
				
			||||||
        // stationNameInput.type = 'search'
 | 
					 | 
				
			||||||
        // stationNameInput.classList.add('items')
 | 
					 | 
				
			||||||
        // stationNameInput.name = 'stationName'
 | 
					 | 
				
			||||||
        // stationNameInput.id = 'stationName'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        document.body.insertBefore(h4('Suggestions'), footer)
 | 
					 | 
				
			||||||
        // var suggestionsH4 = document.createElement('h4')
 | 
					 | 
				
			||||||
        // document.body.insertBefore(suggestionsH4, footer)
 | 
					 | 
				
			||||||
        // suggestionsH4.textContent = 'Suggestions'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var contentDiv = document.createElement('div')
 | 
					 | 
				
			||||||
        document.body.insertBefore(contentDiv, footer)
 | 
					 | 
				
			||||||
        contentDiv.classList.add('content')
 | 
					 | 
				
			||||||
        var suggestionsUl = document.createElement('ul')
 | 
					 | 
				
			||||||
        contentDiv.appendChild(suggestionsUl)
 | 
					 | 
				
			||||||
        suggestionsUl.id = 'suggestionsArea'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        document.querySelector('.csk').textContent = 'Search'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var stationName = document.getElementById('stationName')
 | 
					 | 
				
			||||||
        stationName.addEventListener('input', function (e) {
 | 
					 | 
				
			||||||
            reloadSuggestions()
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        stationName.addEventListener('focus', function (e) {
 | 
					 | 
				
			||||||
            focusedElement = stationName
 | 
					 | 
				
			||||||
            document.getElementsByClassName('lsk')[0].textContent = ''
 | 
					 | 
				
			||||||
            document.getElementsByClassName('csk')[0].textContent = 'Search'
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        stationName.addEventListener('blur', function (e) {
 | 
					 | 
				
			||||||
            document.getElementsByClassName('lsk')[0].textContent = 'Search'
 | 
					 | 
				
			||||||
            document.getElementsByClassName('csk')[0].textContent = 'Select'
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        stationName.addEventListener('keypress', function (e) {
 | 
					 | 
				
			||||||
            if (e.key == 'Enter') {
 | 
					 | 
				
			||||||
                goToStation(stationName.value.trim())
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (!departureDate) {
 | 
					 | 
				
			||||||
        var departureDateH4 = document.createElement('h4')
 | 
					 | 
				
			||||||
        document.body.insertBefore(departureDateH4, footer)
 | 
					 | 
				
			||||||
        departureDateH4.textContent = 'Departure Date'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var contentDiv = document.createElement('div')
 | 
					 | 
				
			||||||
        document.body.insertBefore(contentDiv, footer)
 | 
					 | 
				
			||||||
        contentDiv.classList.add('content')
 | 
					 | 
				
			||||||
        var departureDateUl = document.createElement('ul')
 | 
					 | 
				
			||||||
        contentDiv.appendChild(departureDateUl)
 | 
					 | 
				
			||||||
        departureDateUl.id = 'suggestionsArea'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (var i = -1, departureOption = (function () { var d = new Date(); d.setDate(d.getDate() - 1); return d })(); i < 30; i++, departureOption.setDate(departureOption.getDate() + 1)) {
 | 
					 | 
				
			||||||
            var suggestionLi = document.createElement('li')
 | 
					 | 
				
			||||||
            departureDateUl.appendChild(suggestionLi)
 | 
					 | 
				
			||||||
            suggestionLi.classList.add('items')
 | 
					 | 
				
			||||||
            suggestionLi.tabIndex = i + 10
 | 
					 | 
				
			||||||
            // Capture
 | 
					 | 
				
			||||||
            ;(function () {
 | 
					 | 
				
			||||||
                var d = new Date(departureOption.getTime())
 | 
					 | 
				
			||||||
                function onAction() {
 | 
					 | 
				
			||||||
                    setDepartureDate(d)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                suggestionLi.addEventListener('click', onAction)
 | 
					 | 
				
			||||||
                suggestionLi.addEventListener('keypress', function (e) {
 | 
					 | 
				
			||||||
                    if (e.key == 'Enter') {
 | 
					 | 
				
			||||||
                        onAction(e)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                suggestionLi.addEventListener('focus', function (e) {
 | 
					 | 
				
			||||||
                    focusedElement = suggestionLi
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                if (i === 0) {
 | 
					 | 
				
			||||||
                    suggestionLi.focus()
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })()
 | 
					 | 
				
			||||||
            var innerP = document.createElement('p')
 | 
					 | 
				
			||||||
            suggestionLi.appendChild(innerP)
 | 
					 | 
				
			||||||
            innerP.classList.add('pri')
 | 
					 | 
				
			||||||
            var innerPre = document.createElement('pre')
 | 
					 | 
				
			||||||
            innerP.appendChild(innerPre)
 | 
					 | 
				
			||||||
            innerPre.textContent = `${departureOption.getDate().toString().padStart(2, '0')}.${(departureOption.getMonth() + 1).toString().padStart(2, '0')}.${departureOption.getFullYear().toString().padStart(4, '0')}`
 | 
					 | 
				
			||||||
            if (i === 0) {
 | 
					 | 
				
			||||||
                innerPre.textContent += ' (today)'
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        document.querySelector('.csk').textContent = 'Select'
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        var contentDiv = document.createElement('div')
 | 
					        var contentDiv = document.createElement('div')
 | 
				
			||||||
| 
						 | 
					@ -532,7 +305,12 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                url.searchParams.set(`to.${key}`, toJson[key])
 | 
					                url.searchParams.set(`to.${key}`, toJson[key])
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (departureDate) {
 | 
				
			||||||
            url.searchParams.set('departure', departureDate.toISOString())
 | 
					            url.searchParams.set('departure', departureDate.toISOString())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (arrivalDate) {
 | 
				
			||||||
 | 
					            url.searchParams.set('arrival', arrivalDate.toISOString())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        url.searchParams.set('results', '20')
 | 
					        url.searchParams.set('results', '20')
 | 
				
			||||||
        url.searchParams.set('stopovers', 'true')
 | 
					        url.searchParams.set('stopovers', 'true')
 | 
				
			||||||
        url.searchParams.set('nationalExpress', transitKind.ice)
 | 
					        url.searchParams.set('nationalExpress', transitKind.ice)
 | 
				
			||||||
| 
						 | 
					@ -562,10 +340,11 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                contentDiv.remove()
 | 
					                contentDiv.remove()
 | 
				
			||||||
                onItineraries(data)
 | 
					                onItineraries(data)
 | 
				
			||||||
                itineraries = data
 | 
					                itineraries = data
 | 
				
			||||||
                function fetchMore() {
 | 
					                function fetchMore(timeoutMs) {
 | 
				
			||||||
                    console.debug(`Got ${itineraries.journeys.length} journeys, fetching more`)
 | 
					                    console.debug(`Got ${itineraries.journeys.length} journeys, fetching more`)
 | 
				
			||||||
                    var moreUrl = new URL(url.toString())
 | 
					                    var moreUrl = new URL(url.toString())
 | 
				
			||||||
                    moreUrl.searchParams.delete('departure')
 | 
					                    moreUrl.searchParams.delete('departure')
 | 
				
			||||||
 | 
					                    moreUrl.searchParams.delete('arrival')
 | 
				
			||||||
                    moreUrl.searchParams.set('laterThan', itineraries.laterRef)
 | 
					                    moreUrl.searchParams.set('laterThan', itineraries.laterRef)
 | 
				
			||||||
                    fetch(moreUrl.toString())
 | 
					                    fetch(moreUrl.toString())
 | 
				
			||||||
                        .then(function (result) {
 | 
					                        .then(function (result) {
 | 
				
			||||||
| 
						 | 
					@ -582,13 +361,21 @@ window.addEventListener('load', function (e) {
 | 
				
			||||||
                                    var lastLeg = lastJourney.legs[lastJourney.legs.length - 1]
 | 
					                                    var lastLeg = lastJourney.legs[lastJourney.legs.length - 1]
 | 
				
			||||||
                                    var departureDate = new Date(lastLeg.plannedDeparture)
 | 
					                                    var departureDate = new Date(lastLeg.plannedDeparture)
 | 
				
			||||||
                                    if (departureDate.getTime() - Date.now() < 86400000) {
 | 
					                                    if (departureDate.getTime() - Date.now() < 86400000) {
 | 
				
			||||||
                                        setTimeout(fetchMore, 500)
 | 
					                                        setTimeout(
 | 
				
			||||||
 | 
					                                            function () {
 | 
				
			||||||
 | 
					                                                fetchMore((timeoutMs || 500) * 1.5)
 | 
				
			||||||
 | 
					                                            },
 | 
				
			||||||
 | 
					                                            timeoutMs || 500,
 | 
				
			||||||
 | 
					                                        )
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (departureDate) {
 | 
				
			||||||
                    fetchMore()
 | 
					                    fetchMore()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .catch(function (e) {
 | 
					            .catch(function (e) {
 | 
				
			||||||
                loadingP.textContent = 'An error has occured'
 | 
					                loadingP.textContent = 'An error has occured'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								sw.js
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								sw.js
									
										
									
									
									
								
							| 
						 | 
					@ -1,8 +1,4 @@
 | 
				
			||||||
const VERSION = 'v15'
 | 
					const VERSION = 'v16'
 | 
				
			||||||
const API_ORIGIN = 'https://scraper.infotren.dcdev.ro/'
 | 
					 | 
				
			||||||
const API_TRAINS = `${API_ORIGIN}v3/trains`
 | 
					 | 
				
			||||||
const API_STATIONS = `${API_ORIGIN}v3/stations`
 | 
					 | 
				
			||||||
const API_ITINERARIES = `${API_ORIGIN}v3/itineraries`
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const CACHE_FIRST = [
 | 
					const CACHE_FIRST = [
 | 
				
			||||||
	// Root
 | 
						// Root
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue