From d9cae0fc46d01b2175e5c30a0d210a78e02713a5 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Mon, 7 Sep 2020 02:25:45 +0200 Subject: [PATCH] Add the possibility to load layouts from the OSM-wiki. What could possibly go wrong? --- Customizations/JSON/FromJSON.ts | 45 ++-- InitUiElements.ts | 204 ++++++++++++++++++ UI/CustomGenerator/CustomGeneratorPanel.ts | 2 +- UI/CustomGenerator/SavePanel.ts | 1 - UI/CustomGenerator/SharePanel.ts | 30 ++- UI/CustomGenerator/TagRenderingPanel.ts | 3 +- index.ts | 234 ++++----------------- 7 files changed, 297 insertions(+), 222 deletions(-) diff --git a/Customizations/JSON/FromJSON.ts b/Customizations/JSON/FromJSON.ts index 5ae62d4..c1c77f1 100644 --- a/Customizations/JSON/FromJSON.ts +++ b/Customizations/JSON/FromJSON.ts @@ -51,7 +51,7 @@ export class FromJSON { const tr = FromJSON.Translation; const layers = json.layers.map(FromJSON.Layer); - const roaming: TagDependantUIElementConstructor[] = json.roamingRenderings?.map(FromJSON.TagRendering) ?? []; + const roaming: TagDependantUIElementConstructor[] = json.roamingRenderings?.map((tr, i) => FromJSON.TagRendering(tr, "Roaming rendering "+i)) ?? []; for (const layer of layers) { layer.elementsToShow.push(...roaming); } @@ -95,15 +95,15 @@ export class FromJSON { return new Translation(tr); } - public static TagRendering(json: TagRenderingConfigJson | string): TagDependantUIElementConstructor { - return FromJSON.TagRenderingWithDefault(json, "", undefined); + public static TagRendering(json: TagRenderingConfigJson | string, propertyeName: string): TagDependantUIElementConstructor { + return FromJSON.TagRenderingWithDefault(json, propertyeName, undefined); } public static TagRenderingWithDefault(json: TagRenderingConfigJson | string, propertyName, defaultValue: string): TagDependantUIElementConstructor { if (json === undefined) { if(defaultValue !== undefined){ console.log(`Using default value ${defaultValue} for ${propertyName}`) - return FromJSON.TagRendering(defaultValue); + return FromJSON.TagRendering(defaultValue, propertyName); } throw `Tagrendering ${propertyName} is undefined...` } @@ -145,7 +145,7 @@ export class FromJSON { // Setup the freeform if (template === undefined) { console.error("Freeform.key is defined, but render is not. This is not allowed.", json) - throw "Freeform is defined, but render is not. This is not allowed." + throw `Freeform is defined in tagrendering ${propertyName}, but render is not. This is not allowed.` } freeform = { @@ -175,7 +175,7 @@ export class FromJSON { if(template === undefined && (mappings === undefined || mappings.length === 0)){ console.error("Empty tagrendering detected: no mappings nor template given", json) - throw "Empty tagrendering detected: no mappings nor template given" + throw `Empty tagrendering ${propertyName} detected: no mappings nor template given` } @@ -247,29 +247,35 @@ export class FromJSON { } public static Layer(json: LayerConfigJson | string): LayerDefinition { - if (typeof (json) === "string") { const cached = FromJSON.sharedLayers.get(json); if (cached) { return cached; } - - throw "Layer not yet loaded..." + throw `Layer ${json} not yet loaded...` } + try { + return FromJSON.LayerUncaught(json); + } catch (e) { + throw `While parsing layer ${json.id}: ${e}` + } + } + + private static LayerUncaught(json: LayerConfigJson): LayerDefinition { console.log("Parsing layer", json) const tr = FromJSON.Translation; const overpassTags = FromJSON.Tag(json.overpassTags); - const icon = FromJSON.TagRenderingWithDefault(json.icon, "layericon", "./assets/bug.svg"); + const icon = FromJSON.TagRenderingWithDefault(json.icon, "icon", "./assets/bug.svg"); const iconSize = FromJSON.TagRenderingWithDefault(json.iconSize, "iconSize", "40,40,center"); - const color = FromJSON.TagRenderingWithDefault(json.color, "layercolor", "#0000ff"); - const width = FromJSON.TagRenderingWithDefault(json.width, "layerwidth", "10"); - if(json.title === "Layer"){ + const color = FromJSON.TagRenderingWithDefault(json.color, "color", "#0000ff"); + const width = FromJSON.TagRenderingWithDefault(json.width, "width", "10"); + if (json.title === "Layer") { json.title = {}; } - let title= FromJSON.TagRendering(json.title); - - + let title = FromJSON.TagRendering(json.title, "Popup title"); + + let tagRenderingDefs = json.tagRenderings ?? []; let hasImageElement = false; for (const tagRenderingDef of tagRenderingDefs) { @@ -277,7 +283,7 @@ export class FromJSON { continue; } let str = tagRenderingDef as string; - if(tagRenderingDef.indexOf("images") >= 0 || str.indexOf("pictures") >= 0){ + if (tagRenderingDef.indexOf("images") >= 0 || str.indexOf("pictures") >= 0) { hasImageElement = true; break; } @@ -285,7 +291,7 @@ export class FromJSON { if (!hasImageElement) { tagRenderingDefs = ["images", ...tagRenderingDefs]; } - let tagRenderings = tagRenderingDefs.map(FromJSON.TagRendering); + let tagRenderings = tagRenderingDefs.map((tr, i) => FromJSON.TagRendering(tr, "Tagrendering #"+i)); const renderTags = {"id": "node/-1"} @@ -352,10 +358,7 @@ export class FromJSON { } ); - console.log("Parsed layer is ", layer); return layer; - } - } \ No newline at end of file diff --git a/InitUiElements.ts b/InitUiElements.ts index 8459afd..02c5575 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -22,10 +22,214 @@ import {QueryParameters} from "./Logic/Web/QueryParameters"; import {PersonalLayout} from "./Logic/PersonalLayout"; import {PersonalLayersPanel} from "./Logic/PersonalLayersPanel"; import Locale from "./UI/i18n/Locale"; +import {StrayClickHandler} from "./Logic/Leaflet/StrayClickHandler"; +import {SimpleAddUI} from "./UI/SimpleAddUI"; +import {CenterMessageBox} from "./UI/CenterMessageBox"; +import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; +import {TagUtils} from "./Logic/Tags"; +import {UserBadge} from "./UI/UserBadge"; +import {SearchAndGo} from "./UI/SearchAndGo"; +import {FullScreenMessageBox} from "./UI/FullScreenMessageBoxHandler"; +import {GeoLocationHandler} from "./Logic/Leaflet/GeoLocationHandler"; +import {Layout} from "./Customizations/Layout"; +import {LocalStorageSource} from "./Logic/Web/LocalStorageSource"; +import {FromJSON} from "./Customizations/JSON/FromJSON"; export class InitUiElements { + static InitAll(layoutToUse: Layout, layoutFromBase64: string, testing: UIEventSource, defaultLayout1: string ) { + if (layoutToUse === undefined) { + console.log("Incorrect layout") + new FixedUiElement("Error: incorrect layout " + defaultLayout1 + "
Go back").AttachTo("centermessage").onClick(() => { + }); + throw "Incorrect layout" + } + + console.log("Using layout: ", layoutToUse.id); + State.state = new State(layoutToUse); + + if (layoutToUse.hideFromOverview) { + State.state.osmConnection.GetPreference("hidden-theme-" + layoutToUse.id + "-enabled").setData("true"); + } + + if (layoutFromBase64 !== "false") { + State.state.layoutDefinition = location.hash.substr(1); + if (testing.data !== "true") { + State.state.osmConnection.OnLoggedIn(() => { + State.state.osmConnection.GetLongPreference("installed-theme-" + layoutToUse.id).setData(State.state.layoutDefinition); + }) + } else { + console.warn("NOT saving custom layout to OSM as we are tesing -> probably in an iFrame") + } + } + InitUiElements.InitBaseMap(); + + new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration + + function setupAllLayerElements() { + + // ------------- Setup the layers ------------------------------- + + InitUiElements.InitLayers(); + InitUiElements.InitLayerSelection(); + + + // ------------------ Setup various other UI elements ------------ + + + InitUiElements.OnlyIf(State.state.featureSwitchAddNew, () => { + + let presetCount = 0; + for (const layer of State.state.filteredLayers.data) { + for (const preset of layer.layerDef.presets) { + presetCount++; + } + } + if (presetCount == 0) { + return; + } + + + new StrayClickHandler(() => { + return new SimpleAddUI(); + } + ); + }); + + new CenterMessageBox().AttachTo("centermessage"); + + } + + setupAllLayerElements(); + + + function updateFavs() { + const favs = State.state.favouriteLayers.data ?? []; + + layoutToUse.layers = []; + for (const fav of favs) { + const layer = AllKnownLayouts.allLayers[fav]; + if (!!layer) { + layoutToUse.layers.push(layer); + } + + for (const layouts of State.state.installedThemes.data) { + for (const layer of layouts.layout.layers) { + if (typeof layer === "string") { + continue; + } + if (layer.id === fav) { + layoutToUse.layers.push(layer); + } + } + } + } + + setupAllLayerElements(); + State.state.layerUpdater.ForceRefresh(); + State.state.locationControl.ping(); + } + + if (layoutToUse === AllKnownLayouts.allSets[PersonalLayout.NAME]) { + + State.state.favouriteLayers.addCallback(updateFavs); + State.state.installedThemes.addCallback(updateFavs); + } + + + /** + * Show the questions and information for the selected element + * This is given to the div which renders fullscreen on mobile devices + */ + State.state.selectedElement.addCallback((feature) => { + if (feature?.feature?.properties === undefined) { + return; + } + const data = feature.feature.properties; + // Which is the applicable set? + for (const layer of layoutToUse.layers) { + if (typeof layer === "string") { + continue; + } + const applicable = layer.overpassFilter.matches(TagUtils.proprtiesToKV(data)); + if (applicable) { + // This layer is the layer that gives the questions + + const featureBox = new FeatureInfoBox( + feature.feature, + State.state.allElements.getElement(data.id), + layer.title, + layer.elementsToShow, + ); + + State.state.fullScreenMessage.setData(featureBox); + break; + } + } + } + ); + + InitUiElements.OnlyIf(State.state.featureSwitchUserbadge, () => { + new UserBadge().AttachTo('userbadge'); + }); + + InitUiElements.OnlyIf((State.state.featureSwitchSearch), () => { + new SearchAndGo().AttachTo("searchbox"); + }); + + + new FullScreenMessageBox(() => { + State.state.selectedElement.setData(undefined) + }).AttachTo("messagesboxmobile"); + + + InitUiElements.OnlyIf(State.state.featureSwitchWelcomeMessage, () => { + InitUiElements.InitWelcomeMessage() + }); + + if ((window != window.top && !State.state.featureSwitchWelcomeMessage.data) || State.state.featureSwitchIframe.data) { + const currentLocation = State.state.locationControl; + const url = `${window.location.origin}${window.location.pathname}?z=${currentLocation.data.zoom}&lat=${currentLocation.data.lat}&lon=${currentLocation.data.lon}`; + const content = ``; + new FixedUiElement(content).AttachTo("messagesbox"); + new FixedUiElement(content).AttachTo("help-button-mobile") + } + + + new GeoLocationHandler().AttachTo("geolocate-button"); + State.state.locationControl.ping(); + } + + + static LoadLayoutFromHash(userLayoutParam: UIEventSource) { + try { + let hash = location.hash.substr(1); + const layoutFromBase64 = userLayoutParam.data; + // layoutFromBase64 contains the name of the theme. This is partly to do tracking with goat counter + + const dedicatedHashFromLocalStorage = LocalStorageSource.Get("user-layout-" + layoutFromBase64.replace(" ", "_")); + if (dedicatedHashFromLocalStorage.data?.length < 10) { + dedicatedHashFromLocalStorage.setData(undefined); + } + + const hashFromLocalStorage = LocalStorageSource.Get("last-loaded-user-layout"); + if (hash.length < 10) { + hash = dedicatedHashFromLocalStorage.data ?? hashFromLocalStorage.data; + } else { + console.log("Saving hash to local storage") + hashFromLocalStorage.setData(hash); + dedicatedHashFromLocalStorage.setData(hash); + } + const layoutToUse = FromJSON.FromBase64(hash.substr(1)); + userLayoutParam.setData(layoutToUse.id); + return layoutToUse; + } catch (e) { + new FixedUiElement("Error: could not parse the custom layout:
" + e).AttachTo("centermessage"); + throw e; + } + } + static OnlyIf(featureSwitch: UIEventSource, callback: () => void) { featureSwitch.addCallback(() => { diff --git a/UI/CustomGenerator/CustomGeneratorPanel.ts b/UI/CustomGenerator/CustomGeneratorPanel.ts index fe83784..86a4ece 100644 --- a/UI/CustomGenerator/CustomGeneratorPanel.ts +++ b/UI/CustomGenerator/CustomGeneratorPanel.ts @@ -86,7 +86,7 @@ export default class CustomGeneratorPanel extends UIElement { }, { header: "", - content: new SharePanel(es, liveUrl) + content: new SharePanel(es, liveUrl, userDetails) } ]) } diff --git a/UI/CustomGenerator/SavePanel.ts b/UI/CustomGenerator/SavePanel.ts index fd52edf..9367621 100644 --- a/UI/CustomGenerator/SavePanel.ts +++ b/UI/CustomGenerator/SavePanel.ts @@ -7,7 +7,6 @@ import {OsmConnection} from "../../Logic/Osm/OsmConnection"; import {FixedUiElement} from "../Base/FixedUiElement"; import {TextField} from "../Input/TextField"; import {SubtleButton} from "../Base/SubtleButton"; -import {FromJSON} from "../../Customizations/JSON/FromJSON"; export default class SavePanel extends UIElement { private json: UIElement; diff --git a/UI/CustomGenerator/SharePanel.ts b/UI/CustomGenerator/SharePanel.ts index 3b41b04..68527d0 100644 --- a/UI/CustomGenerator/SharePanel.ts +++ b/UI/CustomGenerator/SharePanel.ts @@ -3,22 +3,50 @@ import {UIEventSource} from "../../Logic/UIEventSource"; import {LayoutConfigJson} from "../../Customizations/JSON/LayoutConfigJson"; import Combine from "../Base/Combine"; import {VariableUiElement} from "../Base/VariableUIElement"; +import {UserDetails} from "../../Logic/Osm/OsmConnection"; export default class SharePanel extends UIElement { private _config: UIEventSource; private _panel: UIElement; - constructor(config: UIEventSource, liveUrl: UIEventSource) { + constructor(config: UIEventSource, liveUrl: UIEventSource, userDetails: UserDetails) { super(undefined); this._config = config; + const proposedName = `User:${userDetails.name}/${config.data.id}` + const proposedNameEnc = encodeURIComponent(`wiki:User:${userDetails.name}/${config.data.id}`) this._panel = new Combine([ "

share

", "Share the following link with friends:
", new VariableUiElement(liveUrl.map(url => `${url}`)), + "

Publish on OSM Wiki

", + "In the list of 'hacks upon hacks to make MapComplete work', it is now possible to put the JSON-file onto a Wikipage*.
" + + "This is a very stable and very well-tested solution. Using wikipages as source control! What could possibly go wrong???? /s

", + + "Why to publish the layout as a wikipage?", + "
    ", + ...["If something breaks, it can be fixed centrally", + "If someone has a remark about your preset, the talk page can be used to point this out and discuss the preset", + "In case of a grave error, everyone can step in to fix the prest"].map(li => `
  • ${li}
  • `), + "
", + + "In order to make this work:", + "
    ", + + ...[`Create a new page on the OSM-wiki, e.g. ${proposedName}`, + "Click 'create page'", + "Type <nowiki>, a few newlines and </nowiki>", + "Copy the json configuration from the 'save-tab', paste it between the 'nowiki'-tags in the Wiki", + "Click 'save' to save the wiki page", + "Share the link with the url parameter userlayout=wiki:YOURWIKIPAGE, e.g. " + + `https://pietervdvn.github.io/MapComplete/index.html?userlayout=${proposedNameEnc}` + ].map(li => `
  1. ${li}
  2. `), + + "
", + "(* This has made a lot of people very angry and been widely regarded as a bad move.)", "" ]); } diff --git a/UI/CustomGenerator/TagRenderingPanel.ts b/UI/CustomGenerator/TagRenderingPanel.ts index 5d1dade..a51ad55 100644 --- a/UI/CustomGenerator/TagRenderingPanel.ts +++ b/UI/CustomGenerator/TagRenderingPanel.ts @@ -88,7 +88,8 @@ export default class TagRenderingPanel extends InputElementMappings", setting(new MultiInput<{ if: AndOrTagConfigJson, then: (string | any), hideInAnswer?: boolean }>("Add a mapping", () => ({if: undefined, then: undefined}), - () => new MappingInput(languages, options?.disableQuestions ?? false)), "mappings", + () => new MappingInput(languages, options?.disableQuestions ?? false), + undefined, {allowMovement: true}), "mappings", "If a tag matches, then show the first respective text", "") ]; diff --git a/index.ts b/index.ts index bcedad6..a8a89d3 100644 --- a/index.ts +++ b/index.ts @@ -1,23 +1,12 @@ import {TagRendering} from "./Customizations/TagRendering"; -import {UserBadge} from "./UI/UserBadge"; -import {CenterMessageBox} from "./UI/CenterMessageBox"; -import {TagUtils} from "./Logic/Tags"; -import {FeatureInfoBox} from "./UI/FeatureInfoBox"; -import {SimpleAddUI} from "./UI/SimpleAddUI"; -import {SearchAndGo} from "./UI/SearchAndGo"; import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; import {Layout} from "./Customizations/Layout"; import {FixedUiElement} from "./UI/Base/FixedUiElement"; import {InitUiElements} from "./InitUiElements"; -import {StrayClickHandler} from "./Logic/Leaflet/StrayClickHandler"; -import {GeoLocationHandler} from "./Logic/Leaflet/GeoLocationHandler"; -import {State} from "./State"; import {QueryParameters} from "./Logic/Web/QueryParameters"; -import {LocalStorageSource} from "./Logic/Web/LocalStorageSource"; -import {PersonalLayout} from "./Logic/PersonalLayout"; -import {FromJSON} from "./Customizations/JSON/FromJSON"; -import {FullScreenMessageBox} from "./UI/FullScreenMessageBoxHandler"; import {UIEventSource} from "./Logic/UIEventSource"; +import * as $ from "jquery"; +import {FromJSON} from "./Customizations/JSON/FromJSON"; TagRendering.injectFunction(); @@ -73,193 +62,44 @@ let layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout.toLowerCase()] ? const userLayoutParam = QueryParameters.GetQueryParameter("userlayout", "false"); -const layoutFromBase64 = userLayoutParam.data; -if (layoutFromBase64 !== "false") { - try { - // layoutFromBase64 contains the name of the theme. This is partly to do tracking with goat counter +const layoutFromBase64 = decodeURIComponent(userLayoutParam.data); +console.log(layoutFromBase64); +if (layoutFromBase64.startsWith("wiki:")) { + console.log("Downloading map theme from the wiki"); + const themeName = layoutFromBase64.substr("wiki:".length); + new FixedUiElement(`Downloading ${themeName} from the wiki...`) + .AttachTo("centermessage"); + const cleanUrl = `https://wiki.openstreetmap.org/wiki/${themeName}`; + const url = `https://cors-anywhere.herokuapp.com/` + cleanUrl; // VERY SAFE AND HACKER-PROOF! - const dedicatedHashFromLocalStorage = LocalStorageSource.Get("user-layout-" + layoutFromBase64.replace(" ", "_")); - if(dedicatedHashFromLocalStorage.data?.length < 10){ - dedicatedHashFromLocalStorage.setData(undefined); - } - - const hashFromLocalStorage = LocalStorageSource.Get("last-loaded-user-layout"); - if (hash.length < 10) { - hash = dedicatedHashFromLocalStorage.data ?? hashFromLocalStorage.data; - } else { - console.log("Saving hash to local storage") - hashFromLocalStorage.setData(hash); - dedicatedHashFromLocalStorage.setData(hash); - } - layoutToUse = FromJSON.FromBase64(hash.substr(1)); - userLayoutParam.setData(layoutToUse.id); - } catch (e) { - new FixedUiElement("Error: could not parse the custom layout:
"+e).AttachTo("centermessage"); - throw e; - } -} - - -if (layoutToUse === undefined) { - console.log("Incorrect layout") - new FixedUiElement("Error: incorrect layout " + defaultLayout + "
Go back").AttachTo("centermessage").onClick(() => { - }); - throw "Incorrect layout" -} - -console.log("Using layout: ", layoutToUse.id); - -State.state = new State(layoutToUse); - -if (layoutToUse.hideFromOverview) { - State.state.osmConnection.GetPreference("hidden-theme-" + layoutToUse.id + "-enabled").setData("true"); -} - -if (layoutFromBase64 !== "false") { - State.state.layoutDefinition = hash.substr(1); - if (!testing) { - State.state.osmConnection.OnLoggedIn(() => { - State.state.osmConnection.GetLongPreference("installed-theme-" + layoutToUse.id).setData(State.state.layoutDefinition); - }) - }else{ - console.warn("NOT saving custom layout to OSM as we are tesing -> probably in an iFrame") - } -} -InitUiElements.InitBaseMap(); - -new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration - -function setupAllLayerElements() { - - // ------------- Setup the layers ------------------------------- - - InitUiElements.InitLayers(); - InitUiElements.InitLayerSelection(); - - - // ------------------ Setup various other UI elements ------------ - - - InitUiElements.OnlyIf(State.state.featureSwitchAddNew, () => { - - let presetCount = 0; - for (const layer of State.state.filteredLayers.data) { - for (const preset of layer.layerDef.presets) { - presetCount++; + $.ajax({ + url: url, + dataType: 'xml', + success: function (data) { + const layoutJson = data.querySelector('[id="bodyContent"]') + .querySelector('[class="mw-parser-output"]') + .children[0] + .firstChild.textContent; + try { + console.log("DOWNLOADED:",layoutJson); + const layout = FromJSON.LayoutFromJSON(JSON.parse(layoutJson)); + InitUiElements.InitAll(layout, layoutFromBase64, testing, layoutFromBase64); + } catch (e) { + new FixedUiElement(`${themeName} is invalid:
${e}`) + .SetClass("clickable") + .AttachTo("centermessage"); + throw e; } - } - if (presetCount == 0) { - return; - } - - - new StrayClickHandler(() => { - return new SimpleAddUI(); - } - ); + }, + }).fail(e => { + new FixedUiElement(`${themeName} is invalid:
Could not download - wrong URL?`) + .SetClass("clickable") + .AttachTo("centermessage"); }); - new CenterMessageBox().AttachTo("centermessage"); - -} - -setupAllLayerElements(); - - -function updateFavs() { - const favs = State.state.favouriteLayers.data ?? []; - - layoutToUse.layers = []; - for (const fav of favs) { - const layer = AllKnownLayouts.allLayers[fav]; - if (!!layer) { - layoutToUse.layers.push(layer); - } - - for (const layouts of State.state.installedThemes.data) { - for (const layer of layouts.layout.layers) { - if (typeof layer === "string") { - continue; - } - if (layer.id === fav) { - layoutToUse.layers.push(layer); - } - } - } +} else { + if (layoutFromBase64 !== "false") { + layoutToUse = InitUiElements.LoadLayoutFromHash(userLayoutParam); } - - setupAllLayerElements(); - State.state.layerUpdater.ForceRefresh(); - State.state.locationControl.ping(); + InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout); } - -if (layoutToUse === AllKnownLayouts.allSets[PersonalLayout.NAME]) { - - State.state.favouriteLayers.addCallback(updateFavs); - State.state.installedThemes.addCallback(updateFavs); -} - - -/** - * Show the questions and information for the selected element - * This is given to the div which renders fullscreen on mobile devices - */ -State.state.selectedElement.addCallback((feature) => { - if (feature?.feature?.properties === undefined) { - return; - } - const data = feature.feature.properties; - // Which is the applicable set? - for (const layer of layoutToUse.layers) { - if (typeof layer === "string") { - continue; - } - const applicable = layer.overpassFilter.matches(TagUtils.proprtiesToKV(data)); - if (applicable) { - // This layer is the layer that gives the questions - - const featureBox = new FeatureInfoBox( - feature.feature, - State.state.allElements.getElement(data.id), - layer.title, - layer.elementsToShow, - ); - - State.state.fullScreenMessage.setData(featureBox); - break; - } - } - } -); - -InitUiElements.OnlyIf(State.state.featureSwitchUserbadge, () => { - new UserBadge().AttachTo('userbadge'); -}); - -InitUiElements.OnlyIf((State.state.featureSwitchSearch), () => { - new SearchAndGo().AttachTo("searchbox"); -}); - - -new FullScreenMessageBox(() => { - State.state.selectedElement.setData(undefined) -}).AttachTo("messagesboxmobile"); - - - -InitUiElements.OnlyIf(State.state.featureSwitchWelcomeMessage, () => { - InitUiElements.InitWelcomeMessage() -}); - -if ((window != window.top && !State.state.featureSwitchWelcomeMessage.data) || State.state.featureSwitchIframe.data) { - const currentLocation = State.state.locationControl; - const url = `${window.location.origin}${window.location.pathname}?z=${currentLocation.data.zoom}&lat=${currentLocation.data.lat}&lon=${currentLocation.data.lon}`; - const content = ``; - new FixedUiElement(content).AttachTo("messagesbox"); - new FixedUiElement(content).AttachTo("help-button-mobile") -} - - - -new GeoLocationHandler().AttachTo("geolocate-button"); -State.state.locationControl.ping(); \ No newline at end of file