Init project
This commit is contained in:
28
web/api.js
Normal file
28
web/api.js
Normal file
@@ -0,0 +1,28 @@
|
||||
export function fetchApi(pathcomponents, query) {
|
||||
query.pretty = true;
|
||||
let url = '/api/' + pathcomponents.join("/") + "?" + new URLSearchParams(query).toString();
|
||||
return fetch(url).then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Fetching api failed");
|
||||
}
|
||||
return response;
|
||||
}).then(response => response.json());
|
||||
}
|
||||
|
||||
export function fetchLocations(query) {
|
||||
return fetchApi(["locations"], {
|
||||
query: query,
|
||||
addresses: false,
|
||||
poi: false,
|
||||
subStop: false,
|
||||
entrances: false,
|
||||
linesOfStops: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchJourneys(from_, to) {
|
||||
return fetchApi(["journeys"], {
|
||||
from: from_,
|
||||
to: to,
|
||||
});
|
||||
}
|
26
web/index.html
Normal file
26
web/index.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script type="module" src="traveldrafter.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="journey-search-from">Select…</div>
|
||||
<div id="journey-search-to">Select…</div>
|
||||
<div id="journey-search-submit">Search</div>
|
||||
<div id="journey-search-result"></div>
|
||||
|
||||
<div id="locations-search" class="popup">
|
||||
<div class="popup-close">×</div>
|
||||
<div id="locations-search-content" class="popup-content">
|
||||
<div class="container">
|
||||
<input id="locations-search-query" class="form-control" type="text" />
|
||||
<div id="locations-search-response"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
39
web/journeys-search.js
Normal file
39
web/journeys-search.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { fetchJourneys } from './api.js';
|
||||
import { attachLocationsSearch } from './locations-search.js';
|
||||
|
||||
let element_from = document.querySelector("#journey-search-from");
|
||||
let element_to = document.querySelector("#journey-search-to");
|
||||
let element_submit = document.querySelector("#journey-search-submit");
|
||||
let element_result = document.querySelector("#journey-search-result");
|
||||
|
||||
export function setupJourneysSearch() {
|
||||
attachLocationsSearch(element_from);
|
||||
attachLocationsSearch(element_to);
|
||||
|
||||
element_submit.addEventListener("click", event => {
|
||||
element_result.innerText = "Loading…";
|
||||
fetchJourneys(element_from.dataset.locationId, element_to.dataset.locationId).then(result => {
|
||||
for (let journey of result.journeys) {
|
||||
element_result.appendChild(createJourneyElement(journey));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createJourneyElement(journey) {
|
||||
let el = document.createElement("div");
|
||||
|
||||
for (let leg of journey.legs) {
|
||||
el.appendChild(createJourneyLegElement(leg));
|
||||
}
|
||||
|
||||
return el;
|
||||
|
||||
}
|
||||
|
||||
function createJourneyLegElement(leg) {
|
||||
let el = document.createElement("div");
|
||||
el.innerText = JSON.stringify(leg);
|
||||
el.innerText = leg?.line?.name + ": " + leg.origin.name + " > " + leg.destination.name;
|
||||
return el;
|
||||
}
|
36
web/locations-search.js
Normal file
36
web/locations-search.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { fetchLocations } from './api.js';
|
||||
|
||||
let element_locations_search = document.querySelector("#locations-search");
|
||||
let element_query = document.querySelector("#locations-search-query");
|
||||
let element_response = document.querySelector("#locations-search-response");
|
||||
|
||||
export function setupLocationsSearch() {
|
||||
element_query.addEventListener("change", (event) => {
|
||||
element_response.innerText = "Loading…";
|
||||
fetchLocations(event.target.value).then(result => {
|
||||
element_response.innerText = "";
|
||||
result.forEach(lr => {
|
||||
let location_element = document.createElement("div");
|
||||
location_element.innerText = lr.name;
|
||||
location_element.dataset.locationId = lr.id;
|
||||
|
||||
location_element.addEventListener("click", event => {
|
||||
console.log(event.target.dataset.locationId);
|
||||
element_locations_search.locationSelectedCallback(event.target.innerText, event.target.dataset.locationId);
|
||||
element_locations_search.style.display = "none";
|
||||
});
|
||||
element_response.appendChild(location_element);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function attachLocationsSearch(search_element) {
|
||||
search_element.addEventListener("click", event => {
|
||||
element_locations_search.locationSelectedCallback = (location_name, location_id) => {
|
||||
search_element.innerText = location_name;
|
||||
search_element.dataset.locationId = location_id;
|
||||
};
|
||||
element_locations_search.style.display = "block";
|
||||
});
|
||||
}
|
7
web/popup.js
Normal file
7
web/popup.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export function setupPopups() {
|
||||
document.querySelectorAll(".popup-close").forEach(element => {
|
||||
element.addEventListener("click", event => {
|
||||
event.target.parentElement.style.display="none";
|
||||
});
|
||||
});
|
||||
}
|
54
web/style.css
Normal file
54
web/style.css
Normal file
@@ -0,0 +1,54 @@
|
||||
* {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
|
||||
max-width: 768px;
|
||||
}
|
||||
|
||||
.popup {
|
||||
position: fixed;
|
||||
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
z-index: 10000;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
color: white;
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
.popup .popup-close {
|
||||
margin: 60px;
|
||||
margin-left: auto;
|
||||
font-size: 60px;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.popup .popup-content {
|
||||
position: relative;
|
||||
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.popup input {
|
||||
color: white;
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
width: 100%;
|
||||
background-color: transparent;
|
||||
|
||||
border: none;
|
||||
border-bottom-style: solid;
|
||||
border-width: 1px;
|
||||
font-size: 2em;
|
||||
}
|
10
web/traveldrafter.js
Normal file
10
web/traveldrafter.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import * as Api from './api.js';
|
||||
import { setupPopups } from "./popup.js";
|
||||
import { setupLocationsSearch } from './locations-search.js';
|
||||
import { setupJourneysSearch } from './journeys-search.js';
|
||||
|
||||
window.Api = Api;
|
||||
|
||||
setupPopups();
|
||||
setupLocationsSearch();
|
||||
setupJourneysSearch();
|
Reference in New Issue
Block a user