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%;
|
||||
}
|
||||
|
||||
.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 {
|
||||
color: green !important;
|
||||
}
|
||||
|
|
|
@ -115,34 +115,3 @@ div.checkbox p {
|
|||
div.checkbox input {
|
||||
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 defer src="/common/back.js"></script>
|
||||
<script defer src="/common/items.js"></script>
|
||||
<script defer src="/common/components.js"></script>
|
||||
<script defer src="station.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
191
station.js
191
station.js
|
@ -1,5 +1,12 @@
|
|||
var starred = []
|
||||
var knownStations = []
|
||||
|
||||
/**
|
||||
* @type {'unavailable' | 'notRequested' | 'waiting' | 'gotData'}
|
||||
*/
|
||||
var nearbyStatus = 'notRequested'
|
||||
var nearbyStations = []
|
||||
|
||||
function goToStation(stationId) {
|
||||
var url = new URL(window.location.href)
|
||||
url.pathname = 'view-station.html'
|
||||
|
@ -22,6 +29,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
|
||||
|
@ -37,42 +132,66 @@ function rebuildSuggestions() {
|
|||
}
|
||||
|
||||
var suggestions = knownStations.slice()
|
||||
if (suggestions.length === 0) {
|
||||
suggestions = starred.map(function (s) { return JSON.parse(s) })
|
||||
}
|
||||
|
||||
suggestions.forEach(function (suggestion, index) {
|
||||
var suggestionLi = document.createElement('li')
|
||||
suggestionsArea.appendChild(suggestionLi)
|
||||
suggestionsArea.append(createSuggestion(suggestion, index))
|
||||
})
|
||||
|
||||
setTimeout(function () {
|
||||
suggestionLi.classList.add('items')
|
||||
suggestionLi.tabIndex = index + 1
|
||||
suggestionLi.style.padding = '2px 0'
|
||||
|
||||
function onAction(e) {
|
||||
goToStation(suggestion.id)
|
||||
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()
|
||||
}
|
||||
suggestionLi.addEventListener('click', onAction)
|
||||
suggestionLi.addEventListener('keypress', function (e) {
|
||||
if (e.key == 'Enter') {
|
||||
onAction(e)
|
||||
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))
|
||||
})
|
||||
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 () {
|
||||
_rebuildDebounce = null
|
||||
|
@ -97,7 +216,12 @@ function reloadSuggestions() {
|
|||
fetchAbortController = new AbortController()
|
||||
fetch(locationsUrl.toString(), { signal: fetchAbortController.signal })
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
else {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
.then(function (data) {
|
||||
if (data) {
|
||||
|
@ -125,6 +249,13 @@ function csk() {
|
|||
}
|
||||
|
||||
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')
|
||||
stationName.addEventListener('input', function (e) {
|
||||
reloadSuggestions()
|
||||
|
|
Loading…
Add table
Reference in a new issue