simplify application and remove window references
Sonarqube Scanner / Build and analyze (push) Failing after 1m27s
Sonarqube Scanner / Build and analyze (push) Failing after 1m27s
This commit is contained in:
+37
-17
@@ -99,7 +99,7 @@ button,
|
||||
padding: .35rem;
|
||||
border-color: rgba(255, 255, 255, .45);
|
||||
border-radius: .45rem;
|
||||
background: rgba(255, 255, 255, .12);
|
||||
background: var(--primary-dark);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -289,38 +289,45 @@ button,
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.route-facts {
|
||||
#route-page dl {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: .5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.route-facts div {
|
||||
#route-page dl > div {
|
||||
padding: .75rem;
|
||||
border-radius: .5rem;
|
||||
background: var(--surface);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.route-facts dt {
|
||||
#route-page dt {
|
||||
color: var(--muted);
|
||||
font-size: .8rem;
|
||||
}
|
||||
|
||||
.route-facts dd {
|
||||
#route-page dd {
|
||||
margin: .25rem 0 0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.route-controls {
|
||||
#route-page fieldset,
|
||||
#slideshow > fieldset {
|
||||
min-width: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#route-page fieldset {
|
||||
display: grid;
|
||||
padding: 0;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: .5rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
.route-controls button {
|
||||
#route-page fieldset button {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-width: 0;
|
||||
@@ -334,23 +341,35 @@ button,
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.route-controls button:focus-visible {
|
||||
#route-page fieldset button:focus-visible {
|
||||
outline: .2rem solid var(--focus);
|
||||
outline-offset: .15rem;
|
||||
}
|
||||
|
||||
.route-controls button:disabled {
|
||||
#route-page fieldset button:disabled {
|
||||
cursor: default;
|
||||
filter: grayscale(.65);
|
||||
opacity: .42;
|
||||
}
|
||||
|
||||
.route-controls img {
|
||||
#route-page fieldset img {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#route-page fieldset > legend,
|
||||
#slideshow > fieldset > legend {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#start-route {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary-dark);
|
||||
@@ -386,8 +405,9 @@ button,
|
||||
background: #111;
|
||||
}
|
||||
|
||||
#slide-controls {
|
||||
#slideshow > fieldset {
|
||||
display: grid;
|
||||
margin: 0;
|
||||
grid-template-columns: var(--icon-button-size) minmax(0, 1fr) var(--icon-button-size);
|
||||
align-items: stretch;
|
||||
gap: .5rem;
|
||||
@@ -396,7 +416,7 @@ button,
|
||||
padding: .65rem;
|
||||
}
|
||||
|
||||
#slide-controls .ui-button {
|
||||
#slideshow > fieldset .ui-button {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-width: 0;
|
||||
@@ -405,13 +425,13 @@ button,
|
||||
padding: .45rem;
|
||||
}
|
||||
|
||||
#slide-controls .ui-button img {
|
||||
#slideshow > fieldset .ui-button img {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.slide-meta {
|
||||
#slideshow > fieldset > div {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
min-height: var(--icon-button-size);
|
||||
@@ -521,17 +541,17 @@ button,
|
||||
grid-template-columns: minmax(0, 1fr) 3rem;
|
||||
}
|
||||
|
||||
.route-facts {
|
||||
#route-page dl {
|
||||
gap: .35rem;
|
||||
}
|
||||
|
||||
.route-facts div {
|
||||
#route-page dl > div {
|
||||
padding: .6rem .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 22rem) {
|
||||
.route-facts {
|
||||
#route-page dl {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-15
@@ -8,8 +8,8 @@
|
||||
<link rel="stylesheet" href="css/bootstrap.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="bootstrap-screen" role="status" aria-live="polite">
|
||||
<section aria-label="Anwendung wird initialisiert">
|
||||
<div id="bootstrap-screen" aria-live="polite" aria-busy="true">
|
||||
<section>
|
||||
<span aria-hidden="true">🧭</span>
|
||||
<h1>Wegwichtel</h1>
|
||||
<p>Der Wegwichtel bereitet Routen und Medien vor.</p>
|
||||
@@ -31,20 +31,20 @@
|
||||
</div>
|
||||
|
||||
<main id="app-shell" hidden>
|
||||
<section id="routes-page" class="app-page" aria-label="Routenauswahl">
|
||||
<section id="routes-page" class="app-page">
|
||||
<header>
|
||||
<h1>Wegwichtel</h1>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<p id="location-hint" class="notice">Standort wird ermittelt.</p>
|
||||
<p id="location-hint" class="notice">Standort wird für nahe Routen lokal auf diesem Gerät ermittelt.</p>
|
||||
|
||||
<section aria-label="Routen in der Nähe">
|
||||
<section>
|
||||
<h2>Routen in deiner Nähe</h2>
|
||||
<ul id="nearby-route-list" class="route-list" aria-live="polite"></ul>
|
||||
</section>
|
||||
|
||||
<section aria-label="Alle Routen">
|
||||
<section>
|
||||
<h2>Alle Routen</h2>
|
||||
<label for="route-search">Routen durchsuchen</label>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="route-page" class="app-page" aria-label="Ausgewählte Route" hidden>
|
||||
<section id="route-page" class="app-page" hidden>
|
||||
<header>
|
||||
<button class="back-button" type="button" data-page-target="#routes-page" aria-label="Zurück zur Routenauswahl" title="Zurück zur Routenauswahl">
|
||||
<img src="images/icons/back.svg" alt="">
|
||||
@@ -75,13 +75,14 @@
|
||||
<div class="content">
|
||||
<p id="route-description"></p>
|
||||
|
||||
<dl class="route-facts">
|
||||
<dl>
|
||||
<div><dt>Länge</dt><dd id="route-distance">–</dd></div>
|
||||
<div><dt>Höhenmeter</dt><dd id="route-elevation">–</dd></div>
|
||||
<div><dt>POIs</dt><dd id="route-poi-count">–</dd></div>
|
||||
</dl>
|
||||
|
||||
<div class="route-controls" role="group" aria-label="Routensteuerung">
|
||||
<fieldset>
|
||||
<legend>Routensteuerung</legend>
|
||||
<button id="start-route" type="button" aria-label="Route starten" title="Route starten">
|
||||
<img src="images/icons/play.svg" alt="">
|
||||
</button>
|
||||
@@ -91,7 +92,7 @@
|
||||
<button id="stop-route" type="button" aria-label="Route beenden" title="Route beenden" disabled>
|
||||
<img src="images/icons/stop.svg" alt="">
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
<p id="tracking-status" class="notice" hidden></p>
|
||||
|
||||
<h2>Stationen</h2>
|
||||
@@ -99,7 +100,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="poi-page" class="app-page" aria-label="Station" hidden>
|
||||
<section id="poi-page" class="app-page" hidden>
|
||||
<header>
|
||||
<button class="back-button" type="button" data-page-target="#route-page" aria-label="Zurück zur Route" title="Zurück zur Route">
|
||||
<img src="images/icons/back.svg" alt="">
|
||||
@@ -113,18 +114,19 @@
|
||||
<img id="slide-image" alt="">
|
||||
</figure>
|
||||
|
||||
<div id="slide-controls" role="group" aria-label="Bildnavigation">
|
||||
<fieldset>
|
||||
<legend>Bildnavigation</legend>
|
||||
<button id="slide-prev" type="button" aria-label="Vorheriges Bild" title="Vorheriges Bild">
|
||||
<img src="images/icons/chevron-left.svg" alt="">
|
||||
</button>
|
||||
<div class="slide-meta">
|
||||
<div>
|
||||
<p id="slide-caption"></p>
|
||||
<span id="slide-position" aria-live="polite">0 / 0</span>
|
||||
<span id="slide-position">0 / 0</span>
|
||||
</div>
|
||||
<button id="slide-next" type="button" aria-label="Nächstes Bild" title="Nächstes Bild">
|
||||
<img src="images/icons/chevron-right.svg" alt="">
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<p id="poi-description"></p>
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
routes: position => request('/routes' + (position ? `?lat=${encodeURIComponent(position.lat)}&lon=${encodeURIComponent(position.lon)}&radiusKm=${ns.Config.routeRadiusKm}` : '')),
|
||||
route: id => request(`/routes/${encodeURIComponent(id)}`)
|
||||
};
|
||||
}(window.Wegwichtel, window.jQuery));
|
||||
}(globalThis.Wegwichtel, globalThis.jQuery));
|
||||
|
||||
+11
-14
@@ -9,7 +9,6 @@
|
||||
routeState: 'idle',
|
||||
activePage: null,
|
||||
routeProgressIndex: null,
|
||||
activePoiId: null,
|
||||
deviceHeading: null
|
||||
};
|
||||
|
||||
@@ -21,7 +20,7 @@
|
||||
$(document)
|
||||
.on('pointerup', selector, function (event) {
|
||||
const pointer = event.originalEvent;
|
||||
if (pointer && pointer.isPrimary === false) return;
|
||||
if (pointer?.isPrimary === false) return;
|
||||
if (pointer?.pointerType === 'mouse' && pointer.button !== 0) return;
|
||||
event.preventDefault();
|
||||
handler.call(this, event);
|
||||
@@ -38,10 +37,10 @@
|
||||
if (!target.length) throw new Error(`Unbekannte Ansicht: ${pageSelector}`);
|
||||
|
||||
const previous = state.activePage;
|
||||
$('.app-page').attr('hidden', true).removeClass('is-active');
|
||||
target.removeAttr('hidden').addClass('is-active');
|
||||
$('.app-page').attr('hidden', true);
|
||||
target.removeAttr('hidden');
|
||||
state.activePage = pageSelector;
|
||||
window.scrollTo({ top: 0, behavior: options.instant ? 'auto' : 'smooth' });
|
||||
globalThis.scrollTo({ top: 0, behavior: options.instant ? 'auto' : 'smooth' });
|
||||
|
||||
if (options.updateHistory === false) return;
|
||||
const historyState = { page: pageSelector, previous };
|
||||
@@ -52,7 +51,7 @@
|
||||
function normalizeSearch(value) {
|
||||
return String(value ?? '')
|
||||
.normalize('NFKD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replaceAll(/[\u0300-\u036f]/g, '')
|
||||
.toLocaleLowerCase('de');
|
||||
}
|
||||
|
||||
@@ -172,11 +171,10 @@
|
||||
}
|
||||
|
||||
function setActivePoi(poiId) {
|
||||
state.activePoiId = poiId == null ? null : Number(poiId);
|
||||
$('#poi-list [data-poi-id]').removeAttr('aria-current');
|
||||
if (state.activePoiId != null) {
|
||||
$(`#poi-list [data-poi-id="${state.activePoiId}"]`).attr('aria-current', 'step');
|
||||
}
|
||||
if (poiId == null) return;
|
||||
|
||||
$(`#poi-list [data-poi-id="${Number(poiId)}"]`).attr('aria-current', 'step');
|
||||
}
|
||||
|
||||
function endRoute({ announce = true, returnToRoutes = false } = {}) {
|
||||
@@ -451,7 +449,7 @@
|
||||
const metrics = updatePoiIndicators(position);
|
||||
if (state.routeState !== 'running') return;
|
||||
|
||||
let nearest = nearestPendingPoi(metrics);
|
||||
const nearest = nearestPendingPoi(metrics);
|
||||
updateNavigation(position);
|
||||
|
||||
$('#tracking-status').text(
|
||||
@@ -463,7 +461,6 @@
|
||||
state.triggered.add(nearest.poi.id);
|
||||
ns.Vibration.start(ns.Vibration.Patterns.ACTIVE_POI);
|
||||
showPoi(nearest.poi);
|
||||
nearest = nearestPendingPoi(metrics);
|
||||
updateNavigation(position);
|
||||
}
|
||||
}
|
||||
@@ -545,7 +542,7 @@
|
||||
endRoute({ returnToRoutes: true });
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', event => {
|
||||
globalThis.addEventListener('popstate', event => {
|
||||
const page = event.state?.page || '#routes-page';
|
||||
navigate(page, { updateHistory: false, instant: true });
|
||||
});
|
||||
@@ -587,4 +584,4 @@
|
||||
hideNavigation();
|
||||
}
|
||||
};
|
||||
}(window.Wegwichtel, window.jQuery));
|
||||
}(globalThis.Wegwichtel, globalThis.jQuery));
|
||||
|
||||
@@ -36,4 +36,4 @@
|
||||
|
||||
unload
|
||||
};
|
||||
}(window.Wegwichtel, window.jQuery));
|
||||
}(globalThis.Wegwichtel, globalThis.jQuery));
|
||||
|
||||
Vendored
+6
-6
@@ -41,7 +41,7 @@
|
||||
}
|
||||
|
||||
function initializeJqueryUi() {
|
||||
const $ = window.jQuery;
|
||||
const $ = globalThis.jQuery;
|
||||
$('#bootstrap-retry').button({ icon: 'ui-icon-refresh' });
|
||||
$('.back-button').button();
|
||||
$('#clear-route-search').button({ icon: 'ui-icon-close', showLabel: false });
|
||||
@@ -56,7 +56,7 @@
|
||||
try {
|
||||
await loadScript(
|
||||
`vendor/jquery/jquery-${versions.jquery}.min.js`,
|
||||
() => window.jQuery?.fn?.jquery === versions.jquery
|
||||
() => globalThis.jQuery?.fn?.jquery === versions.jquery
|
||||
);
|
||||
mark('jquery', 'done');
|
||||
|
||||
@@ -64,20 +64,20 @@
|
||||
await loadStyle('css/app.css');
|
||||
await loadScript(
|
||||
`vendor/jquery-ui/jquery-ui-${versions.jqueryUi}.min.js`,
|
||||
() => window.jQuery?.ui?.version === versions.jqueryUi
|
||||
() => globalThis.jQuery?.ui?.version === versions.jqueryUi
|
||||
);
|
||||
initializeJqueryUi();
|
||||
mark('jquery-ui', 'done');
|
||||
|
||||
for (const module of ['config', 'api-client', 'distance', 'geolocation', 'orientation', 'slideshow', 'audio-player', 'vibration', 'app']) {
|
||||
await loadScript(`js/${module}.js`, () => Boolean(window.Wegwichtel));
|
||||
await loadScript(`js/${module}.js`, () => Boolean(globalThis.Wegwichtel));
|
||||
}
|
||||
mark('modules', 'done');
|
||||
|
||||
await window.Wegwichtel.App.initialize({ markStep: mark });
|
||||
await globalThis.Wegwichtel.App.initialize({ markStep: mark });
|
||||
document.getElementById('bootstrap-screen').hidden = true;
|
||||
document.getElementById('app-shell').hidden = false;
|
||||
window.Wegwichtel.App.navigate('#routes-page', { replace: true });
|
||||
globalThis.Wegwichtel.App.navigate('#routes-page', { replace: true });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
const current = steps.find(step => !document.querySelector(`[data-step="${step}"]`)?.classList.contains('done'));
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
window.Wegwichtel = window.Wegwichtel || {};
|
||||
window.Wegwichtel.Config = Object.freeze({ apiBase: '/api', routeRadiusKm: 25, geolocationTimeoutMs: 12000 });
|
||||
globalThis.Wegwichtel ??= {};
|
||||
globalThis.Wegwichtel.Config = Object.freeze({ apiBase: '/api', routeRadiusKm: 25, geolocationTimeoutMs: 12000 });
|
||||
|
||||
@@ -30,4 +30,4 @@
|
||||
return meters < 1000 ? `${Math.round(meters)} m` : `${(meters / 1000).toFixed(1)} km`;
|
||||
}
|
||||
};
|
||||
}(window.Wegwichtel));
|
||||
}(globalThis.Wegwichtel));
|
||||
|
||||
+26
-14
@@ -1,8 +1,17 @@
|
||||
(function (ns) {
|
||||
'use strict';
|
||||
|
||||
const WATCH_OPTIONS = Object.freeze({
|
||||
enableHighAccuracy: true,
|
||||
timeout: 20000,
|
||||
maximumAge: 5000
|
||||
});
|
||||
let watchId = null;
|
||||
|
||||
function geolocation() {
|
||||
return globalThis.navigator?.geolocation;
|
||||
}
|
||||
|
||||
function normalize(position) {
|
||||
return {
|
||||
lat: position.coords.latitude,
|
||||
@@ -15,19 +24,24 @@
|
||||
};
|
||||
}
|
||||
|
||||
function unsupportedError() {
|
||||
return new Error('Dieses Gerät unterstützt keine Geolokalisierung.');
|
||||
}
|
||||
|
||||
ns.Geo = {
|
||||
current() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!navigator.geolocation) {
|
||||
reject(new Error('Dieses Gerät unterstützt keine Geolokalisierung.'));
|
||||
const service = geolocation();
|
||||
if (!service) {
|
||||
reject(unsupportedError());
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
service.getCurrentPosition(
|
||||
position => resolve(normalize(position)),
|
||||
reject,
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
...WATCH_OPTIONS,
|
||||
timeout: ns.Config.geolocationTimeoutMs,
|
||||
maximumAge: 30000
|
||||
}
|
||||
@@ -37,25 +51,23 @@
|
||||
|
||||
start(callback, onError) {
|
||||
this.stop();
|
||||
if (!navigator.geolocation) {
|
||||
onError?.(new Error('Dieses Gerät unterstützt keine Geolokalisierung.'));
|
||||
const service = geolocation();
|
||||
if (!service) {
|
||||
onError?.(unsupportedError());
|
||||
return;
|
||||
}
|
||||
|
||||
watchId = navigator.geolocation.watchPosition(
|
||||
watchId = service.watchPosition(
|
||||
position => callback(normalize(position)),
|
||||
onError,
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
timeout: 20000,
|
||||
maximumAge: 5000
|
||||
}
|
||||
WATCH_OPTIONS
|
||||
);
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (watchId != null) navigator.geolocation.clearWatch(watchId);
|
||||
const service = geolocation();
|
||||
if (watchId != null) service?.clearWatch(watchId);
|
||||
watchId = null;
|
||||
}
|
||||
};
|
||||
}(window.Wegwichtel));
|
||||
}(globalThis.Wegwichtel));
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
async function requestPermission() {
|
||||
const orientation = window.DeviceOrientationEvent;
|
||||
const orientation = globalThis.DeviceOrientationEvent;
|
||||
if (!orientation) return false;
|
||||
|
||||
if (typeof orientation.requestPermission === 'function') {
|
||||
@@ -51,14 +51,14 @@
|
||||
if (heading != null) callback?.(heading);
|
||||
};
|
||||
|
||||
eventNames.forEach(name => window.addEventListener(name, listener, true));
|
||||
eventNames.forEach(name => globalThis.addEventListener(name, listener, true));
|
||||
return true;
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (listener) eventNames.forEach(name => window.removeEventListener(name, listener, true));
|
||||
if (listener) eventNames.forEach(name => globalThis.removeEventListener(name, listener, true));
|
||||
listener = null;
|
||||
callback = null;
|
||||
}
|
||||
};
|
||||
}(window.Wegwichtel));
|
||||
}(globalThis.Wegwichtel));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
$(document)
|
||||
.on('pointerup', selector, function (event) {
|
||||
const pointer = event.originalEvent;
|
||||
if (pointer && pointer.isPrimary === false) return;
|
||||
if (pointer?.isPrimary === false) return;
|
||||
if (pointer?.pointerType === 'mouse' && pointer.button !== 0) return;
|
||||
event.preventDefault();
|
||||
handler.call(this, event);
|
||||
@@ -29,7 +29,6 @@
|
||||
function render() {
|
||||
const hasImages = images.length > 0;
|
||||
$('#slideshow').toggle(hasImages);
|
||||
$('#slide-controls').attr('data-image-count', images.length);
|
||||
if (!hasImages) return;
|
||||
|
||||
const image = images[index];
|
||||
@@ -86,4 +85,4 @@
|
||||
if (deltaX < 0) ns.Slideshow.next();
|
||||
else ns.Slideshow.previous();
|
||||
});
|
||||
}(window.Wegwichtel, window.jQuery));
|
||||
}(globalThis.Wegwichtel, globalThis.jQuery));
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
if (!Number.isFinite(duration) || duration < 0) {
|
||||
throw new TypeError('Die Vibrationsdauer muss eine nichtnegative Millisekundenangabe sein.');
|
||||
}
|
||||
return duration;
|
||||
return [duration];
|
||||
}
|
||||
|
||||
function start(pattern = Patterns.LONG) {
|
||||
@@ -50,4 +50,4 @@
|
||||
start,
|
||||
stop
|
||||
});
|
||||
}(window.Wegwichtel));
|
||||
}(globalThis.Wegwichtel));
|
||||
|
||||
Reference in New Issue
Block a user