Cleanup of code

This commit is contained in:
Pieter Vander Vennet 2020-07-24 01:12:57 +02:00
parent dd91e11bd0
commit e0f9a93468
12 changed files with 193 additions and 369 deletions

View file

@ -96,13 +96,11 @@ export class WelcomeMessage extends UIElement {
}
InnerRender(): string {
return "<div id='welcomeMessage'>" +
return "<span id='welcomeMessage'>" +
this.description.Render() +
"<br/>"+
(this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() +
"<br/>"+
this.tail.Render() +
"</div>"
"</span>"
;
/*

View file

@ -41,6 +41,7 @@ export class LayerUpdater {
map.Location.addCallback(function () {
self.update();
});
self.update();
}

View file

@ -1,76 +0,0 @@
import {QuestionDefinition} from "./Logic/Question";
export class Quests {
static hasFee = QuestionDefinition.radioQuestionSimple("Moet men betalen om deze toiletten te gebruiken?", 10,
"fee",
[{text: "ja", value: "yes"}, {text: "nee", value: "no"}]
);
static toiletsWheelChairs = QuestionDefinition.radioQuestionSimple("Zijn deze toiletten rolstoeltoegankelijk?", 20,
"wheelchair",
[{text: "ja", value: "yes"}, {text: "nee", value: "no"}]
).addUnrequiredTag("toilets:position", "urinals");
static toiletsChangingTable = QuestionDefinition.radioQuestionSimple("Is er een luiertafel beschikbaar?", 20,
"changing_table",
[{text: "ja", value: "yes"}, {text: "nee", value: "no"}]
)
// Urinals are often a pitlatrine/something very poor where no changing table is
.addUnrequiredTag("toilets:position", "urinals").addUnrequiredTag("toilets:position", "urinal");
static toiletsChangingTableLocation = QuestionDefinition.radioAndTextQuestion("Waar bevindt de luiertafel zich?", 5,
"changing_table",
[{text: "In de vrouwentoiletten", value: "female_toilet"},
{text: "In de mannentoiletten", value: "male_toilet"},
{text: "In de rolstoeltoegangkelijke toiletten", value: "wheelchair_toilet"},
{text: "In de aparte, speciaal voorziene ruimte", value: "dedicated_room"},
{text: "In de genderneutrale toiletten", value: "unisex_toilet"}]
)
.addRequiredTag("changing_table", "yes");
static toiletsPosition = QuestionDefinition.radioQuestionSimple("Wat voor toiletten zijn dit?", 1,
"toilets:position",
[{text: "Enkel urinoirs", value: "urinals"},
{text: "Enkel 'gewone' toiletten waar men op gaat zitten", value: "seated"},
{text: "Er zijn zowel urinoirs als zittoiletten", value: "seated;urinals"}]);
static accessNatureReserve = QuestionDefinition.radioQuestionSimple(
"Is dit gebied toegankelijk voor het publiek?",
10,
"access",
[
{text: "Nee, dit is afgesloten", value: "no"},
{text: "Nee, dit is een privaat terrein", value: "no"},
{text: "Hoewel het een privebos is, kan men er toch in", value: "permissive"},
{text: "Enkel tijdens activiteiten of met een gids", value: "guided"},
{text: "Ja, het is gewoon toegankelijk", value: "yes"}
]
).addUnrequiredTag("seamark:type", "restricted_area");
static nameOf(name: string) : QuestionDefinition {
return QuestionDefinition.noNameOrNameQuestion("<b>Wat is de <i>officiële</i> naam van dit " + name + "?</b><br />" +
"Veel gebieden hebben geen naam. Duid dit dan ook zo aan.",
"Dit " + name + " heeft geen naam", 20);
}
static operator =
QuestionDefinition.radioAndTextQuestion(
"Wie is de beheerder van dit gebied?",
1,
"operator",
[{text: "Natuurpunt", value: "Natuurpunt"},
{text: "Het Agenschap voor Natuur en Bos", value: "Agentschap Natuur en Bos"},
{text: "Een prive-eigenaar", value: "private"}
]
).addUnrequiredTag("access", "private")
.addUnrequiredTag("access", "no");
}

View file

@ -1,148 +0,0 @@
import {UIEventSource} from "./UIEventSource";
import {UIElement} from "./UIElement";
import {Basemap} from "../Logic/Basemap";
import {Changes} from "../Logic/Changes";
import L from "leaflet";
import {Tag} from "../Logic/TagsFilter";
import {FilteredLayer} from "../Logic/FilteredLayer";
export class AddButton extends UIElement {
public curentAddSelection: UIEventSource<string> = new UIEventSource<string>("");
private zoomlevel: UIEventSource<{ zoom: number }>;
private readonly SELECTING_POI = "selecting_POI";
private readonly PLACING_POI = "placing_POI";
private changes: Changes;
/*State is one of:
* "": the default stated
* "select_POI": show a 'select which POI to add' query (skipped if only one option exists)
* "placing_point": shown while adding a point
* ""
*/
private state: UIEventSource<string> = new UIEventSource<string>("");
private _options: { name: string; icon: string; tags: Tag[]; layerToAddTo: FilteredLayer }[];
constructor(
basemap: Basemap,
changes: Changes,
options: {
name: string,
icon: string,
tags: Tag[],
layerToAddTo: FilteredLayer
}[]) {
super(undefined);
this.zoomlevel = basemap.Location;
this.ListenTo(this.zoomlevel);
this._options = options;
this.ListenTo(this.curentAddSelection);
this.ListenTo(this.state);
this.state.setData(this.SELECTING_POI);
this.changes = changes;
const self = this;
basemap.map.on("click", function (e) {
const location = e.latlng;
console.log("Clicked at ", location)
self.HandleClick(location.lat, location.lng)
}
);
basemap.map.on("mousemove", function(){
if (self.state.data === self.PLACING_POI) {
let icon = "crosshair";
for (const option of self._options) {
if (option.name === self.curentAddSelection.data && option.icon !== undefined) {
icon = 'url("' + option.icon + '") 32 32 ,crosshair';
console.log("Cursor icon: ", icon)
}
}
document.getElementById('leafletDiv').style.cursor = icon;
} else {
// @ts-ignore
document.getElementById('leafletDiv').style.cursor = '';
}
});
}
private HandleClick(lat: number, lon: number): void {
this.state.setData(this.SELECTING_POI);
console.log("Handling click", lat, lon, this.curentAddSelection.data);
for (const option of this._options) {
if (this.curentAddSelection.data === option.name) {
console.log("PLACING a ", option);
let feature = this.changes.createElement(option.tags, lat, lon);
option.layerToAddTo.AddNewElement(feature);
return;
}
}
}
protected InnerRender(): string {
if (this.zoomlevel.data.zoom < 19) {
return "Zoom in om een punt toe te voegen"
}
if (this.state.data === this.SELECTING_POI) {
var html = "<form>";
for (const option of this._options) {
// <button type='button'> looks SO retarded
// the default type of button is 'submit', which performs a POST and page reload
html += "<button type='button' class='addPOIoption' value='" + option.name + "'>Voeg een " + option.name + " toe</button><br/>";
}
html += "</form>";
return html;
}
if (this.state.data === this.PLACING_POI) {
return "<div id='clickOnMapInstruction'>Klik op de kaart om een nieuw punt toe te voegen<div>" +
"<div id='cancelInstruction'>Klik hier om toevoegen te annuleren</div>"
}
if (this.curentAddSelection.data === "") {
return "<span onclick>Voeg een punt toe...</span>"
}
return "Annuleer";
}
InnerUpdate(htmlElement: HTMLElement) {
const self = this;
htmlElement.onclick = function (event) {
// @ts-ignore
if(event.consumed){
return;
}
if (self.state.data === self.PLACING_POI) {
self.state.setData(self.SELECTING_POI);
}
}
const buttons = htmlElement.getElementsByClassName('addPOIoption');
// @ts-ignore
for (const button of buttons) {
button.onclick = function (event) {
self.curentAddSelection.setData(button.value);
self.state.setData(self.PLACING_POI);
event.consumed = true;
}
}
}
}

View file

@ -1,43 +0,0 @@
import {UIElement} from "../UIElement";
import {UIEventSource} from "../UIEventSource";
export class CollapseButton extends UIElement {
public isCollapsed = new UIEventSource(false);
constructor(idToCollapse: string) {
super(undefined);
this.ListenTo(this.isCollapsed);
this.isCollapsed.addCallback((collapse) => {
const el = document.getElementById(idToCollapse);
if (el === undefined || el === null) {
console.log("Element not found")
return;
}
if (collapse) {
el.style.height = "3.5em";
el.style.width = "15em";
} else {
el.style.height = "auto";
el.style.width = "auto";
}
});
const self = this;
this.onClick(() => {
self.isCollapsed.setData(!self.isCollapsed.data);
})
}
protected InnerRender(): string {
const up = './assets/arrow-up.svg';
const down = './assets/arrow-down.svg';
let arrow = up;
if (this.isCollapsed.data) {
arrow = down;
}
return `<img class='collapse-button' src='${arrow}' alt='collapse'>`;
}
}

View file

@ -2,6 +2,7 @@ import {UIElement} from "../UIElement";
import {UIEventSource} from "../UIEventSource";
import { FilteredLayer } from "../../Logic/FilteredLayer";
import Translations from "../../UI/i18n/Translations";
import instantiate = WebAssembly.instantiate;
export class CheckBox extends UIElement{
@ -11,9 +12,10 @@ export class CheckBox extends UIElement{
private readonly _showEnabled: string|UIElement;
private readonly _showDisabled: string|UIElement;
constructor(showEnabled: string|UIElement, showDisabled: string|UIElement, data: UIEventSource<boolean> = undefined) {
constructor(showEnabled: string | UIElement, showDisabled: string | UIElement, data: UIEventSource<boolean> | boolean = false) {
super(undefined);
this._data = data ?? new UIEventSource<boolean>(false);
this._data =
data instanceof UIEventSource ? data : new UIEventSource(data ?? false);
this.ListenTo(this._data);
this._showEnabled = showEnabled;
this._showDisabled = showDisabled;

View file

@ -1,6 +1,6 @@
import { UIElement } from "./UIElement";
import { FilteredLayer } from "../Logic/FilteredLayer";
import { CheckBox } from "./Base/CheckBox";
import { CheckBox } from "./Input/CheckBox";
import Combine from "./Base/Combine";
export class LayerSelection extends UIElement{

17
Utils.ts Normal file
View file

@ -0,0 +1,17 @@
export class Utils {
/**
* Gives a clean float, or undefined if parsing fails
* @param str
*/
static asFloat(str): number {
if (str) {
const i = parseFloat(str);
if (isNaN(i)) {
return undefined;
}
return i;
}
return undefined;
}
}

71
assets/help.svg Normal file
View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
width="900"
height="900"
id="svg11382"
sodipodi:docname="help.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1001"
id="namedview8"
showgrid="false"
units="px"
inkscape:zoom="0.26767309"
inkscape:cx="339.73914"
inkscape:cy="440.83624"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg11382" />
<defs
id="defs11384" />
<g
transform="matrix(0.90103258,0,0,0.90103258,112.84058,-1.9060177)"
id="layer1">
<g
id="g11476">
<path
d="M 474.50888,718.22841 H 303.49547 v -22.30134 c -2.4e-4,-37.95108 4.30352,-68.76211 12.9113,-92.43319 8.60728,-23.67032 23.63352,-45.28695 40.65324,-64.84996 17.01914,-19.56211 41.98734,-26.33264 101.45793,-75.63085 31.69095,-25.82203 55.2813,-77.1523 55.28175,-98.67174 2.21232,-56.92245 -13.93983,-79.3422 -34.56287,-99.96524 -22.67355,-19.67717 -60.67027,-30.06998 -90.99892,-30.06998 -27.77921,6.9e-4 -68.46735,8.08871 -87.7666,25.37047 -25.93817,17.28308 -65.23747,73.70611 -57.04687,130.54577 l -194.516943,1.70222 c 0,-157.21399 29.393699,-198.69465 99.004113,-263.03032 67.39739,-54.376643 126.53128,-73.268365 243.84757,-73.268365 89.71791,0 161.89728,17.80281 214.32552,53.405855 71.20714,48.12472 122.30105,111.18354 122.30105,230.11281 -6.9e-4,44.32081 -19.15253,90.78638 -43.0726,128.33299 -18.38947,30.90938 -60.37511,66.45236 -118.21237,104.41628 -42.83607,25.7686 -66.67196,53.11926 -77.03964,72.0946 -10.36863,18.97603 -15.55271,43.72267 -15.55225,74.23999 z"
style="font-style:normal;font-weight:normal;font-size:1201.92492676px;font-family:'Bitstream Vera Sans';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path11472"
inkscape:connector-curvature="0" />
<path
d="m 482.38298,869.80902 a 94.042557,73.021278 0 1 1 -188.08511,0 94.042557,73.021278 0 1 1 188.08511,0 z"
transform="translate(1.106383,-5.5319149)"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path11474"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -101,8 +101,8 @@ form {
#usertext {
width: auto;
margin:0;
width: max-content;
margin: 0;
padding: 0.9em;
padding-left: 4.7em; /* Should be half of profile-pic's width + actual padding (same as padding-right)*/
@ -225,7 +225,7 @@ form {
}
@media only screen and (max-height: 600px) {
@media only screen and (max-height: 300px) {
/* Landscape */
#userbadge-and-search {
display: inline-block;
@ -267,44 +267,58 @@ form {
display: none; /*Only shown on small screens*/
}
#welcomeMessage {
max-width: 35em;
padding: 0;
padding-top: 1em;
padding-bottom: 1em;
}
#collapseButton {
.collapse-button {
position: absolute;
right: 1em;
background-color: white;
margin: 1.5em;
border: 2px solid black;
border-radius: 2em;
padding: 0.5em;
background-color: #e5f5ff;
width: 3.5em;
border-top-left-radius: 2em;
border-bottom-left-radius: 2em;
display: inline-block;
width: 1em;
height: 1em;
height:calc(100% - 8em);
}
#collapseButton img {
width: 1em;
height: 1em;
.collapse-button .collapse-button-img{
background-color: #e5f5ff;
}
e
#messagesbox-wrapper {
.open-button {
width: 2em;
border-top-left-radius: 2em;
border-bottom-left-radius: 2em;
}
.collapse-button-img {
border-radius: 50%;
box-sizing: border-box;
display: inline-block;
padding: 1em;
background-color: white;
}
.collapse-button-img img{
width: 1.5em;
padding: 0.5em;
margin: 0;
padding: 0;
}
#welcomeMessage {
display: inline-block;
background-color: white;
padding: 1em;
margin-left: 3.5em;
padding-left: 1em;
padding-bottom: 2em;
border-radius: 2em;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
width: 100%;
max-width: 25vw;
}
#messagesbox {
/*Only shown on big screens*/
padding: 2em;
padding-top: 1em;
padding-bottom: 1em;
z-index: 5000;
background-color: white;
border-radius: 2em;
padding: 0;
pointer-events: all;
}
@ -405,7 +419,7 @@ e
border-radius: 15px 15px 0 0;
}
@media only screen and (max-width: 600px), only screen and (max-height: 600px) {
@media only screen and (max-width: 600px), only screen and (max-height: 300px) {
#messagesbox-wrapper {
display: none;
}

View file

@ -36,10 +36,7 @@
<div id="searchbox"></div>
</div>
<br/>
<div id="messagesbox-wrapper">
<div id="collapseButton"></div>
<div id="messagesbox"></div>
</div>
</div>
<div id="filter__popup" class="filter__popup">

View file

@ -20,7 +20,7 @@ import {VariableUiElement} from "./UI/Base/VariableUIElement";
import {SearchAndGo} from "./UI/SearchAndGo";
import {CollapseButton} from "./UI/Base/CollapseButton";
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
import {CheckBox} from "./UI/Base/CheckBox";
import {CheckBox} from "./UI/Input/CheckBox";
import Translations from "./UI/i18n/Translations";
import Locale from "./UI/i18n/Locale";
import {Layout, WelcomeMessage} from "./Customizations/Layout";
@ -30,9 +30,10 @@ import {LayerSelection} from "./UI/LayerSelection";
import Combine from "./UI/Base/Combine";
import {Img} from "./UI/Img";
import {QueryParameters} from "./Logic/QueryParameters";
import {Utils} from "./Utils";
// --------------------- Read the URL parameters -----------------
// --------------------- Special actions based on the parameters -----------------
// @ts-ignore
if (location.href.startsWith("http://buurtnatuur.be")) {
@ -40,13 +41,11 @@ if (location.href.startsWith("http://buurtnatuur.be")) {
window.location.replace("https://buurtnatuur.be");
}
let dryRun = false;
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
// Set to true if testing and changes should NOT be saved
dryRun = true;
const testing = QueryParameters.GetQueryParameter("test");
testing.setData((testing.data === undefined) + "")
// If you have a testfile somewhere, enable this to spoof overpass
// This should be hosted independantly, e.g. with `cd assets; webfsd -p 8080` + a CORS plugin to disable cors rules
//Overpass.testUrl = "http://127.0.0.1:8080/streetwidths.geojson";
@ -55,7 +54,6 @@ if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
// ----------------- SELECT THE RIGHT QUESTSET -----------------
let defaultLayout = "walkbybrussels"
@ -74,16 +72,10 @@ for (const k in AllKnownLayouts.allSets) {
}
defaultLayout = QueryParameters.GetQueryParameter("layout").data ?? defaultLayout;
dryRun = QueryParameters.GetQueryParameter("test").data === "true";
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout];
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout] ?? AllKnownLayouts["all"];
console.log("Using layout: ", layoutToUse.name);
document.title = layoutToUse.title.InnerRender();
Locale.language.addCallback(e => {
document.title = layoutToUse.title.InnerRender();
})
// ----------------- Setup a few event sources -------------
@ -102,31 +94,19 @@ const fullScreenMessage = new UIEventSource<UIElement>(undefined);
// The latest element that was selected - used to generate the right UI at the right place
const selectedElement = new UIEventSource<{ feature: any }>(undefined);
function clean(str) : number{
if (str) {
const i = parseFloat(str);
if (isNaN(i)) {
return undefined;
}
return i;
}
return undefined;
}
const zoom = QueryParameters.GetQueryParameter("z");
const lat = QueryParameters.GetQueryParameter("lat");
const lon = QueryParameters.GetQueryParameter("lon");
const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({
zoom: clean(zoom.data) ?? layoutToUse.startzoom,
lat: clean(lat.data) ?? layoutToUse.startLat,
lon: clean(lon.data) ?? layoutToUse.startLon
zoom: Utils.asFloat(zoom.data) ?? layoutToUse.startzoom,
lat: Utils.asFloat(lat.data) ?? layoutToUse.startLat,
lon: Utils.asFloat(lon.data) ?? layoutToUse.startLon
});
locationControl.addCallback((latlonz) => {
zoom.setData(latlonz.zoom.toString());
lat.setData(latlonz.lat.toString().substr(0,6));
lon.setData(latlonz.lon.toString().substr(0,6));
})
@ -134,7 +114,9 @@ locationControl.addCallback((latlonz) => {
// ----------------- Prepare the important objects -----------------
const osmConnection = new OsmConnection(dryRun);
const osmConnection = new OsmConnection(
QueryParameters.GetQueryParameter("test").data === "true"
);
Locale.language.syncWith(osmConnection.GetPreference("language"));
@ -212,7 +194,7 @@ for (const layer of layoutToUse.layers) {
const layerUpdater = new LayerUpdater(bm, minZoom, flayers);
// --------------- Setting up filter ui --------
// --------------- Setting up layer selection ui --------
const closedFilterButton = `<button id="filter__button" class="filter__button filter__button--shadow">${Img.closedFilterButton}</button>`;
@ -229,13 +211,23 @@ const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLaye
const layerSelection = new Combine([`<p class="filter__label">Maplayers</p>`, new LayerSelection(flayers)]);
let layerControl = backgroundMapPicker;
if (flayers.length > 1) {
layerControl = new Combine([layerSelection, backgroundMapPicker);
layerControl = new Combine([layerSelection, backgroundMapPicker]);
}
new CheckBox(layerControl, closedFilterButton).AttachTo("filter__selection");
// ------------------ Setup various UI elements ------------
// ------------------ Setup various other UI elements ------------
document.title = layoutToUse.title.InnerRender();
Locale.language.addCallback(e => {
document.title = layoutToUse.title.InnerRender();
})
let languagePicker = new DropDown("", layoutToUse.supportedLanguages.map(lang => {
return {value: lang, shown: lang}
}
), Locale.language);
new StrayClickHandler(bm, selectedElement, fullScreenMessage, () => {
@ -250,7 +242,8 @@ new StrayClickHandler(bm, selectedElement, fullScreenMessage, () => {
);
/**
* Show the questions and information for the selected element on the fullScreen
* Show the questions and information for the selected element
* This is given to the div which renders fullscreen on mobile devices
*/
selectedElement.addCallback((feature) => {
const data = feature.feature.properties;
@ -278,13 +271,7 @@ selectedElement.addCallback((feature) => {
);
const pendingChanges = new PendingChanges(
changes, secondsTillChangesAreSaved,);
let languagePicker = new DropDown("", layoutToUse.supportedLanguages.map(lang => {
return {value: lang, shown: lang}
}
), Locale.language);
const pendingChanges = new PendingChanges(changes, secondsTillChangesAreSaved,);
new UserBadge(osmConnection.userDetails,
pendingChanges,
@ -294,12 +281,20 @@ new UserBadge(osmConnection.userDetails,
new SearchAndGo(bm).AttachTo("searchbox");
/*
new CollapseButton("messagesbox")
.AttachTo("collapseButton");
new WelcomeMessage(layoutToUse, osmConnection).AttachTo("messagesbox");
fullScreenMessage.setData(
new WelcomeMessage(layoutToUse, osmConnection)
);
.AttachTo("collapseButton");*/
const welcome = new WelcomeMessage(layoutToUse, osmConnection).onClick(() => {
});
const help = new FixedUiElement(`<div class='collapse-button-img'><img src='assets/help.svg' alt='collapse'></div>`);
new CheckBox(
new Combine([
new Combine(["<span class='collapse-button'>", help, "</span>"]),
welcome]),
new Combine(["<span class='open-button'>", help, "</span>"])
, true
).AttachTo("messagesbox")
new FullScreenMessageBoxHandler(fullScreenMessage, () => {
@ -324,9 +319,5 @@ osmConnection.registerActivateOsmAUthenticationClass();
new GeoLocationHandler(bm).AttachTo("geolocate-button");
// --------------- Send a ping to start various action --------
locationControl.ping();