Add favorites + nearby stations to stations.html
This commit is contained in:
parent
e0ad2fa46c
commit
42352a740f
4 changed files with 197 additions and 65 deletions
31
base.css
31
base.css
|
@ -351,6 +351,37 @@ pre {
|
||||||
border-bottom-right-radius: 5%;
|
border-bottom-right-radius: 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.suggestion {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion :first-child {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion .star {
|
||||||
|
flex: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion .star.checked {
|
||||||
|
filter: invert(90%) sepia(49%) saturate(704%) hue-rotate(359deg) brightness(94%) contrast(99%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.suggestion .star {
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestion .star.checked {
|
||||||
|
filter: invert(86%) sepia(79%) saturate(2126%) hue-rotate(357deg) brightness(108%) contrast(104%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.product-suburban {
|
.product-suburban {
|
||||||
color: green !important;
|
color: green !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,34 +115,3 @@ div.checkbox p {
|
||||||
div.checkbox input {
|
div.checkbox input {
|
||||||
flex: 0;
|
flex: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.suggestion {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suggestion :first-child {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suggestion .star {
|
|
||||||
flex: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.suggestion .star.checked {
|
|
||||||
filter: invert(90%) sepia(49%) saturate(704%) hue-rotate(359deg) brightness(94%) contrast(99%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.suggestion .star {
|
|
||||||
filter: invert(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.suggestion .star.checked {
|
|
||||||
filter: invert(86%) sepia(79%) saturate(2126%) hue-rotate(357deg) brightness(108%) contrast(104%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
<script src="/common/worker.js"></script>
|
<script src="/common/worker.js"></script>
|
||||||
<script defer src="/common/back.js"></script>
|
<script defer src="/common/back.js"></script>
|
||||||
<script defer src="/common/items.js"></script>
|
<script defer src="/common/items.js"></script>
|
||||||
|
<script defer src="/common/components.js"></script>
|
||||||
<script defer src="station.js"></script>
|
<script defer src="station.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
191
station.js
191
station.js
|
@ -1,5 +1,12 @@
|
||||||
|
var starred = []
|
||||||
var knownStations = []
|
var knownStations = []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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)
|
||||||
url.pathname = 'view-station.html'
|
url.pathname = 'view-station.html'
|
||||||
|
@ -22,6 +29,94 @@ var focusedElement = null
|
||||||
|
|
||||||
var _rebuildDebounce = null
|
var _rebuildDebounce = null
|
||||||
var _rebuildRequested = false
|
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() {
|
function rebuildSuggestions() {
|
||||||
if (_rebuildDebounce !== null) {
|
if (_rebuildDebounce !== null) {
|
||||||
_rebuildRequested = true
|
_rebuildRequested = true
|
||||||
|
@ -37,42 +132,66 @@ function rebuildSuggestions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var suggestions = knownStations.slice()
|
var suggestions = knownStations.slice()
|
||||||
|
if (suggestions.length === 0) {
|
||||||
|
suggestions = starred.map(function (s) { return JSON.parse(s) })
|
||||||
|
}
|
||||||
|
|
||||||
suggestions.forEach(function (suggestion, index) {
|
suggestions.forEach(function (suggestion, index) {
|
||||||
var suggestionLi = document.createElement('li')
|
suggestionsArea.append(createSuggestion(suggestion, index))
|
||||||
suggestionsArea.appendChild(suggestionLi)
|
})
|
||||||
|
|
||||||
setTimeout(function () {
|
if (nearbyStatus !== 'unavailable') {
|
||||||
suggestionLi.classList.add('items')
|
suggestionsArea.appendChild(h4('Nearby stations'))
|
||||||
suggestionLi.tabIndex = index + 1
|
if (nearbyStatus === 'notRequested') {
|
||||||
suggestionLi.style.padding = '2px 0'
|
suggestionsArea.appendChild(a('', 'Load nearby stations').event$('click', function (event) {
|
||||||
|
event.preventDefault()
|
||||||
function onAction(e) {
|
var watchId = navigator.geolocation.watchPosition(
|
||||||
goToStation(suggestion.id)
|
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()
|
||||||
}
|
}
|
||||||
suggestionLi.addEventListener('click', onAction)
|
navigator.geolocation.clearWatch(watchId)
|
||||||
suggestionLi.addEventListener('keypress', function (e) {
|
},
|
||||||
if (e.key == 'Enter') {
|
{
|
||||||
onAction(e)
|
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))
|
||||||
})
|
})
|
||||||
suggestionLi.addEventListener('focus', function (e) {
|
}
|
||||||
focusedElement = suggestionLi
|
}
|
||||||
})
|
|
||||||
|
|
||||||
var stationNameP = document.createElement('p')
|
|
||||||
suggestionLi.appendChild(stationNameP)
|
|
||||||
|
|
||||||
stationNameP.textContent = suggestion.name
|
|
||||||
stationNameP.classList.add('pri', 'stationName')
|
|
||||||
|
|
||||||
// var trainCompanyP = document.createElement('p')
|
|
||||||
// suggestionLi.appendChild(trainCompanyP)
|
|
||||||
|
|
||||||
// trainCompanyP.textContent = suggestion.company
|
|
||||||
// trainCompanyP.classList.add('thi')
|
|
||||||
}, 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
_rebuildDebounce = null
|
_rebuildDebounce = null
|
||||||
|
@ -97,7 +216,12 @@ function reloadSuggestions() {
|
||||||
fetchAbortController = new AbortController()
|
fetchAbortController = new AbortController()
|
||||||
fetch(locationsUrl.toString(), { signal: fetchAbortController.signal })
|
fetch(locationsUrl.toString(), { signal: fetchAbortController.signal })
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
|
if (response.ok) {
|
||||||
return response.json()
|
return response.json()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -125,6 +249,13 @@ function csk() {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', function (e) {
|
window.addEventListener('load', function (e) {
|
||||||
|
if (window.localStorage) {
|
||||||
|
var maybeStarred = JSON.parse(localStorage.getItem('stations/starred'))
|
||||||
|
if (maybeStarred) {
|
||||||
|
starred = maybeStarred
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var stationName = document.getElementById('stationName')
|
var stationName = document.getElementById('stationName')
|
||||||
stationName.addEventListener('input', function (e) {
|
stationName.addEventListener('input', function (e) {
|
||||||
reloadSuggestions()
|
reloadSuggestions()
|
||||||
|
|
Loading…
Add table
Reference in a new issue