diff --git a/config-route.js b/config-route.js index 1fcfca8..72189d9 100644 --- a/config-route.js +++ b/config-route.js @@ -10,6 +10,7 @@ var toStation = null * @type {Date | null} */ var departureDate = null +var arrivalInsteadOfDeparture = false var transitKind = { ice: true, ic: true, @@ -28,7 +29,11 @@ var starred = [] */ var knownStations = [] -var itineraries = null +/** + * @type {'unavailable' | 'notRequested' | 'waiting' | 'gotData'} + */ +var nearbyStatus = 'notRequested' +var nearbyStations = [] function goToStation(stationId) { var url = new URL(window.location.href) @@ -62,6 +67,94 @@ var focusedElement = null var _rebuildDebounce = null var _rebuildRequested = false +function createSuggestion(suggestion, index) { + delete suggestion['products'] + var suggestionDiv = document.createElement('div') + suggestionDiv.classList.add('suggestion') + + var suggestionLi = document.createElement('li') + suggestionDiv.appendChild(suggestionLi) + + suggestionLi.classList.add('items') + if (index) { + 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) + + var stationNameSpan = document.createElement('span') + 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) { + var suggestionDistance = suggestion['distance'] + delete suggestion['distance'] + var suggestionLink = document.createElement('a') + suggestionLink.classList.add('no-custom-a') + + var suggestionStar = document.createElement('object') + suggestionLink.appendChild(suggestionStar) + suggestionStar.classList.add('star') + suggestionStar.type = 'image/svg+xml' + function setStar() { + if (starred.includes(JSON.stringify(suggestion))) { + suggestionStar.data = '/icons/star_full.svg' + suggestionStar.classList.add('checked') + } + else { + suggestionStar.data = '/icons/star_empty.svg' + suggestionStar.classList.remove('checked') + } + } + suggestionLink.addEventListener('click', function (event) { + event.preventDefault() + if (starred.includes(JSON.stringify(suggestion))) { + starred = starred.filter(function (s) { + return s !== suggestion + }) + } else { + starred.push(JSON.stringify(suggestion)) + } + setStar() + localStorage.setItem('stations/starred', JSON.stringify(starred)) + }) + setStar() + suggestionDiv.appendChild(suggestionLink) + suggestion['distance'] = suggestionDistance + } + + // var trainCompanyP = document.createElement('p') + // suggestionLi.appendChild(trainCompanyP) + + // trainCompanyP.textContent = suggestion.company + // trainCompanyP.classList.add('thi') + return suggestionDiv +} function rebuildSuggestions() { if (_rebuildDebounce !== null) { _rebuildRequested = true @@ -82,76 +175,61 @@ function rebuildSuggestions() { } suggestions.forEach(function (suggestion, index) { - var suggestionDiv = document.createElement('div') - suggestionDiv.classList.add('suggestion') - - var suggestionLi = document.createElement('li') - suggestionDiv.appendChild(suggestionLi) - - 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 - }) + suggestionsArea.appendChild(createSuggestion(suggestion, index)) + }) - var stationNameP = document.createElement('p') - suggestionLi.appendChild(stationNameP) - - stationNameP.textContent = suggestion.name || suggestion.address - stationNameP.classList.add('pri', 'stationName') - - if (window.localStorage) { - var suggestionLink = document.createElement('a') - suggestionDiv.appendChild(suggestionLink) - suggestionLink.classList.add('no-custom-a') - - var suggestionStar = document.createElement('object') - suggestionLink.appendChild(suggestionStar) - suggestionStar.classList.add('star') - suggestionStar.type = 'image/svg+xml' - function setStar() { - if (starred.includes(JSON.stringify(suggestion))) { - suggestionStar.data = '/icons/star_full.svg' - suggestionStar.classList.add('checked') - } - else { - suggestionStar.data = '/icons/star_empty.svg' - suggestionStar.classList.remove('checked') - } - } - suggestionLink.addEventListener('click', function (event) { + if (nearbyStatus !== 'unavailable') { + suggestionsArea.appendChild(h4('Nearby stations')) + if (nearbyStatus === 'notRequested') { + suggestionsArea.appendChild(a('', 'Load nearby stations').event$('click', function (event) { event.preventDefault() - if (starred.includes(JSON.stringify(suggestion))) { - starred = starred.filter(function (s) { - return s !== suggestion - }) - } else { - starred.push(JSON.stringify(suggestion)) - } - setStar() - localStorage.setItem('stations/starred', JSON.stringify(starred)) + 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)) }) - setStar() } - - // var trainCompanyP = document.createElement('p') - // suggestionLi.appendChild(trainCompanyP) - - // trainCompanyP.textContent = suggestion.company - // trainCompanyP.classList.add('thi') - suggestionsArea.appendChild(suggestionDiv) - }) + } setTimeout(function () { _rebuildDebounce = null @@ -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() { document.getElementById('stationName').focus() } @@ -361,15 +280,15 @@ function csk() { return } - if (focusedElement.id === 'stationName') { - goToTrain(document.activeElement.value.trim()) - } - else { - focusedElement.click() - } + focusedElement.click() } window.addEventListener('load', function (e) { + if ('geolocation' in navigator) {} + else { + nearbyStatus = 'unavailable' + } + var sp = new URL(window.location.href).searchParams fromStation = sp.get('from') var fromJson = JSON.parse(fromStation || 'null') @@ -388,7 +307,7 @@ window.addEventListener('load', function (e) { titleH1.textContent = 'Find Route - To' } else if (!departureDate) { - titleH1.textContent = 'Find Route - Departure Date' + titleH1.textContent = 'Find Route - Date' } else { // 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 url = new URL(window.location.href) url.pathname = 'route.html' - url.searchParams.set('departureDate', departureDate.toISOString()) + 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('from', JSON.stringify(fromJson)) url.searchParams.set('to', JSON.stringify(toJson)) url.searchParams.set('transitKind', JSON.stringify(transitKind)) @@ -544,6 +470,17 @@ window.addEventListener('load', function (e) { 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( h4('Route'), p('From').class$('thi'), @@ -552,6 +489,26 @@ window.addEventListener('load', function (e) { p(toJson.name || toJson.address).class$('pri'), // a('', 'Configure via...'), 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(departureDate.toDateString()).class$('pri'), p(label('Time').att$('for', 'time')).class$('thi'), @@ -559,6 +516,7 @@ window.addEventListener('load', function (e) { input('time') .id$('time') .att$('value', departureDate.getHours().toString().padStart(2, '0') + ':' + departureDate.getMinutes().toString().padStart(2, '0')) + .class$('items') .event$('input', function(event) { var text = event.target.value var splitted = text.toString().split(':') @@ -568,13 +526,14 @@ window.addEventListener('load', function (e) { updateSearchLink() }), ), - h4('Train categories'), + h4('Transport categories'), div( p(label('ICE, RJX, High speed').class$('product-nationalExpress').att$('for', 'transit-kind-ice')), input('checkbox') .checked$(transitKind.ice) .id$('transit-kind-ice') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -583,6 +542,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.ic) .id$('transit-kind-ic') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -591,6 +551,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.re) .id$('transit-kind-re') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -599,6 +560,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.rb) .id$('transit-kind-rb') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -607,6 +569,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.s) .id$('transit-kind-s') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -615,6 +578,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.u) .id$('transit-kind-u') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -623,6 +587,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.tram) .id$('transit-kind-tram') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -631,6 +596,7 @@ window.addEventListener('load', function (e) { .checked$(transitKind.bus) .id$('transit-kind-bus') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), div( @@ -639,10 +605,11 @@ window.addEventListener('load', function (e) { .checked$(transitKind.ferry) .id$('transit-kind-ferry') .class$('transit-kind') + .class$('items') .event$('change', transitKindCheckChanged), ).class$('checkbox'), h4('Start search'), - a('', 'Search').id$('search-link'), + a('', 'Search').id$('search-link').class$('items'), ).class$('content') document.body.insertBefore(contentDiv, footer) contentDiv.style.display = 'flex' diff --git a/route.js b/route.js index af695fb..44af4a9 100644 --- a/route.js +++ b/route.js @@ -10,6 +10,10 @@ var toStation = null * @type {Date | null} */ var departureDate = null +/** + * @type {Date | null} + */ +var arrivalDate = null var transitKind = { ice: true, ic: true, @@ -22,132 +26,10 @@ var transitKind = { tram: true, } -/** - * @type {{id: string, name: string}[]} - */ -var knownStations = [] - 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 _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 * @prop {'journey'} type @@ -339,7 +221,7 @@ function onItineraries(data) { } function lsk() { - document.getElementById('stationName').focus() + } function csk() { @@ -347,12 +229,7 @@ function csk() { return } - if (focusedElement.id === 'stationName') { - goToTrain(document.activeElement.value.trim()) - } - else { - focusedElement.click() - } + focusedElement.click() } window.addEventListener('load', function (e) { @@ -365,16 +242,14 @@ window.addEventListener('load', function (e) { if (departureDateStr) { departureDate = new Date(departureDateStr) } + var arrivalDateStr = sp.get('arrivalDate') + if (arrivalDateStr) { + arrivalDate = new Date(arrivalDateStr) + } var titleH1 = document.querySelector("header > h1") - if (!fromStation) { - titleH1.textContent = 'Find Route - From' - } - else if (!toStation) { - titleH1.textContent = 'Find Route - To' - } - else if (!departureDate) { - titleH1.textContent = 'Find Route - Departure Date' + if (!fromJson || !toJson) { + titleH1.textContent = 'Find Route' } else { titleH1.textContent = `${fromJson.name || fromJson.address} - ${toJson.name || toJson.address}` @@ -387,113 +262,11 @@ window.addEventListener('load', function (e) { var footer = document.querySelector('footer') - if (!fromStation || !toStation) { - // Build station selection UI - document.body.insertBefore( - h4( - label('Station Name').att$('for', 'stationName'), - ), - 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' + if (!fromStation || !toStation || (!departureDate && !arrivalDate)) { + // Send to config page + var url = new URL(window.location.href) + url.pathname = '/config-route.html' + window.location.href = url.toString() } else { var contentDiv = document.createElement('div') @@ -532,7 +305,12 @@ window.addEventListener('load', function (e) { url.searchParams.set(`to.${key}`, toJson[key]) }) } - url.searchParams.set('departure', departureDate.toISOString()) + if (departureDate) { + url.searchParams.set('departure', departureDate.toISOString()) + } + if (arrivalDate) { + url.searchParams.set('arrival', arrivalDate.toISOString()) + } url.searchParams.set('results', '20') url.searchParams.set('stopovers', 'true') url.searchParams.set('nationalExpress', transitKind.ice) @@ -562,10 +340,11 @@ window.addEventListener('load', function (e) { contentDiv.remove() onItineraries(data) itineraries = data - function fetchMore() { + function fetchMore(timeoutMs) { console.debug(`Got ${itineraries.journeys.length} journeys, fetching more`) var moreUrl = new URL(url.toString()) moreUrl.searchParams.delete('departure') + moreUrl.searchParams.delete('arrival') moreUrl.searchParams.set('laterThan', itineraries.laterRef) fetch(moreUrl.toString()) .then(function (result) { @@ -582,13 +361,21 @@ window.addEventListener('load', function (e) { var lastLeg = lastJourney.legs[lastJourney.legs.length - 1] var departureDate = new Date(lastLeg.plannedDeparture) if (departureDate.getTime() - Date.now() < 86400000) { - setTimeout(fetchMore, 500) + setTimeout( + function () { + fetchMore((timeoutMs || 500) * 1.5) + }, + timeoutMs || 500, + ) } } } }) } - fetchMore() + + if (departureDate) { + fetchMore() + } }) .catch(function (e) { loadingP.textContent = 'An error has occured' diff --git a/sw.js b/sw.js index 6920347..998e37d 100755 --- a/sw.js +++ b/sw.js @@ -1,8 +1,4 @@ -const VERSION = 'v15' -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 VERSION = 'v16' const CACHE_FIRST = [ // Root