forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			147 lines
		
	
	
		
			No EOL
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			No EOL
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
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) {
 | 
						|
 | 
						|
                var 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) {
 | 
						|
            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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
} |