oeffisearch/client/js/searchView.js
2020-06-12 14:49:54 +00:00

429 lines
14 KiB
JavaScript

'use strict';
import { showDiv, ElementById, padZeros, isValidDate } from './helpers.js';
import { getCache, addCache, parseName, saveDataStorage, ConsoleLog, t, loadDS100 } from './app_functions.js';
import { dataStorage } from './app.js';
import { get } from './api.js';
import { go } from './router.js';
import { html, render } from './lit-html.js';
import { showAlertModal, showSelectModal, showLoader, hideLoader} from './overlays.js';
import { showSettings } from './settingsView.js';
let currDate = new Date();
let fromValue = '';
let toValue = '';
let isArrValue = false;
let dateValue = currDate.getFullYear()+'-'+padZeros(currDate.getMonth()+1)+'-'+padZeros(currDate.getDate());;
let timeValue = padZeros(currDate.getHours())+':'+padZeros(currDate.getMinutes());
let suggestionsCache = {
from: {},
to: {},
};
const searchTemplate = (journeysHistory) => html`
<div class="center">
<form class="search" onsubmit="return false;">
<div class="title">
<div class="logo"></div>
<h1>Öffisearch</h1>
</div>
<label for="from">${t('from')}:</label>
<input type="text" name="from" id="from" placeholder="${t('from')}" value="${fromValue}" autocomplete="off" @keyup=${loadSuggestions} @focus=${startTyping} @blur=${stopTyping} @keypress=${onKeypress} required>
<div class="suggestions" id="fromSuggestions"></div>
<label for="to">${t('to')}:</label>
<input type="text" name="to" id="to" placeholder="${t('to')}" value="${toValue}" autocomplete="off" @keyup=${loadSuggestions} @focus=${startTyping} @blur=${stopTyping} @keypress=${onKeypress} required>
<div class="suggestions" id="toSuggestions"></div>
<div class="row">
<label class="switch">
<input type="checkbox" id="isarr" name="isarr" ?checked=${isArrValue}>
<span class="slider ${t('lang_short')}"></span>
<label for="isarr"> <br></label>
</label>
<label for="date">${t('date')}:</label>
<input type="date" name="date" id="date" value="${dateValue}" placeholder="${t('date')}" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" @keypress=${onKeypressSubmit} required>
<label for="time"><br>${t('time')}:</label>
<input type="time" name="time" id="time" value="${timeValue}" placeholder="${t('time')}" pattern="[0-9]{2}:[0-9]{2}" @keypress=${onKeypressSubmit} required>
</div>
<div class="row">
<span class="hidden">${t('products')}:</span>
<div class="selector">
${dataStorage.settings.advancedSelection ? html`
<input type="checkbox" id="nationalExp" name="nationalExp" checked>
<label for="nationalExp" title="${t('iceonly')}">${t('iceonly')}<br></label>
<input type="checkbox" id="national" name="national" checked>
<label class="ic" for="national" title="${t('iconly')}">${t('iconly')}<br></label>
` : html`
<input type="checkbox" id="national" name="national" checked>
<label class="ic-ice" for="national" title="${t('longdistancetrain')}">${t('longdistancetrain')}<br></label>
`}
${dataStorage.settings.advancedSelection ? html`
<input type="checkbox" id="regionalExp" name="regionalExp" checked>
<label for="regionalExp" title="${t('dzug')}">${t('dzug')}<br></label>
<input type="checkbox" id="regional" name="regional" checked>
<label for="regional" title="${t('regionaltrain')}">${t('regionaltrain')}<br></label>
` : html`
<input type="checkbox" id="regional" name="regional" checked>
<label for="regional" title="${t('regionaltrain')}">${t('regionaltrain')}<br></label>
`}
<input type="checkbox" id="suburban" name="suburban" checked>
<label for="suburban" title="${t('suburbantrain')}">${t('suburbantrain')}<br></label>
<input type="checkbox" id="subway" name="subway" checked>
<label for="subway" title="${t('subway')}">${t('subway')}<br></label>
<input type="checkbox" id="tram" name="tram" checked>
<label for="tram" title="${t('tram')}">${t('tram')}<br></label>
<input type="checkbox" id="bus" name="bus" checked>
<label for="bus" title="${t('bus')}">${t('bus')}<br></label>
<input type="checkbox" id="ferry" name="ferry" checked>
<label for="ferry" title="${t('ferry')}">${t('ferry')}<br></label>
<input type="checkbox" id="taxi" name="taxi" checked>
<label for="taxi" title="${t('taxi')}">${t('taxi')}<br></label>
</div>
<span class="hidden">{{LABEL_ACCESSIBILITY}}:</span>
<div class="selector">
<input type="radio" id="accessibilityNone" name="accessibility" value="none" ?checked=${dataStorage.settings.accessibility === "none"}>
<label for="accessibilityNone" title="{{LABEL_ACCESSIBILITY_NONE}}">{{LABEL_ACCESSIBILITY_NONE}}<br></label>
<input type="radio" id="accessibilityPartial" name="accessibility" value="partial" ?checked=${dataStorage.settings.accessibility === "partial"}>
<label for="accessibilityPartial" title="{{LABEL_ACCESSIBILITY_PARTIAL}}">{{LABEL_ACCESSIBILITY_PARTIAL}}<br></label>
<input type="radio" id="accessibilityComplete" name="accessibility" value="complete" ?checked=${dataStorage.settings.accessibility === "complete"}>
<label for="accessibilityComplete" title="{{LABEL_ACCESSIBILITY_FULL}}">{{LABEL_ACCESSIBILITY_FULL}}<br></label>
</div>
<div class="selector" >
<div class="btn swap" title="${t('swap')}" @click=${swapFromTo}></div>
<div class="btn settings" title="${t('settings')}" @click=${showSettings}></div>
</div>
<div class="button btn go" tabindex="0" id="go" @click=${search}>
${t('search')}
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"/></svg>
</div>
</div>
${journeysHistory.length ? html`
<input type="checkbox" id="btn-history" class="btn history hidden">
<label for="btn-history"></label>
${journeysHistoryTemplate(journeysHistory)}
` : ''}
</div>
</div>
`;
const journeysHistoryTemplate = (journeysHistory) => html`
<div class="history">
${journeysHistory.map(element => html`
<div class="row history" @click=${() => {journeysHistoryAction(journeysHistory, element)}}">
<div class="history from">
<small>${t('from')}:</small><br>
${parseName(element.fromPoint)}
</div>
<div class="history arrow"></div>
<div class="history to">
<small>${t('to')}:</small><br>
${parseName(element.toPoint)}
</div>
</div>
`)}
</div>
`;
const journeysHistoryAction = (journeysHistory, element) => {
ConsoleLog(element);
showSelectModal(html`
<a @click=${() => {setFromHistory(journeysHistory.length - 1 - journeysHistory.indexOf(element));hideLoader()}}>${t('setfromto')}</a>
<a @click=${() => {go("/"+element.reqId);hideLoader();}}>${t('journeyoverview')}</a>
${element.journeyId === '' ? '' : html`
<a @click=${() => {go("/"+element.reqId+"/"+element.journeyId);hideLoader();}}>${t('lastjourney')}</a>
`}
`);
};
export const searchView = () => {
const journeysHistory = getCache('journeysHistory').slice().reverse();
render(searchTemplate(journeysHistory), ElementById('content'));
ElementById('from').focus();
for (let product in dataStorage.settings.products) {
if (ElementById(product) !== null) {
ElementById(product).checked = dataStorage.settings.products[product];
}
};
};
export const search = async (requestId) => {
const provider = dataStorage.settings.provider;
let products = readProductSelection();
const accessibility = document.querySelector('input[name="accessibility"]:checked').value;
let isDep = !ElementById('isarr').checked;
let date = ElementById('date').value;
let time = ElementById('time').value;
let timestamp = '';
let from = '';
let to = '';
currDate = new Date();
fromValue = ElementById('from').value;
toValue = ElementById('to').value;
dateValue = ElementById('date').value;
timeValue = ElementById('time').value;
isArrValue = ElementById('isarr').checked;
if (date !== '') {
if (!isValidDate(date)) {
showAlertModal('Ungültiges Datum!');
return;
}
} else {
date = currDate.getFullYear()+'-'+padZeros(currDate.getMonth()+1)+'-'+padZeros(currDate.getDate());
}
if (time !== '') {
if (!new RegExp('([0-1][0-9]|2[0-3]):([0-5][0-9])').test(time)) {
showAlertModal('Ungültige Zeitangabe!');
return;
}
} else {
time = padZeros(currDate.getHours())+':'+padZeros(currDate.getMinutes());
}
if (ElementById('from').value == "" | ElementById('to').value == "") {
showAlertModal("Abfahrts - und Ankunftsbahnhof müssen ausgefüllt werden.");
return;
}
if (Object.entries(suggestionsCache.from).length !== 0) {
from = suggestionsCache.from;
} else {
let suggestions = await get("/suggestions", {"query": ElementById('from').value, "results": 1}, true);
if (!suggestions[0]) {
showAlertModal("Abfahrtsbahnof ungültig");
return;
}
from = suggestions[0]
}
if (Object.entries(suggestionsCache.to).length !== 0) {
to = suggestionsCache.to;
} else {
let suggestions = await get("/suggestions", {"query": ElementById('to').value, "results": 1}, true);
if (!suggestions[0]) {
showAlertModal("Ankunftsbahnhof ungültig");
return;
}
to = suggestions[0]
}
dataStorage.settings.products = products;
dataStorage.settings.accessibility = accessibility;
saveDataStorage();
const split_date = date.split('-');
const split_time = time.split(':');
timestamp = Math.round(new Date(split_date[0], split_date[1]-1, split_date[2], split_time[0], split_time[1]).getTime()/1000);
ConsoleLog(timestamp+'///'+date+' '+time+':00');
let params = {
"fromPoint": from,
"toPoint": to,
"accessibility": accessibility,
"products": products
}
if (!isDep) {
params.arrival = timestamp
} else {
params.departure = timestamp
}
const data = await get("/journeys", {"params":params});
addCache('journeys', data);
go('/' + data.reqId);
return false;
};
const suggestionsTemplate = (suggestions, inputId) => html`
<div class="suggestionsbox" @mouseover=${mouseOverSuggestions} @mouseout=${stopMouseOverSuggestions}>
${suggestions.map(element => html`
<p class="suggestion" @click=${() => setSuggestion(encodeURI(JSON.stringify(element)), inputId)}>${parseName(element)}</p>
`)}
</div>
`;
const loadSuggestions = async (e, input) => {
const val = e.target.value;
suggestionsCache[e.target.id] = {};
const suggestions = val ? await get("/suggestions", {"query": val}, true) : [];
const suggestionsEl = ElementById(e.target.id+'Suggestions');
render(suggestionsTemplate(suggestions, e.target.id), suggestionsEl);
};
export const setSuggestion = (data, inputId) => {
if (typeof data === 'string') {
data = JSON.parse(decodeURI(data));
}
suggestionsCache[inputId] = data;
ElementById(inputId).value = parseName(data);
if (inputId === 'from') {
ElementById('fromSuggestions').classList.remove('mouseover');
ElementById('to').focus();
} else if (inputId === 'to') {
ElementById('toSuggestions').classList.remove('mouseover');
ElementById('to').blur();
}
};
export const swapFromTo = () => {
suggestionsCache.from = [suggestionsCache.to, suggestionsCache.to = suggestionsCache.from][0];
let from = ElementById('from');
let to = ElementById('to');
from.value = [to.value, to.value = from.value][0];
};
export const setFromHistory = (id) => {
const cache = getCache('journeysHistory');
if (cache[id] !== undefined){
setSuggestion(cache[id].fromPoint, 'from');
setSuggestion(cache[id].toPoint, 'to');
}
};
export const readProductSelection = () => {
let products = {
"nationalExp": false,
"national": false,
"regionalExp": false,
"regional": false,
"suburban": false,
"bus": false,
"ferry": false,
"subway": false,
"tram": false,
"taxi": false
}
if (ElementById('national').checked !== false) {
products.national = true;
if (dataStorage.settings.advancedSelection !== true) {
products.nationalExp = true;
}
}
if (ElementById('regional').checked !== false) {
products.regional = true;
if (dataStorage.settings.advancedSelection !== true) {
products.regionalExp = true;
}
}
if (dataStorage.settings.advancedSelection !== false) {
if (ElementById('nationalExp').checked !== false) {
products.nationalExp = true;
}
if (ElementById('regionalExp').checked !== false) {
products.regionalExp = true;
}
}
if (ElementById('suburban').checked !== false) {
products.suburban = true;
}
if (ElementById('subway').checked !== false) {
products.subway = true;
}
if (ElementById('tram').checked !== false) {
products.tram = true;
}
if (ElementById('bus').checked !== false) {
products.bus = true;
}
if (ElementById('ferry').checked !== false) {
products.ferry = true;
}
if (ElementById('taxi').checked !== false) {
products.taxi = true;
}
return products;
};
const startTyping = (e) => {
ElementById(e.target.id+'Suggestions').classList.add('typing');
if (e.target.id == 'from') ElementById('toSuggestions').classList.remove('mouseover');
if (e.target.id == 'to') ElementById('fromSuggestions').classList.remove('mouseover');
};
const stopTyping = (e) => {
ElementById(e.target.id+'Suggestions').classList.remove('typing');
};
const mouseOverSuggestions = (e) => {
let el = e.target;
let i = 0;
while (i++ < 10 && el.id !== 'fromSuggestions' && el.id !== 'toSuggestions') el = el.parentElement;
el.classList.add('mouseover');
};
const stopMouseOverSuggestions = (e) => {
let el = e.target;
let i = 0;
while (i++ < 10 && el.id !== 'fromSuggestions' && el.id !== 'toSuggestions') el = el.parentElement;
el.classList.remove('mouseover');
};
const onKeypress = (e) => {
if (e.which == 13 || e.keyCode == 13) { // enter
document.querySelector(`#${e.target.id}Suggestions>.suggestionsbox>:first-child`).click();
if (e.target.id === 'to') ElementById('go').click();
return false;
}
return true;
};
const onKeypressSubmit = (e) => {
if (e.which == 13 || e.keyCode == 13) { // enter
ElementById('go').click();
return false;
}
return true;
};