diff --git a/Logic/FilteredLayer.ts b/Logic/FilteredLayer.ts index a05d3ed..6af93ff 100644 --- a/Logic/FilteredLayer.ts +++ b/Logic/FilteredLayer.ts @@ -191,9 +191,15 @@ export class FilteredLayer { layer.on("click", function(e) { console.log("Selected ", feature) self._selectedElement.setData(feature.properties); + L.DomEvent.stop(e); // Marks the event as consumed const uiElement = self._showOnPopup.data(); - layer.bindPopup(uiElement.Render()).openPopup(); + const popup = L.popup(); + popup.setContent(uiElement.Render()); + layer.bindPopup(popup).openPopup(); + popup.onclose(() => { + layer.removePopup(popup) + }); uiElement.Update(); uiElement.Activate(); diff --git a/Logic/Geocoding.ts b/Logic/Geocoding.ts new file mode 100644 index 0000000..75d620e --- /dev/null +++ b/Logic/Geocoding.ts @@ -0,0 +1,18 @@ +import * as $ from "jquery" +import {UIEventSource} from "../UI/UIEventSource"; + +export class Geocoding { + + private static readonly host = "https://nominatim.openstreetmap.org/search?"; + + static Search(query: string, currentLocation: UIEventSource<{ lat: number, lon: number }>, + handleResult: ((places: { display_name: string, lat: number, lon: number, boundingbox : number[] }[]) => void)) { + $.getJSON( + Geocoding.host + "format=json&accept-language=nl&q=" + query, + function (data) { + handleResult(data); + }); + } + + +} diff --git a/Logic/StrayClickHandler.ts b/Logic/StrayClickHandler.ts index a85c872..85ccc9d 100644 --- a/Logic/StrayClickHandler.ts +++ b/Logic/StrayClickHandler.ts @@ -24,6 +24,7 @@ export class StrayClickHandler { const self = this; const map = basemap.map; basemap.LastClickLocation.addCallback(function (lastClick) { + selectElement.setData(undefined); if (self._lastMarker !== undefined) { map.removeLayer(self._lastMarker); @@ -36,8 +37,9 @@ export class StrayClickHandler { self._lastMarker.addTo(map); self._lastMarker.bindPopup(popup).openPopup(); - - leftMessage.setData(self._uiToShow); + self._lastMarker.on("click", () => { + leftMessage.setData(self._uiToShow); + }); }); diff --git a/README.md b/README.md index 43e289a..45a305a 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,9 @@ Images from Wikipedia/Wikimedia https://commons.wikimedia.org/wiki/File:Camera_font_awesome.svg Camera Icon, Dave Gandy, CC-BY-SA 3.0 + +https://commons.wikimedia.org/wiki/File:OOjs_UI_indicator_search-rtl.svg +Search Icon, MIT https://commons.wikimedia.org/wiki/File:Home-icon.svg Home icon by Timothy Miller, CC-BY-SA 3.0 diff --git a/UI/Base/TextField.ts b/UI/Base/TextField.ts new file mode 100644 index 0000000..d872b03 --- /dev/null +++ b/UI/Base/TextField.ts @@ -0,0 +1,46 @@ +import {UIElement} from "../UIElement"; +import {UIEventSource} from "../UIEventSource"; + + +export class TextField extends UIElement { + + public value = new UIEventSource(""); + /** + * Pings and has the value data + */ + public enterPressed = new UIEventSource(undefined); + private _placeholder: UIEventSource; + + constructor(placeholder : UIEventSource) { + super(placeholder); + this._placeholder = placeholder; + } + + protected InnerRender(): string { + return "
" + + "" + + "
"; + } + + InnerUpdate(htmlElement: HTMLElement) { + super.InnerUpdate(htmlElement); + const field = document.getElementById('text-' + this.id); + const self = this; + field.oninput = () => { + self.value.setData(field.value); + }; + + field.addEventListener("keyup", function (event) { + if (event.key === "Enter") { + self.enterPressed.setData(field.value); + } + }); + } + + Clear() { + const field = document.getElementById('text-' + this.id); + if (field !== undefined) { + field.value = ""; + } + } +} \ No newline at end of file diff --git a/UI/SearchAndGo.ts b/UI/SearchAndGo.ts new file mode 100644 index 0000000..d03e71a --- /dev/null +++ b/UI/SearchAndGo.ts @@ -0,0 +1,73 @@ +import {UIElement} from "./UIElement"; +import {TextField} from "./Base/TextField"; +import {VariableUiElement} from "./Base/VariableUIElement"; +import {UIEventSource} from "./UIEventSource"; +import {FixedUiElement} from "./Base/FixedUiElement"; +import {Geocoding} from "../Logic/Geocoding"; +import {Basemap} from "../Logic/Basemap"; +import {VerticalCombine} from "./Base/VerticalCombine"; + + +export class SearchAndGo extends UIElement { + + private _placeholder = new UIEventSource("Ga naar een locatie...") + private _searchField = new TextField(this._placeholder); + + private _foundEntries = new UIEventSource([]); + private _map: Basemap; + private _goButton = new FixedUiElement("GO"); + + constructor(map: Basemap) { + super(undefined); + this._map = map; + this.ListenTo(this._foundEntries); + + const self = this; + this._searchField.enterPressed.addCallback(() => { + self.RunSearch(); + }); + + this._goButton.onClick(function () { + self.RunSearch(); + }); + + } + + // Triggered by 'enter' or onclick + private RunSearch() { + const searchString = this._searchField.value.data; + this._searchField.Clear(); + this._placeholder.setData("Bezig met zoeken..."); + const self = this; + Geocoding.Search(searchString, undefined, (result) => { + + const bb = result[0].boundingbox; + const bounds = [ + [bb[0], bb[2]], + [bb[1], bb[3]] + ] + self._map.map.fitBounds(bounds); + this._placeholder.setData("Ga naar locatie..."); + }); + + } + + protected InnerRender(): string { + // "Search " + + return this._goButton.Render() + + this._searchField.Render(); + + } + + 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/UIElement.ts b/UI/UIElement.ts index a690bdc..408c2ef 100644 --- a/UI/UIElement.ts +++ b/UI/UIElement.ts @@ -1,4 +1,5 @@ import {UIEventSource} from "./UIEventSource"; +import {Playground} from "../Layers/Playground"; export abstract class UIElement { @@ -18,7 +19,7 @@ export abstract class UIElement { protected ListenTo(source: UIEventSource) { - if(source === undefined){ + if (source === undefined) { return; } const self = this; @@ -27,22 +28,39 @@ export abstract class UIElement { }) } + private _onClick: () => void; + + public onClick(f: (() => void)) { + this._onClick = f; + this.Update(); + } + Update(): void { - let element = document.getElementById(this.id); + let element = document.getElementById(this.id); if (element === null || element === undefined) { // The element is not painted return; } - + element.innerHTML = this.InnerRender(); - if(this._hideIfEmpty){ - if(element.innerHTML === ""){ + if (this._hideIfEmpty) { + if (element.innerHTML === "") { element.parentElement.style.display = "none"; - }else{ + } else { element.parentElement.style.display = undefined; } } - + + if (this._onClick !== undefined) { + console.log("Registering") + const self = this; + element.onclick = () => { + console.log("Clicked!") + self._onClick(); + } + element.style.cursor = "pointer"; + } + this.InnerUpdate(element); } diff --git a/assets/arrow-right-go-black.svg b/assets/arrow-right-go-black.svg new file mode 100644 index 0000000..b91e3ba --- /dev/null +++ b/assets/arrow-right-go-black.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/assets/search.svg b/assets/search.svg new file mode 100644 index 0000000..42c7066 --- /dev/null +++ b/assets/search.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/index.css b/index.css index da5f733..4d4c5ca 100644 --- a/index.css +++ b/index.css @@ -122,12 +122,60 @@ body { -webkit-border-radius: 2em; -moz-border-radius: 2em; border-radius: 2em; + border-bottom-right-radius: 1.5em; + border-top-right-radius: 1.5em; transition: all 500ms linear; - margin: 1em; - margin-left: 0; - margin-top: 0; + margin: 0; + margin-bottom: 0.5em; + min-width: 20em; pointer-events: all; +} + +#userbadge-and-search { + display: inline-block; +} + + +#searchbox { + display: inline-block; + text-align: left; + background-color: white; + transition: all 500ms linear; + pointer-events: all; + border-radius: 1.3em; + margin: 0; + margin-bottom: 1em; + width: 100%; +} + +.search { + position: relative; + float: left; + height: 2em; + margin-right: 0.5em; +} + +#searchbox .form-text-field { + position: relative; + float: left; + margin-top: 0.2em; +} + +#searchbox input[type="text"] { + background: transparent; + border: none; + font-size: large; +} + +.search-go { + position: relative; + height: 1.2em; + border: 2px solid black; + border-radius: 2em; + padding: 0.4em; + float: left; + margin-right: 0.5em; } @@ -159,7 +207,8 @@ body { #welcomeMessage { display: inline-block; max-width: 30em; - padding: 1em; + padding: 0; + padding-bottom: 1em; } #messagesboxmobilewrapper { diff --git a/index.html b/index.html index c527529..d50e48e 100644 --- a/index.html +++ b/index.html @@ -21,8 +21,13 @@
-
- Loading... If this message persists, check if javascript is enabled and if no extension (uMatrix) is blocking it. +
diff --git a/index.ts b/index.ts index 1b8da1c..4a90c00 100644 --- a/index.ts +++ b/index.ts @@ -19,6 +19,7 @@ import {GeoLocationHandler} from "./Logic/GeoLocationHandler"; import {StrayClickHandler} from "./Logic/StrayClickHandler"; import {SimpleAddUI} from "./UI/SimpleAddUI"; import {VariableUiElement} from "./UI/Base/VariableUIElement"; +import {SearchAndGo} from "./UI/SearchAndGo"; let dryRun = false; @@ -182,6 +183,8 @@ const pendingChanges = new PendingChanges( new UserBadge(osmConnection.userDetails, pendingChanges, bm) .AttachTo('userbadge'); +new SearchAndGo(bm).AttachTo("searchbox"); + var welcomeMessage = () => { return new VariableUiElement( osmConnection.userDetails.map((userdetails) => { diff --git a/test.html b/test.html index 5b263e0..b5f19fb 100644 --- a/test.html +++ b/test.html @@ -5,7 +5,8 @@ -
Hello World
+
'maindiv' not attached
+
'extradiv' not attached
diff --git a/test.ts b/test.ts index e69de29..1a28cb8 100644 --- a/test.ts +++ b/test.ts @@ -0,0 +1,17 @@ +import {Geocoding} from "./Logic/Geocoding"; +import {SearchAndGo} from "./UI/SearchAndGo"; +import {TextField} from "./UI/Base/TextField"; +import {VariableUiElement} from "./UI/Base/VariableUIElement"; + +console.log("HI"); + + new SearchAndGo().AttachTo("maindiv"); +/*const tf = new TextField(); +tf.AttachTo("maindiv"); +tf.enterPressed.addCallback(() => {alert("Searching")}); +new VariableUiElement(tf.value).AttachTo("extradiv"); +/*/ + + + +//*/