From 6d5f4ade2507fdc49d6954b738a61fa983ac862e Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sat, 12 Sep 2020 23:15:17 +0200 Subject: [PATCH] Fixes and simplification of the CSS --- Customizations/JSON/FromJSON.ts | 10 +-- Customizations/OnlyShowIf.ts | 8 --- InitUiElements.ts | 14 +++-- Logic/FilteredLayer.ts | 4 -- Logic/ImageSearcher.ts | 18 +----- Logic/Leaflet/StrayClickHandler.ts | 4 -- Logic/Tags.ts | 1 - UI/Base/Combine.ts | 48 ++++---------- UI/Base/TabbedComponent.ts | 10 +-- UI/Base/VariableUIElement.ts | 5 +- UI/FullScreenMessageBoxHandler.ts | 47 +++++++++++--- UI/Image/ImageCarousel.ts | 98 ++++++++++++++--------------- UI/Image/ImageCarouselWithUpload.ts | 13 ---- UI/ImageUploadFlow.ts | 20 +++--- UI/Input/CheckBox.ts | 9 ++- UI/Input/TextField.ts | 14 ++--- UI/SearchAndGo.ts | 19 ++---- UI/SlideShow.ts | 20 +----- UI/TagRendering.ts | 10 +-- UI/UIElement.ts | 68 ++++++++------------ UI/i18n/Translation.ts | 7 +-- customGenerator.html | 1 + index.css | 84 +------------------------ test.ts | 3 +- 24 files changed, 191 insertions(+), 344 deletions(-) diff --git a/Customizations/JSON/FromJSON.ts b/Customizations/JSON/FromJSON.ts index 67c7bb3..193f97c 100644 --- a/Customizations/JSON/FromJSON.ts +++ b/Customizations/JSON/FromJSON.ts @@ -88,23 +88,25 @@ export class FromJSON { return layout; } - public static Translation(json: string | any): string | Translation { + public static Translation(json: string | any): Translation { if (json === undefined) { return undefined; } if (typeof (json) === "string") { - return json; + return new Translation({"*": json}); } const tr = {}; let keyCount = 0; for (let key in json) { - keyCount ++; + keyCount++; tr[key] = json[key]; // I'm doing this wrong, I know } if(keyCount == 0){ return undefined; } - return new Translation(tr); + const transl = new Translation(tr); + transl.addCallback(latest => console.log("tr callback changed to", latest)); + return transl; } public static TagRendering(json: TagRenderingConfigJson | string, propertyeName: string): TagDependantUIElementConstructor { diff --git a/Customizations/OnlyShowIf.ts b/Customizations/OnlyShowIf.ts index 0fe632d..6e3a3a0 100644 --- a/Customizations/OnlyShowIf.ts +++ b/Customizations/OnlyShowIf.ts @@ -103,12 +103,4 @@ class OnlyShowIf extends UIElement implements TagDependantUIElement { return this._embedded.IsQuestioning(); } - Activate(): UIElement { - this._embedded.Activate(); - return this; - } - - Update(): void { - this._embedded.Update(); - } } \ No newline at end of file diff --git a/InitUiElements.ts b/InitUiElements.ts index 22c4601..ce77ec2 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -199,6 +199,10 @@ export class InitUiElements { new GeoLocationHandler().AttachTo("geolocate-button"); State.state.locationControl.ping(); + + // This 'leaks' the global state via the window object, useful for debugging + // @ts-ignore + window.mapcomplete_state = State.state; } @@ -255,7 +259,8 @@ export class InitUiElements { const tabs = [ {header: Img.AsImageElement(layoutToUse.icon), content: welcome}, - {header: ``, content: Translations.t.general.openStreetMapIntro}, + {header: ``, content: + Translations.t.general.openStreetMapIntro}, ] @@ -289,9 +294,8 @@ export class InitUiElements { ); - const fullOptions = new TabbedComponent(tabs, State.state.welcomeMessageOpenedTab); - fullOptions.ListenTo(State.state.osmConnection.userDetails); - return fullOptions; + return new TabbedComponent(tabs, State.state.welcomeMessageOpenedTab) + .ListenTo(State.state.osmConnection.userDetails); } @@ -313,7 +317,7 @@ export class InitUiElements { const openedTime = new Date().getTime(); State.state.locationControl.addCallback(() => { if (new Date().getTime() - openedTime < 15 * 1000) { - // Don't autoclose the first 15 secs + // Don't autoclose the first 15 secs when the map is moving return; } checkbox.isEnabled.setData(false); diff --git a/Logic/FilteredLayer.ts b/Logic/FilteredLayer.ts index 7e09e25..280d130 100644 --- a/Logic/FilteredLayer.ts +++ b/Logic/FilteredLayer.ts @@ -240,14 +240,12 @@ export class FilteredLayer { let content = undefined; marker.bindPopup(popup) .on("popupopen", () => { - if (content === undefined) { uiElement = self._showOnPopup(eventSource, feature); // Lazily create the content content = uiElement.Render(); } popup.setContent(content); - uiElement.Activate(); uiElement.Update(); }); return marker; @@ -290,8 +288,6 @@ export class FilteredLayer { .setLatLng(e.latlng) .openOn(State.state.bm.map); - uiElement.Update(); - uiElement.Activate(); L.DomEvent.stop(e); // Marks the event as consumed }); } diff --git a/Logic/ImageSearcher.ts b/Logic/ImageSearcher.ts index 2efe9f1..700e7a5 100644 --- a/Logic/ImageSearcher.ts +++ b/Logic/ImageSearcher.ts @@ -27,7 +27,6 @@ export class ImageSearcher extends UIEventSource { private readonly _tags: UIEventSource; private readonly _wdItem = new UIEventSource(""); private readonly _commons = new UIEventSource(""); - private _activated: boolean = false; public _deletedImages = new UIEventSource([]); @@ -81,7 +80,7 @@ export class ImageSearcher extends UIEventSource { } } }); - + this._tags.addCallbackAndRun(() => self.LoadImages()); } @@ -121,25 +120,14 @@ export class ImageSearcher extends UIEventSource { return; } console.log("Deleting image...", key, " --> ", url); - State.state.changes.addTag(this._tags.data.id, new Tag(key, "")); this._deletedImages.data.push(url); this._deletedImages.ping(); + this.ping(); + State.state?.changes?.addTag(this._tags.data.id, new Tag(key, "")); } - public Activate() { - if (this._activated) { - return; - } - this._activated = true; - this.LoadImages(); - const self = this; - this._tags.addCallback(() => self.LoadImages()); - } private LoadImages(): void { - if (!this._activated) { - return; - } const imageTag = this._tags.data.image; if (imageTag !== undefined) { const bareImages = imageTag.split(";"); diff --git a/Logic/Leaflet/StrayClickHandler.ts b/Logic/Leaflet/StrayClickHandler.ts index 308ba11..e8275c3 100644 --- a/Logic/Leaflet/StrayClickHandler.ts +++ b/Logic/Leaflet/StrayClickHandler.ts @@ -31,16 +31,12 @@ export class StrayClickHandler { }); const uiElement = uiToShow(); const popup = L.popup().setContent(uiElement.Render()); - uiElement.Update(); - uiElement.Activate(); self._lastMarker.addTo(map); self._lastMarker.bindPopup(popup); self._lastMarker.on("click", () => { State.state.fullScreenMessage.setData(self._uiToShow()); }); - uiElement.Update(); - uiElement.Activate(); }); State.state.selectedElement.addCallback(() => { diff --git a/Logic/Tags.ts b/Logic/Tags.ts index a4727f3..0eecb48 100644 --- a/Logic/Tags.ts +++ b/Logic/Tags.ts @@ -465,7 +465,6 @@ export class TagUtils { let leftoverTag = undefined; if (keyValues[freeformKey] !== undefined && keyValues[freeformKey].length !== 0) { leftoverTag = new Tag(freeformKey, keyValues[freeformKey].join(";")); - console.log("Leftovers are ", leftoverTag) if (freeformExtraTags !== undefined) { leftoverTag = new And([ leftoverTag, diff --git a/UI/Base/Combine.ts b/UI/Base/Combine.ts index 6dd9fda..275da44 100644 --- a/UI/Base/Combine.ts +++ b/UI/Base/Combine.ts @@ -1,45 +1,23 @@ import {UIElement} from "../UIElement"; -import Translations from "../i18n/Translations"; +import {FixedUiElement} from "./FixedUiElement"; +import {Utils} from "../../Utils"; export default class Combine extends UIElement { - private readonly uiElements: (string | UIElement)[]; - private readonly className: string = undefined; + private readonly uiElements: UIElement[]; - constructor(uiElements: (string | UIElement)[], className: string = undefined) { - super(undefined); - this.dumbMode = false; - this.className = className; - this.uiElements = uiElements; - if (className) { - console.error("Deprecated used of className") - } + constructor(uiElements: (string | UIElement)[]) { + super(); + this.uiElements = Utils.NoNull(uiElements) + .map(el => { + if (typeof el === "string") { + return new FixedUiElement(el); + } + return el; + }); } InnerRender(): string { - let elements = ""; - for (const element of this.uiElements) { - if(element === undefined){ - continue; - } - - if (element instanceof UIElement) { - elements += element.Render(); - } else { - elements += element; - } - } - if(this.className !== undefined){ - elements = `${elements}`; - } - - return elements; + return this.uiElements.map(ui => ui.Render()).join(""); } - InnerUpdate(htmlElement: HTMLElement) { - for (const element of this.uiElements) { - if (element instanceof UIElement) { - element.Update(); - } - } - } } \ No newline at end of file diff --git a/UI/Base/TabbedComponent.ts b/UI/Base/TabbedComponent.ts index b7c5d47..e7204db 100644 --- a/UI/Base/TabbedComponent.ts +++ b/UI/Base/TabbedComponent.ts @@ -13,7 +13,9 @@ export class TabbedComponent extends UIElement { for (let i = 0; i < elements.length; i++) { let element = elements[i]; this.headers.push(Translations.W(element.header).onClick(() => self._source.setData(i))); - this.content.push(Translations.W(element.content)); + const content = Translations.W(element.content) + this.ListenTo(content) + this.content.push(content); } } @@ -35,10 +37,4 @@ export class TabbedComponent extends UIElement { return headerBar + "
" + (content?.Render() ?? "") + "
"; } - protected InnerUpdate(htmlElement: HTMLElement) { - - super.InnerUpdate(htmlElement); - this.content[this._source.data].Update(); - } - } \ No newline at end of file diff --git a/UI/Base/VariableUIElement.ts b/UI/Base/VariableUIElement.ts index 40c18c7..6e5e246 100644 --- a/UI/Base/VariableUIElement.ts +++ b/UI/Base/VariableUIElement.ts @@ -3,13 +3,10 @@ import {UIEventSource} from "../../Logic/UIEventSource"; export class VariableUiElement extends UIElement { private _html: UIEventSource; - private _innerUpdate: (htmlElement: HTMLElement) => void; - constructor(html: UIEventSource, innerUpdate : ((htmlElement : HTMLElement) => void) = undefined) { + constructor(html: UIEventSource) { super(html); this._html = html; - this._innerUpdate = innerUpdate; - } InnerRender(): string { diff --git a/UI/FullScreenMessageBoxHandler.ts b/UI/FullScreenMessageBoxHandler.ts index c1cb34b..2490e40 100644 --- a/UI/FullScreenMessageBoxHandler.ts +++ b/UI/FullScreenMessageBoxHandler.ts @@ -8,25 +8,40 @@ import Combine from "./Base/Combine"; */ export class FullScreenMessageBox extends UIElement { + private static readonly _toTheMap_height : string = "5em"; + private _uielement: UIElement; - private returnToTheMap: UIElement; + private readonly returnToTheMap: UIElement; constructor(onClear: (() => void)) { super(undefined); const self = this; - State.state.fullScreenMessage.addCallback(uielement => { - return self._uielement = uielement?.SetClass("messagesboxmobile-scroll")?.Activate(); + + State.state.fullScreenMessage.addCallbackAndRun(uiElement => { + this._uielement = new Combine([State.state.fullScreenMessage.data]).SetStyle( + "display:block;"+ + "padding: 1em;"+ + "padding-bottom:5em;"+ + `margin-bottom:${FullScreenMessageBox._toTheMap_height};`+ + "box-sizing:border-box;"+ + `height:calc(100vh - ${FullScreenMessageBox._toTheMap_height});`+ + "overflow-y: auto;" + + "background:white;" + + ); }); - this._uielement = State.state.fullScreenMessage.data; + this.ListenTo(State.state.fullScreenMessage); + this.HideOnEmpty(true); State.state.fullScreenMessage.addCallback(latestData => { if (latestData === undefined) { location.hash = ""; } else { + // The 'hash' makes sure a new piece of history is added. This makes the 'back-button' on android remove the popup location.hash = "#element"; } this.Update(); @@ -42,8 +57,23 @@ export class FullScreenMessageBox extends UIElement { } } - this.returnToTheMap = Translations.t.general.returnToTheMap.Clone() - .SetClass("to-the-map") + this.returnToTheMap = + new Combine([Translations.t.general.returnToTheMap.Clone().SetStyle("font-size:xx-large")]) + .SetStyle("background:#7ebc6f;" + + "position: fixed;" + + "z-index: 10000;" + + "bottom: 0;" + + "left: 0;" + + `height: ${FullScreenMessageBox._toTheMap_height};` + + "width: 100vw;" + + "color: white;" + + "font-weight: bold;" + + "pointer-events: all;" + + "cursor: pointer;" + + "padding-top: 1.2em;" + + "text-align: center;" + + "padding-bottom: 1.2em;" + + "box-sizing:border-box") .onClick(() => { console.log("Returning...") State.state.fullScreenMessage.setData(undefined); @@ -55,10 +85,11 @@ export class FullScreenMessageBox extends UIElement { InnerRender(): string { - if (this._uielement === undefined) { + if (State.state.fullScreenMessage.data === undefined) { return ""; } - return new Combine([this._uielement, this.returnToTheMap]).Render(); + return new Combine([this._uielement, this.returnToTheMap]) + .Render(); } diff --git a/UI/Image/ImageCarousel.ts b/UI/Image/ImageCarousel.ts index e568266..6c80557 100644 --- a/UI/Image/ImageCarousel.ts +++ b/UI/Image/ImageCarousel.ts @@ -49,6 +49,7 @@ export class ImageCarousel extends TagDependantUIElement { private readonly _uiElements: UIEventSource; private readonly _deleteButton: UIElement; + private readonly _confirmation: UIElement; constructor(tags: UIEventSource, osmConnection: OsmConnection = undefined) { super(tags); @@ -76,74 +77,78 @@ export class ImageCarousel extends TagDependantUIElement { return false; } return self.searcher.IsDeletable(self.searcher.data[i]); - }, [this.searcher, osmConnection?.userDetails]); + }, [this.searcher, osmConnection?.userDetails, this.slideshow._currentSlide]); const isDeleted: UIEventSource = this.slideshow._currentSlide.map((i: number) => { - return self.searcher._deletedImages.data.indexOf(self.searcher.data[i]) >= 0; - }, [this.searcher, this.searcher._deletedImages]); - - this.slideshow._currentSlide.addCallback(() => { - showDeleteButton.ping(); // This pings the showDeleteButton, which indicates that it has to hide it's subbuttons - }) - - - const deleteCurrent = () => { - self.searcher.Delete(self.searcher.data[self.slideshow._currentSlide.data]); - } - + const isDeleted = self.searcher._deletedImages.data.indexOf(self.searcher.data[i]) >= 0; + console.log("Now deleted: ", i, isDeleted); + return isDeleted; + }, [this.searcher, this.searcher._deletedImages, this.slideshow._currentSlide]); const style = ";padding:0.4em;height:2em;padding: 0.4em; font-weight:bold;"; const backButton = Translations.t.image.dontDelete .SetStyle("background:black;border-radius:0.4em 0.4em 0 0" + style) - const deleteButton = Translations.t.image.doDelete - .SetStyle("background:#ff8c8c;border-radius:0 0 0.4em 0.4em" + style) - .onClick(deleteCurrent); + const deleteButton = + Translations.t.image.doDelete + .SetStyle("background:#ff8c8c;border-radius:0 0 0.4em 0.4em" + style); + this._confirmation = deleteButton; + + const isDeletedBadge = Translations.t.image.isDeleted + .SetStyle("display:block;" + + "background-color: black;color:white;padding:0.4em;border-radius:0.4em"); + + const confirmDialog = new Combine([ + backButton, + deleteButton] + ).SetStyle("display:flex;" + + "flex-direction:column;" + + "background:black;" + + "color:white;" + + "border-radius:0.5em;" + + "width:max-content;" + + "height:min-content;"); + + const smallDeleteButton = new FixedUiElement("") + .SetStyle("display:block;" + + "width: 1.5em;" + + "height: 1.5em;" + + "padding: 0.5em;" + + "border-radius: 3em;" + + "background-color: black;") const deleteButtonCheckbox = new CheckBox( - new Combine([ - backButton, - deleteButton] - ).SetStyle("display:flex;" + - "flex-direction:column;" + - "background:black;" + - "color:white;" + - "border-radius:0.5em;" + - "width:max-content;" + - "height:min-content;"), + confirmDialog, new VariableUiElement( showDeleteButton.map(showDelete => { if (isDeleted.data) { - return Translations.t.image.isDeleted - .SetStyle("display:block;" + - "background-color: black;color:white;padding:0.4em;border-radius:0.4em").Render() + return isDeletedBadge.Render() } if (!showDelete) { return ""; } - return new FixedUiElement("") - .SetStyle("display:block;" + - "width: 1.5em;" + - "height: 1.5em;" + - "padding: 0.5em;" + - "border-radius: 3em;" + - "background-color: black;").Render(); + return smallDeleteButton.Render(); }, [this.searcher._deletedImages, isDeleted] ))); + deleteButton.onClick(() => { + console.log("Deleting image..."); + deleteButtonCheckbox.isEnabled.setData(false); + deleteButtonCheckbox.Update(); + self.searcher.Delete(self.searcher.data[self.slideshow._currentSlide.data]); + }); + + isDeleted.addCallback(isD => { + if(isD){ + deleteButtonCheckbox.isEnabled.setData(false); + } + }) + this._deleteButton = deleteButtonCheckbox; this._deleteButton.SetStyle( "position:absolute;display:block;top:1em;left:5em;z-index: 7000;width:min-content;height:min-content;" ) - this.slideshow._currentSlide.addCallback(() => { - deleteButtonCheckbox.isEnabled.setData(false) - }) - - this.searcher._deletedImages.addCallback(() => { - this.slideshow._currentSlide.ping(); - }) - } @@ -171,10 +176,5 @@ export class ImageCarousel extends TagDependantUIElement { } - Activate() { - super.Activate(); - this.searcher.Activate(); - return this; - } } \ No newline at end of file diff --git a/UI/Image/ImageCarouselWithUpload.ts b/UI/Image/ImageCarouselWithUpload.ts index 99e84ed..eaa6d2c 100644 --- a/UI/Image/ImageCarouselWithUpload.ts +++ b/UI/Image/ImageCarouselWithUpload.ts @@ -50,19 +50,6 @@ class ImageCarouselWithUpload extends TagDependantUIElement { this._pictureUploader.Render(); } - Activate() { - super.Activate(); - this._imageElement.Activate(); - this._pictureUploader.Activate(); - return this; - } - - Update() { - super.Update(); - this._imageElement.Update(); - this._pictureUploader.Update(); - } - IsKnown(): boolean { return true; } diff --git a/UI/ImageUploadFlow.ts b/UI/ImageUploadFlow.ts index edecac4..3be2d40 100644 --- a/UI/ImageUploadFlow.ts +++ b/UI/ImageUploadFlow.ts @@ -1,16 +1,11 @@ import {UIElement} from "./UIElement"; import $ from "jquery" -import {UserDetails} from "../Logic/Osm/OsmConnection"; import {DropDown} from "./Input/DropDown"; -import {VariableUiElement} from "./Base/VariableUIElement"; import Translations from "./i18n/Translations"; -import {fail} from "assert"; import Combine from "./Base/Combine"; -import {VerticalCombine} from "./Base/VerticalCombine"; import {State} from "../State"; import {UIEventSource} from "../Logic/UIEventSource"; import {Imgur} from "../Logic/Web/Imgur"; -import {SubtleButton} from "./Base/SubtleButton"; export class ImageUploadFlow extends UIElement { private _licensePicker: UIElement; @@ -107,9 +102,20 @@ export class ImageUploadFlow extends UIElement { const label = new Combine([ " ", Translations.t.image.addPicture - .SetStyle("width:max-content;font-size: 28px;font-weight: bold;float: left;margin-top: 4px;padding-top: 4px;padding-bottom: 4px;padding-left: 13px;"), + .SetStyle("width:max-content;font-size: 28px;" + + "font-weight: bold;" + + "float: left;" + + "margin-top: 4px;" + + "padding-top: 4px;" + + "padding-bottom: 4px;" + + "padding-left: 13px;"), - ]).SetStyle(" display: flex;cursor:pointer;padding: 0.5em;border-radius: 1em;border: 3px solid black;box-sizing:border-box;") + ]).SetStyle(" display: flex;" + + "cursor:pointer;" + + "padding: 0.5em;" + + "border-radius: 1em;" + + "border: 3px solid black;" + + "box-sizing:border-box;") const actualInputElement = ``; diff --git a/UI/Input/CheckBox.ts b/UI/Input/CheckBox.ts index 20357e6..85baba4 100644 --- a/UI/Input/CheckBox.ts +++ b/UI/Input/CheckBox.ts @@ -1,20 +1,19 @@ import {UIElement} from "../UIElement"; -import { FilteredLayer } from "../../Logic/FilteredLayer"; import Translations from "../../UI/i18n/Translations"; import {UIEventSource} from "../../Logic/UIEventSource"; export class CheckBox extends UIElement{ public readonly isEnabled: UIEventSource; - private readonly _showEnabled: string|UIElement; - private readonly _showDisabled: string|UIElement; + private readonly _showEnabled: UIElement; + private readonly _showDisabled: UIElement; constructor(showEnabled: string | UIElement, showDisabled: string | UIElement, data: UIEventSource | boolean = false) { super(undefined); this.isEnabled = data instanceof UIEventSource ? data : new UIEventSource(data ?? false); this.ListenTo(this.isEnabled); - this._showEnabled = showEnabled; - this._showDisabled = showDisabled; + this._showEnabled = Translations.W(showEnabled); + this._showDisabled =Translations.W(showDisabled); const self = this; this.onClick(() => { self.isEnabled.setData(!self.isEnabled.data); diff --git a/UI/Input/TextField.ts b/UI/Input/TextField.ts index 30e7ff9..4401485 100644 --- a/UI/Input/TextField.ts +++ b/UI/Input/TextField.ts @@ -178,8 +178,10 @@ export class TextField extends InputElement { return `` } + const placeholder = this._placeholder.InnerRender().replace("'", "'"); + return `
` + - `` + + `` + `
`; } @@ -246,11 +248,5 @@ export class TextField extends InputElement { return result !== undefined && result !== null; } - Clear() { - const field = document.getElementById('text-' + this.id); - if (field !== undefined) { - // @ts-ignore - field.value = ""; - } - } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/UI/SearchAndGo.ts b/UI/SearchAndGo.ts index afe1f69..047ae1e 100644 --- a/UI/SearchAndGo.ts +++ b/UI/SearchAndGo.ts @@ -44,13 +44,13 @@ export class SearchAndGo extends UIElement { // Triggered by 'enter' or onclick private RunSearch() { const searchString = this._searchField.GetValue().data; - this._searchField.Clear(); + this._searchField.GetValue().setData(""); this._placeholder.setData(Translations.t.general.search.searching); const self = this; Geocoding.Search(searchString, (result) => { if (result.length == 0) { - this._placeholder.setData(Translations.t.general.search.nothing); + self._placeholder.setData(Translations.t.general.search.nothing); return; } @@ -60,10 +60,11 @@ export class SearchAndGo extends UIElement { [bb[1], bb[3]] ] State.state.bm.map.fitBounds(bounds); - this._placeholder.setData(Translations.t.general.search.search); + self._placeholder.setData(Translations.t.general.search.search); }, () => { - this._placeholder.setData(Translations.t.general.search.error); + self._searchField.GetValue().setData(""); + self._placeholder.setData(Translations.t.general.search.error); }); } @@ -74,15 +75,5 @@ export class SearchAndGo extends UIElement { } - Update() { - super.Update(); - this._searchField.Update(); - this._goButton.Update(); - } - Activate() { - super.Activate(); - this._searchField.Activate(); - this._goButton.Activate(); - } } \ No newline at end of file diff --git a/UI/SlideShow.ts b/UI/SlideShow.ts index 38ee929..3abd0b2 100644 --- a/UI/SlideShow.ts +++ b/UI/SlideShow.ts @@ -8,8 +8,8 @@ export class SlideShow extends UIElement { public readonly _currentSlide: UIEventSource = new UIEventSource(0); private readonly _noimages: UIElement; - private _prev: FixedUiElement; - private _next: FixedUiElement; + private _prev: UIElement; + private _next: UIElement; constructor( embeddedElements: UIEventSource, @@ -75,18 +75,4 @@ export class SlideShow extends UIElement { this._currentSlide.setData(index); } - InnerUpdate(htmlElement) { - this._next.Update(); - this._prev.Update(); - } - - Activate() { - for (const embeddedElement of this._embeddedElements.data) { - embeddedElement.Activate(); - } - this._next.Update(); - this._prev.Update(); - return this; - } - -} \ No newline at end of file + } \ No newline at end of file diff --git a/UI/TagRendering.ts b/UI/TagRendering.ts index c9a24e9..ab6a02e 100644 --- a/UI/TagRendering.ts +++ b/UI/TagRendering.ts @@ -179,11 +179,11 @@ export class TagRendering extends UIElement implements TagDependantUIElement { } const cancelContents = this._editMode.map((isEditing) => { - if (isEditing) { - return "" + Translations.t.general.cancel.R() + ""; - } else { - return "" + Translations.t.general.skip.R() + ""; - } + const tr = Translations.t.general; + const text = isEditing ? tr.cancel : tr.skip; + return text + .SetStyle("display: inline-block;border: solid black 0.5px;padding: 0.2em 0.3em;border-radius: 1.5em;") + .Render(); }, [Locale.language]); // And at last, set up the skip button this._skipButton = new VariableUiElement(cancelContents).onClick(cancel); diff --git a/UI/UIElement.ts b/UI/UIElement.ts index 13311c0..dea9000 100644 --- a/UI/UIElement.ts +++ b/UI/UIElement.ts @@ -28,6 +28,7 @@ export abstract class UIElement extends UIEventSource { this.id = "ui-element-" + UIElement.nextId; this._source = source; UIElement.nextId++; + this.dumbMode = true; this.ListenTo(source); } @@ -74,32 +75,18 @@ export abstract class UIElement extends UIEventSource { let element = document.getElementById(this.id); if (element === undefined || element === null) { - // The element is not painted - + // The element is not painted or, in the case of 'dumbmode' this UI-element is not explicitely present if (this.dumbMode) { // We update all the children anyway - for (const i in this) { - const child = this[i]; - if (child instanceof UIElement) { - child.Update(); - } else if (child instanceof Array) { - for (const ch of child) { - if (ch instanceof UIElement) { - ch.Update(); - } - } - } - } + this.UpdateAllChildren(); } - - return; } const newRender = this.InnerRender(); if (newRender !== this.lastInnerRender) { + this.lastInnerRender = newRender; this.setData(this.InnerRender()); element.innerHTML = this.data; - this.lastInnerRender = newRender; } if (this._hideIfEmpty) { @@ -132,7 +119,11 @@ export abstract class UIElement extends UIEventSource { } this.InnerUpdate(element); + this.UpdateAllChildren(); + } + + private UpdateAllChildren() { for (const i in this) { const child = this[i]; if (child instanceof UIElement) { @@ -146,27 +137,32 @@ export abstract class UIElement extends UIEventSource { } } } - - HideOnEmpty(hide : boolean){ + + HideOnEmpty(hide: boolean) { this._hideIfEmpty = hide; this.Update(); return this; } - + // Called after the HTML has been replaced. Can be used for css tricks - protected InnerUpdate(htmlElement: HTMLElement) { - } + protected InnerUpdate(htmlElement: HTMLElement) { + } Render(): string { - this.lastInnerRender = this.lastInnerRender ?? this.InnerRender(); + this.lastInnerRender = this.InnerRender(); if (this.dumbMode) { return this.lastInnerRender; } + let style = ""; if (this.style !== undefined && this.style !== "") { - style = `style="${this.style}"`; + style = `style="${this.style}" `; } - return `${this.lastInnerRender}` + const clss = ""; + if (this.clss.length > 0) { + `class='${this.clss.join(" ")}' `; + } + return `${this.lastInnerRender}` } AttachTo(divId: string) { @@ -182,32 +178,20 @@ export abstract class UIElement extends UIEventSource { public abstract InnerRender(): string; - public Activate(): UIElement { - for (const i in this) { - const child = this[i]; - if (child instanceof UIElement) { - child.Activate(); - } else if (child instanceof Array) { - for (const ch of child) { - if (ch instanceof UIElement) { - ch.Activate(); - } - } - } - } - return this; - }; - public IsEmpty(): boolean { return this.InnerRender() === ""; } public SetClass(clss: string): UIElement { this.dumbMode = false; + if(clss === "" && this.clss.length > 0){ + this.clss = []; + this.Update(); + } if (this.clss.indexOf(clss) < 0) { this.clss.push(clss); + this.Update(); } - this.Update(); return this; } diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts index 1e0f610..316a3f3 100644 --- a/UI/i18n/Translation.ts +++ b/UI/i18n/Translation.ts @@ -41,6 +41,9 @@ export default class Translation extends UIElement { get txt(): string { + if(this.translations["*"]){ + return this.translations["*"]; + } const txt = this.translations[Translation.forcedLanguage ?? Locale.language.data]; if (txt !== undefined) { return txt; @@ -79,10 +82,6 @@ export default class Translation extends UIElement { return result; } - public R(): string { - return new Translation(this.translations).Render(); - } - public Clone() { return new Translation(this.translations) } diff --git a/customGenerator.html b/customGenerator.html index a47a77a..a87a8d4 100644 --- a/customGenerator.html +++ b/customGenerator.html @@ -2,6 +2,7 @@ + Custom Theme Generator for Mapcomplete