diff --git a/templates/map/client/config.json b/templates/map/client/config.json
index 5b8bf6cf..b55279e4 100644
--- a/templates/map/client/config.json
+++ b/templates/map/client/config.json
@@ -45,7 +45,6 @@
 		{ "folder": 13, "type": "WMS", "title": "farbig", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5", "active": false },
 		{ "folder": 13, "type": "WMS", "title": "grau", "attribution": "LVermGeo", "url": "https://geo4.service24.rlp.de/wms/dtk5_rp.fcgi?", "name": "rp_dtk5_grau", "active": false }
 	],
-	
 	"folders":
 	[
 		{ "title": "Hintergrund", "parent": -1 },
@@ -65,7 +64,6 @@
 		{ "title": "BaseMap", "parent": 0 },
 		{ "title": "Webatlas", "parent": 0 }
 	],
-	
 	"projections":
 	[
 		[ "EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs" ]
@@ -78,7 +76,8 @@
 		"minZoom": 5,
 		"maxZoom": 22,
 		"zoom": 9,
-		"attribution": "LANIS RLP"
+		"attribution": "LANIS RLP",
+		"scalebar": true
 	},
 	
 	"output":
@@ -94,9 +93,23 @@
 	"searchParcel":
 	{
 		"nameURL": "/client/proxy?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/gem_search.php?placename={q}",
-		"parcelURL": "/client/proxy?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/flur_search.php?gmk_gmn={district}&fln={field}&fsn_zae={parcelA}&fsn_nen={parcelB}&export=json"
+		"parcelURL": "/client/proxy?https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/flur_search.php?gmk_gmn={district}&fln={field}&fsn_zae={parcelA}&fsn_nen={parcelB}&export=json",
+		"districts_service":
+		{
+			"type": "WFS",
+			"url": "http://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",
+			"name": "vermkv:gemarkungen_rlp",
+			"order": 10,
+			"minZoom": 11,
+			"maxZoom": 17
+		},
+		"fields_service":
+		{
+			"url": "http://geo5.service24.rlp.de/wfs/verwaltungsgrenzen_rp.fcgi?",
+			"name": "vermkv:fluren_rlp",
+			"filter_property": "gmkgnr"
+		}
 	},
-
 	"import":
 	{
 		"geopackageLibURL": "/libs/geopackage/4.2.3/"
@@ -108,7 +121,6 @@
 		"defaultFilename": "Export",
 		"defaultMargin": 10
 	},
-
 	"tools":
 	{
 		"buffer":
@@ -117,7 +129,6 @@
 			"defaultSegments": 2
 		}
 	},
-
 	"styles":
 	{
 		"editLayer":
@@ -127,7 +138,6 @@
 			"strokeWidth": 3,
 			"pointRadius": 6
 		},
-
 		"select":
 		{
 			"fill": "rgba( 0, 127, 255, 0.5 )",
@@ -135,7 +145,6 @@
 			"strokeWidth": 3,
 			"pointRadius": 6
 		},
-
 		"sketch":
 		{
 			"fill": "rgba( 0, 127, 255, 0.2 )",
@@ -143,7 +152,6 @@
 			"strokeWidth": 3,
 			"pointRadius": 6
 		},
-
 		"modify":
 		{
 			"fill": "rgba( 0, 127, 255, 0.5 )",
@@ -151,12 +159,17 @@
 			"strokeWidth": 3,
 			"pointRadius": 6
 		},
-
 		"parcel":
 		{
 			"fill": "rgba( 127, 255, 255, 0.5 )",
 			"stroke": "#7fffff",
 			"strokeWidth": 3
+		},
+		"import":
+		{
+			"fill": "rgba( 0, 127, 255, 0.2 )",
+			"stroke": "rgba( 0, 127, 255, 1.0 )",
+			"width": 1.5
 		}
 	}
 }
\ No newline at end of file
diff --git a/templates/map/client/index.html b/templates/map/client/index.html
index 9d77addc..b45b77db 100644
--- a/templates/map/client/index.html
+++ b/templates/map/client/index.html
@@ -1,59 +1,34 @@
 {% load static %}
+
 		<!-- Library Styles -->
-		<link rel="stylesheet" type="text/css" href="{% static 'fontawesome/5.12.0/css/all.min.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'openlayers/7.2.2/ol.css' %}" />
+		<link rel="stylesheet" type="text/css" href="{% static 'libs/fontawesome/5.12.0/css/all.min.css' %}" />
+		<link rel="stylesheet" type="text/css" href="{% static 'libs/openlayers/7.2.2/ol.css' %}" />
 
 		<!-- Client Styles -->
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Client.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Map.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Attribution.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Controls.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/LayerTree.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/SearchParcel.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Toolbar.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Menu.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Modal.css' %}" />
-		<link rel="stylesheet" type="text/css" href="{% static 'netgis/Theme.css' %}" />
+		<link rel="stylesheet" type="text/css" href="{% static 'netgis.min.css' %}" />
+
+
+		<!-- Library Scripts-->
+		<script type="text/javascript" src="{% static 'libs/openlayers/7.2.2/ol.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/proj4js/2.6.0/proj4.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/jsts/1.6.1/jsts.min.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/shapefilejs/4.0.2/shp.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/jspdf/1.3.2/jspdf.min.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/gifjs/0.2.0/gif.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/sqljs/1.8.0/sql.js' %}"></script>
+		<script type="text/javascript" src="{% static 'libs/geopackage/4.2.3/geopackage.min.js' %}"></script>
+
+		<!-- Client Scripts -->
+		<script type="text/javascript" src="{% static 'netgis.min.js' %}"></script>
+
 
 		<main id="container" {% if geom_form.read_only %}data-editable="false"{% else %}data-editable="true"{% endif %} style="position: relative; width: 100%; height: 100%;">
 		</main>
-		
-		<!--<main id="container" contenteditable="false" style="position: absolute; width: 100%; height: 100%; left: 0mm; top: 0mm;">
-		</main>-->
-		
-		<input type="hidden" id="netgis-storage" name="geom" value="{{geom_form.fields.geom.initial}}"/>
-		
-		<!-- Library Scripts -->
-		<script type="text/javascript" src="{% static 'openlayers/7.2.2/ol.js' %}"></script>
-		<script type="text/javascript" src="{% static 'proj4js/2.6.0/proj4.js' %}"></script>
-		<script type="text/javascript" src="{% static 'jsts/1.6.1/jsts.min.js' %}"></script>
-		<script type="text/javascript" src="{% static 'shapefilejs/4.0.2/shp.js' %}"></script>
-		<script type="text/javascript" src="{% static 'jspdf/1.3.2/jspdf.min.js' %}"></script>
-		<script type="text/javascript" src="{% static 'gifjs/0.2.0/gif.js' %}"></script>
-		<script type="text/javascript" src="{% static 'sqljs/1.8.0/sql.js' %}"></script>
-		<script type="text/javascript" src="{% static 'geopackage/4.2.3/geopackage.min.js' %}"></script>
 
-		<!-- Client Scripts -->		
-		<script type="text/javascript" src="{% static 'netgis/Util.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Events.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Modes.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/LayerTypes.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Client.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Menu.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Map.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/MapOpenLayers.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Controls.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Attribution.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/LayerTree.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Toolbar.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/Modal.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/SearchPlace.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/SearchParcel.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/OWS.js' %}"></script>
-		<script type="text/javascript" src="{% static 'netgis/SLD.js' %}"></script>
+		<input type="hidden" id="netgis-storage" name="geom" value="{{geom_form.fields.geom.initial}}"/>
 
 		<script type="text/javascript">
-			
+
 			// Create Client Instance
 			var client = new netgis.Client( "container", "{% static 'config.json' %}" );
 			
diff --git a/templates/map/client/libs/netgis/Attribution.css b/templates/map/client/libs/netgis/Attribution.css
deleted file mode 100644
index c4cc9bad..00000000
--- a/templates/map/client/libs/netgis/Attribution.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.netgis-attribution
-{
-	position: absolute;
-	right: 0mm;
-	bottom: 0mm;
-	padding: 1mm;
-	background: rgba( 255, 255, 255, 0.5 );
-	/*color: #a7233f;*/
-	font-size: 0.8em !important;
-	z-index: 100;
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Attribution.js b/templates/map/client/libs/netgis/Attribution.js
deleted file mode 100644
index ec735458..00000000
--- a/templates/map/client/libs/netgis/Attribution.js
+++ /dev/null
@@ -1,86 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.Attribution = function()
-{
-	this.client = null;
-	this.layers = null;
-	this.items = [];
-};
-
-netgis.Attribution.prototype.load = function()
-{
-	this.root = document.createElement( "section" );
-	this.root.className = "netgis-attribution netgis-text-primary";
-	
-	if ( netgis.util.isDefined( this.client.config.map ) )
-		if ( netgis.util.isDefined( this.client.config.map.attribution ) )
-			this.items.push( this.client.config.map.attribution );
-	
-	this.update();
-	
-	this.client.root.appendChild( this.root );
-	
-	// Events
-	this.client.on( netgis.Events.CONTEXT_UPDATE, this.onContextUpdate.bind( this ) );
-	this.client.on( netgis.Events.LAYER_SHOW, this.onLayerShow.bind( this ) );
-	this.client.on( netgis.Events.LAYER_HIDE, this.onLayerHide.bind( this ) );
-};
-
-netgis.Attribution.prototype.update = function()
-{
-	this.root.innerHTML = "&copy; " + this.items.join( ", " );
-};
-
-netgis.Attribution.prototype.onContextUpdate = function( e )
-{
-	var context = e;
-	
-	// Layers
-	this.layers = [];
-	
-	for ( var l = 0; l < context.layers.length; l++ )
-	{
-		var item = context.layers[ l ];
-		
-		if ( item.attribution && item.attribution.length > 0 )
-		{
-			this.layers[ l ] = item.attribution;
-		}
-	}
-};
-
-netgis.Attribution.prototype.onLayerShow = function( e )
-{
-	var attribution = this.layers[ e.id ];
-	
-	if ( ! attribution ) return;
-	
-	for ( var i = 0; i < this.items.length; i++ )
-	{
-		if ( this.items[ i ] === attribution ) return;
-	}
-	
-	this.items.push( attribution );
-	
-	this.update();
-};
-
-netgis.Attribution.prototype.onLayerHide = function( e )
-{
-	var attribution = this.layers[ e.id ];
-	
-	if ( ! attribution ) return;
-	
-	for ( var i = 0; i < this.items.length; i++ )
-	{
-		if ( this.items[ i ] === attribution )
-		{
-			this.items.splice( i, 1 );
-			break;
-		}
-	}
-	
-	this.update();
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Client.css b/templates/map/client/libs/netgis/Client.css
deleted file mode 100644
index 84d4b57a..00000000
--- a/templates/map/client/libs/netgis/Client.css
+++ /dev/null
@@ -1,47 +0,0 @@
-.netgis-client
-{
-	position: absolute;
-	width: 100%;
-	height: 100%;
-	overflow: hidden;	
-	background: #aaa;
-}
-
-.netgis-client *
-{
-	box-sizing: border-box;
-}
-
-.netgis-client .netgis-loader
-{
-	position: absolute;
-	width: 100%;
-	height: 100%;
-	z-index: 9999;
-	text-align: center;
-	font-size: 12mm;
-}
-
-.netgis-client .netgis-hide
-{
-	display: none;
-}
-
-.netgis-client .netgis-loader i
-{
-	position: absolute;
-	top: 50%;
-	transform: translateY( -50% );
-	animation: netgis-spin 2s linear infinite;
-}
-
-@keyframes netgis-spin
-{
-    0% { transform: rotate( 0deg ); }
-    100% { transform: rotate( 360deg ); }
-}
-
-.netgis-client button
-{
-	/*outline: none;*/
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Client.js b/templates/map/client/libs/netgis/Client.js
deleted file mode 100644
index ed39abd5..00000000
--- a/templates/map/client/libs/netgis/Client.js
+++ /dev/null
@@ -1,304 +0,0 @@
-"use strict";
-
-/**
- * The netgis namespace.
- * @namespace
- */
-var netgis = netgis || {};
-
-/**
- * The main NetGIS Client class. 
- * @param {Element} container
- * @param {JSON} config
- * @returns {netgis.Client}
- */
-netgis.Client = function( container, config )
-{
-	this.build = "20220826";
-	this.debug = false;
-	
-	if ( netgis.util.isString( container ) )
-		container = document.getElementById( container );
-	
-	this.container = container;
-	
-	this.editable = true;
-	this.root = null;
-	
-	this.modules = [];
-	this.callbacks = {};
-	
-	this.config = this.createDefaultConfig();
-	
-	this.create();
-	
-	if ( netgis.util.isDefined( config ) )
-	{
-		if ( netgis.util.isString( config ) )
-		{
-			// Config From Url
-			var self = this;
-
-			netgis.util.request
-			(
-				config,
-				function( data )
-				{
-					var json = JSON.parse( data );
-					
-					netgis.util.merge( self.config, json );
-
-					self.createModules();
-					self.load();
-					self.invoke( netgis.Events.CONTEXT_UPDATE, self.config );
-
-					self.hideLoader();
-				}
-			);
-		}
-		else
-		{
-			// Config From Object
-			netgis.util.merge( this.config, config );
-
-			this.createModules();
-			this.load();
-			this.invoke( netgis.Events.CONTEXT_UPDATE, this.config );
-
-			this.hideLoader();
-		}
-	}
-	else
-	{
-		// No Config Given
-		this.createModules();
-		this.load();
-		this.invoke( netgis.Events.CONTEXT_UPDATE, this.config );
-
-		this.hideLoader();
-	}
-	
-	//TODO: config module to handle params, existance, defaults, etc. ?
-};
-
-netgis.Client.prototype.createDefaultConfig = function()
-{
-	//TODO: should this be a static method of a config module ?
-	
-	var config =
-	{
-		map:
-		{
-			projection: "EPSG:3857",
-			center: [ 1113194.0, 6621293.0 ],
-			minZoom: 0,
-			maxZoom: 20,
-			zoom: 6,
-			attribution: "NetGIS"
-		},
-		projections:
-		[
-		],
-		layers:
-		[
-			{ folder: 0, type: netgis.LayerTypes.OSM, title: "Open Street Map", attribution: "OSM Contributors", active: true }
-		],
-		folders:
-		[
-			{ title: "Hintergrund", parent: -1 }
-		],
-		styles:
-		{
-			editLayer: { fill: "rgba( 255, 0, 0, 0.5 )", stroke: "#ff0000", strokeWidth: 3, pointRadius: 6 },
-			select: { fill: "rgba( 0, 127, 255, 0.5 )", stroke: "#007fff", strokeWidth: 3, pointRadius: 6 },
-			sketch: { fill: "rgba( 0, 127, 0, 0.5 )", stroke: "#007f00", strokeWidth: 3, pointRadius: 6 },
-			modify: { fill: "rgba( 0, 127, 0, 0.5 )", stroke: "#007f00", strokeWidth: 3, pointRadius: 6 },
-			parcel: { fill: "rgba( 127, 255, 255, 0.5 )", stroke: "#7fffff", strokeWidth: 3 }
-		}
-	};
-	
-	//TODO: advanced config merge, so it's easier to extend layers, styles etc. without replacing the whole array
-	
-	return config;
-};
-
-/**
- * Creates the core HTML elements for this client.
- */
-netgis.Client.prototype.create = function()
-{
-	this.root = document.createElement( "section" );
-	this.root.className = "netgis-client";
-	
-	this.loader = document.createElement( "div" );
-	this.loader.className = "netgis-loader netgis-dialog netgis-text-primary";
-	this.loader.innerHTML = "<i class='fas fa-spinner'></i>";
-	this.root.appendChild( this.loader );
-	
-	this.container.appendChild( this.root );
-};
-
-/**
- * Create and add all modules to this client.
- */
-netgis.Client.prototype.createModules = function()
-{
-	// Editable
-	this.editable = true;
-	
-	if ( this.container.hasAttribute( "contenteditable" ) )
-	{
-		if ( this.container.getAttribute( "contenteditable" ) === "false" )
-		{
-			this.editable = false;
-		}
-	}
-	
-	if ( this.container.hasAttribute( "data-editable" ) )
-	{
-		this.editable = this.container.getAttribute( "data-editable" ) === "true" ? true : false;
-	}
-	
-	// Modules
-	this.add( this.map = new netgis.MapOpenLayers() ); //TODO: how to properly store module references ?
-	this.add( new netgis.Controls() );
-	this.add( new netgis.Attribution() );
-	this.add( new netgis.LayerTree() );
-	this.add( new netgis.Toolbar() );
-	this.add( new netgis.Menu() );
-	this.add( new netgis.SearchPlace() );
-	this.add( new netgis.SearchParcel() );
-	this.add( new netgis.Modal() );
-};
-
-/**
- * Finally load this client and its modules.
- */
-netgis.Client.prototype.load = function()
-{	
-	// Modules
-	for ( var m = 0; m < this.modules.length; m++ )
-	{
-		this.modules[ m ].load();
-	}
-	
-	// Output Element
-	if ( netgis.util.isDefined( this.config.output ) )
-	{
-		if ( netgis.util.isDefined( this.config.output.id ) )
-		{
-			this.output = document.getElementById( this.config.output.id );
-
-			if ( this.output.value && this.output.value.length > 0 )
-			{
-				//console.info( "INPUT:", this.output.value );
-				var json = JSON.parse( this.output.value );
-				this.invoke( netgis.Events.EDIT_FEATURES_LOADED, json );
-			}
-		}
-		
-	}
-	else
-	{
-		this.output = document.createElement( "input" );
-		this.output.setAttribute( "type", "hidden" );
-		this.output.className = "netgis-edit-output";
-		this.root.appendChild( this.output );
-	}
-	
-	// Default Interaction
-	this.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-	
-	// Events
-	this.on( netgis.Events.EXPORT_BEGIN, this.onMapExportBegin.bind( this ) );
-	this.on( netgis.Events.EXPORT_END, this.onMapExportEnd.bind( this ) );
-	this.on( netgis.Events.EDIT_FEATURES_CHANGE, this.onEditFeaturesChange.bind( this ) );
-};
-
-netgis.Client.prototype.add = function( module )
-{
-	module.client = this;
-	this.modules.push( module );
-};
-
-netgis.Client.prototype.on = function( evt, callback )
-{
-	if ( ! netgis.util.isDefined( this.callbacks[ evt ] ) )
-	{
-		this.callbacks[ evt ] = [];
-	}
-
-	this.callbacks[ evt ].push( callback );
-};
-
-netgis.Client.prototype.off = function( evt, callback )
-{
-	if ( netgis.util.isDefined( this.callbacks[ evt ] ) )
-	{
-		if ( netgis.util.isDefined( callback ) )
-		{
-			// Remove Specific Callback
-			for ( var i = 0; i < this.callbacks[ evt ].length; i++ )
-			{
-				if ( this.callbacks[ evt ][ i ] === callback )
-				{
-					this.callbacks[ evt ].splice( i, 1 );
-					break;
-				}
-			}
-			
-			if ( this.callbacks[ evt ].length < 1 ) delete this.callbacks[ evt ];
-		}
-		else
-		{
-			// Remove All Callbacks
-			delete this.callbacks[ evt ];
-		}
-	}
-};
-
-netgis.Client.prototype.invoke = function( evt, params )
-{
-	if ( this.debug ) console.info( "EVENT:", evt, params );
-			
-	if ( netgis.util.isDefined( this.callbacks[ evt ] ) )
-	{
-		for ( var i = 0; i < this.callbacks[ evt ].length; i++ )
-		{
-			this.callbacks[ evt ][ i ]( params );
-		}
-	}
-};
-
-netgis.Client.prototype.showLoader = function()
-{
-	this.loader.classList.remove( "netgis-hide" );
-};
-
-netgis.Client.prototype.hideLoader = function()
-{
-	this.loader.classList.add( "netgis-hide" );
-};
-
-netgis.Client.prototype.onHtmlResponse = function( data )
-{
-	this.root = netgis.util.create( data );
-	this.container.appendChild( this.root );
-};
-
-netgis.Client.prototype.onEditFeaturesChange = function( e )
-{
-	var geojson = JSON.stringify( e );
-	//console.info( "OUTPUT:", geojson );
-	this.output.value = geojson;
-};
-
-netgis.Client.prototype.onMapExportBegin = function( e )
-{
-	this.showLoader();
-};
-
-netgis.Client.prototype.onMapExportEnd = function( e )
-{
-	this.hideLoader();
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Controls.css b/templates/map/client/libs/netgis/Controls.css
deleted file mode 100644
index 3dd39293..00000000
--- a/templates/map/client/libs/netgis/Controls.css
+++ /dev/null
@@ -1,59 +0,0 @@
-.netgis-controls
-{
-	position: absolute;
-	width: 12mm;
-	left: 0mm;
-	bottom: 8mm;
-	
-	z-index: 100;
-	
-	/*background: lightblue;*/
-}
-
-.netgis-controls button
-{
-	font-size: 6mm !important;
-	
-	width: 100%;
-	height: 12mm;
-	padding: 0mm;
-	border: none;
-	background: none;
-	
-	cursor: pointer;
-	
-	color: white;
-	/*text-shadow: 0mm 0mm 1mm #a7233f;*/
-	/*color: #a7233f;*/
-	/*text-shadow: 0mm 0mm 1mm white, 0mm 0mm 2mm white, 0mm 0mm 3mm white;*/
-	/*text-shadow: 0mm 0mm 1mm rgba( 0, 0, 0, 0.7 ), 0mm 0mm 3mm rgba( 0, 0, 0, 0.7 );*/
-	
-	text-shadow:	-0.5mm 0.0mm 0.3mm #000,
-					0.5mm 0.0mm 0.3mm #000,
-					0.0mm -0.5mm 0.3mm #000,
-					0.0mm 0.5mm 0.3mm #000,
-					/*-0.4mm -0.4mm 0.3mm rgba( 0, 0, 0, 0.7 ),
-					0.4mm -0.4mm 0.3mm rgba( 0, 0, 0, 0.7 ),
-					-0.4mm 0.4mm 0.3mm rgba( 0, 0, 0, 0.7 ),
-					0.4mm 0.4mm 0.3mm rgba( 0, 0, 0, 0.7 ),*/
-					0mm 1mm 3mm rgba( 0, 0, 0, 0.7 );
-}
-
-.netgis-controls button:hover
-{
-	/*color: #a7233f;*/
-	
-	/*color: white;*/
-	/*text-shadow: 0mm 0mm 1mm #a7233f, 0mm 0mm 2mm #a7233f, 0mm 0mm 3mm #a7233f;*/
-	/*text-shadow: 0mm 0mm 1mm rgba( 167, 35, 63, 0.7 ), 0mm 0mm 3mm rgba( 167, 35, 63, 0.7 );*/
-	
-	text-shadow:	-0.5mm 0.0mm 0.3mm #a7233f,
-					0.5mm 0.0mm 0.3mm #a7233f,
-					0.0mm -0.5mm 0.3mm #a7233f,
-					0.0mm 0.5mm 0.3mm #a7233f,
-					/*-0.4mm -0.4mm 0.3mm rgba( 167, 35, 63, 0.7 ),
-					0.4mm -0.4mm 0.3mm rgba( 167, 35, 63, 0.7 ),
-					-0.4mm 0.4mm 0.3mm rgba( 167, 35, 63, 0.7 ),
-					0.4mm 0.4mm 0.3mm rgba( 167, 35, 63, 0.7 ),*/
-					0mm 1mm 3mm rgba( 0, 0, 0, 0.7 );
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Controls.js b/templates/map/client/libs/netgis/Controls.js
deleted file mode 100644
index bcce1df1..00000000
--- a/templates/map/client/libs/netgis/Controls.js
+++ /dev/null
@@ -1,59 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.Controls = function()
-{
-	this.client = null;
-};
-
-netgis.Controls.prototype.load = function()
-{
-	this.root = document.createElement( "section" ); // header?
-	this.root.className = "netgis-controls";
-	
-	/*var controls = document.createElement( "div" );
-	controls.className = "netgis-controls";
-	this.root.appendChild( controls );*/
-	
-	var zoomIn = document.createElement( "button" );
-	zoomIn.setAttribute( "type", "button" );
-	zoomIn.innerHTML = "<i class='fas fa-search-plus'></i>";
-	zoomIn.title = "Hineinzoomen";
-	zoomIn.addEventListener( "click", this.onZoomIn.bind( this ) );
-	this.root.appendChild( zoomIn );
-	
-	var zoomOut = document.createElement( "button" );
-	zoomOut.setAttribute( "type", "button" );
-	zoomOut.innerHTML = "<i class='fas fa-search-minus'></i>";
-	zoomOut.title = "Herauszoomen";
-	zoomOut.addEventListener( "click", this.onZoomOut.bind( this ) );
-	this.root.appendChild( zoomOut );
-	
-	/*var settings = document.createElement( "button" );
-	settings.innerHTML = "<i class='fas fa-cog'></i>";
-	settings.title = "Einstellungen";
-	settings.addEventListener( "click", this.onSettings.bind( this ) );
-	this.root.appendChild( settings );*/
-	
-	this.client.root.appendChild( this.root );
-};
-
-netgis.Controls.prototype.onZoomIn = function( e )
-{
-	//this.view.adjustZoom( 1.0 );
-	////this.view.animate( { zoom: this.view.getZoom() + 1.0, duration: 200 } );
-	this.client.invoke( netgis.Events.MAP_CHANGE_ZOOM, 1.0 );
-};
-
-netgis.Controls.prototype.onZoomOut = function( e )
-{
-	//this.view.adjustZoom( -1.0 );
-	////this.view.animate( { zoom: this.view.getZoom() - 1.0, duration: 200 } );
-	this.client.invoke( netgis.Events.MAP_CHANGE_ZOOM, -1.0 );
-};
-
-netgis.Controls.prototype.onSettings = function( e )
-{
-	alert( "TODO: settings dialog" );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Events.js b/templates/map/client/libs/netgis/Events.js
deleted file mode 100644
index f0ba9014..00000000
--- a/templates/map/client/libs/netgis/Events.js
+++ /dev/null
@@ -1,81 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.Events = Object.freeze
-(
-	{
-		CONTEXT_UPDATE: "CONTEXT_UPDATE",
-		SET_MODE: "SET_MODE",
-		
-		LAYER_LIST_TOGGLE: "LAYER_LIST_TOGGLE",
-
-		PANEL_TOGGLE: "PANEL_TOGGLE",
-		PANEL_SHOW: "PANEL_SHOW",
-		PANEL_HIDE: "PANEL_HIDE",
-
-		LAYER_SHOW: "LAYER_SHOW",
-		LAYER_HIDE: "LAYER_HIDE",
-		LAYER_CREATED: "LAYER_CREATED",
-
-		MAP_ZOOM_WKT: "MAP_ZOOM_WKT",
-		MAP_SET_EXTENT: "MAP_SET_EXTENT",
-		MAP_CHANGE_ZOOM: "MAP_CHANGE_ZOOM",
-		
-		MAP_UPDATE_STYLE: "MAP_UPDATE_STYLE", //TODO: ?
-
-		MAP_MODE_POINTS: "MAP_MODE_POINTS",
-		MAP_MODE_LINES: "MAP_MODE_LINES",
-		MAP_MODE_POLYGONS: "MAP_MODE_POLYGONS",
-		
-		EDIT_FEATURES_LOADED: "EDIT_FEATURES_LOADED",
-		EDIT_FEATURES_CHANGE: "EDIT_FEATURES_CHANGE",
-		
-		SEARCH_PLACE_REQUEST: "SEARCH_PLACE_REQUEST",
-		SEARCH_PLACE_RESPONSE: "SEARCH_PLACE_RESPONSE",
-		
-		PARCEL_SHOW_PREVIEW: "PARCEL_SHOW_PREVIEW",
-		PARCEL_HIDE_PREVIEW: "PARCEL_HIDE_PREVIEW",
-		
-		BUFFER_CHANGE: "BUFFER_CHANGE",
-		BUFFER_ACCEPT: "BUFFER_ACCEPT",
-		BUFFER_CANCEL: "BUFFER_CANCEL",
-		DRAW_BUFFER_ON: "DRAW_BUFFER_ON",
-		DRAW_BUFFER_OFF: "DRAW_BUFFER_OFF",
-		DRAW_BUFFER_RADIUS_CHANGE: "DRAW_BUFFER_RADIUS_CHANGE",
-		DRAW_BUFFER_SEGMENTS_CHANGE: "DRAW_BUFFER_SEGMENTS_CHANGE",
-		SNAP_ON: "SNAP_ON",
-		SNAP_OFF: "SNAP_OFF",
-		TRACING_ON: "TRACING_ON",
-		TRACING_OFF: "TRACING_OFF",
-		
-		IMPORT_SHAPEFILE_SHOW: "IMPORT_SHAPEFILE_SHOW",
-		IMPORT_GEOJSON_SHOW: "IMPORT_GEOJSON_SHOW",
-		IMPORT_GML_SHOW: "IMPORT_GML_SHOW",
-		IMPORT_SPATIALITE_SHOW: "IMPORT_SPATIALITE_SHOW",
-		IMPORT_GEOPACKAGE_SHOW: "IMPORT_GEOPACKAGE_SHOW",
-		
-		IMPORT_SHAPEFILE: "IMPORT_SHAPEFILE",
-		IMPORT_GEOJSON: "IMPORT_GEOJSON",
-		IMPORT_GML: "IMPORT_GML",
-		IMPORT_WKT: "IMPORT_WKT",
-		IMPORT_SPATIALITE: "IMPORT_SPATIALITE",
-		IMPORT_GEOPACKAGE: "IMPORT_GEOPACKAGE",
-		
-		EXPORT_PDF_SHOW: "EXPORT_PDF_SHOW",
-		EXPORT_JPEG_SHOW: "EXPORT_JPEG_SHOW",
-		EXPORT_PNG_SHOW: "EXPORT_PNG_SHOW",
-		EXPORT_GIF_SHOW: "EXPORT_GIF_SHOW",
-		
-		EXPORT_PDF: "EXPORT_PDF",
-		EXPORT_JPEG: "EXPORT_JPEG",
-		EXPORT_PNG: "EXPORT_PNG",
-		EXPORT_GIF: "EXPORT_GIF",
-		EXPORT_BEGIN: "EXPORT_BEGIN",
-		EXPORT_END: "EXPORT_END",
-		
-		ADD_SERVICE_SHOW: "ADD_SERVICE_SHOW",
-		ADD_SERVICE_WMS: "ADD_SERVICE_WMS",
-		ADD_SERVICE_WFS: "ADD_SERVICE_WFS"
-	}
-);
diff --git a/templates/map/client/libs/netgis/LayerTree.css b/templates/map/client/libs/netgis/LayerTree.css
deleted file mode 100644
index 29d0017d..00000000
--- a/templates/map/client/libs/netgis/LayerTree.css
+++ /dev/null
@@ -1,183 +0,0 @@
-
-/* TODO: refactor into common panel class */
-
-.netgis-layer-list
-{
-	position: absolute;
-	right: 0mm;
-	width: 100%;
-	max-width: 100mm;
-	top: 12mm;
-	bottom: 0mm;
-	overflow: auto;
-	z-index: 200;
-	
-	-webkit-transform: none;
-	transform: none;
-	transition: transform 150ms ease;
-}
-
-.netgis-layer-list.netgis-hide
-{
-	display: initial;
-	
-	-webkit-transform: translateX( 110% );
-	transform: translateX( 110% );
-	transition: transform 150ms ease;
-	will-change: transform;
-}
-
-.netgis-layer-list ul
-{
-	list-style-type: none;
-}
-
-.netgis-layer-list > ul
-{
-	display: block;
-	position: relative;
-	width: 100%;
-	margin: 0mm;
-	padding: 0mm;
-}
-
-.netgis-folder
-{
-	position: relative;
-	overflow: hidden;
-	list-style: none;
-	padding: 0mm;
-	margin: 0mm;
-	min-height: 12mm;
-	width: 100%;
-	white-space: nowrap;
-}
-
-.netgis-folder label
-{
-	/*/display: inline-block;
-	position: absolute;
-	width: 12mm;
-	height: 12mm;
-	left: 0mm;
-	top: 0mm;
-	text-align: center;
-	line-height: 12mm;*/
-	cursor: pointer;
-}
-
-.netgis-folder input[type=checkbox]
-{
-	cursor: pointer;
-}
-
-.netgis-folder > button
-{
-	display: inline-block;
-	/*display: block;
-	position: absolute;*/
-	/* width: auto; TODO: ??? */
-	
-	width: 100%;
-	padding: 0mm;
-	padding-right: 16mm; /* 4mm + 12mm ( padding + checkbox width ) */
-	
-	/*width: 88mm; /* 100mm - 12mm */
-	/*width: calc( 100% - 12mm );*/
-	/*width: literal( "calc(100%-12mm)" );*/
-	
-	margin: 0mm;
-	
-	/*left: 12mm;
-	right: 0mm;
-	top: 0mm;
-	height: 12mm;*/
-	line-height: 12mm;
-	text-align: left;
-	/*padding: 0mm;
-	padding-right: 4mm;*/
-}
-
-.netgis-folder > ul
-{
-	display: none;
-	/*max-height: 0mm;
-	overflow: hidden;
-	transition: max-height ease 200ms;*/
-
-	/*padding-top: 12mm;*/
-	padding-left: 8mm;
-}
-
-.netgis-folder.netgis-active > ul
-{
-	display: block;
-	/*max-height: 60mm;
-	overflow-y: auto;*/
-} 
-
-.netgis-folder-item
-{
-	height: 12mm;
-	line-height: 12mm;
-}
-
-.netgis-folder-item > label
-{
-	display: block;
-	/*width: 100%;*/
-	padding-right: 4mm;
-}
-
-/* TODO: just .netgis-icon for folders too */
-/*.netgis-folder-item*/ .netgis-layer-list .netgis-icon
-{
-	display: inline-block;
-	width: 12mm;
-	line-height: 12mm;
-	text-align: center;
-}
-
-.netgis-layer-list i
-{
-	margin-right: 4mm;
-}
-
-.netgis-folder i
-{
-	color: #eab000;
-}
-
-.netgis-folder-item i
-{
-	color: #bbb;
-}
-
-.netgis-folder .netgis-partial
-{
-	opacity: 0.5;
-}
-
-.netgis-layer-tools
-{
-	padding: 4mm;
-	padding-top: 0mm;
-	text-align: center;
-}
-
-.netgis-layer-tools hr
-{
-	margin: 4mm 0mm;
-	color: #eee;
-	border-color: #eee;
-}
-
-.netgis-layer-tools button
-{
-	padding: 2mm 4mm;
-}
-
-.netgis-layer-tools button i
-{
-	margin-right: 1mm;
-}
diff --git a/templates/map/client/libs/netgis/LayerTree.js b/templates/map/client/libs/netgis/LayerTree.js
deleted file mode 100644
index 9f52a2f0..00000000
--- a/templates/map/client/libs/netgis/LayerTree.js
+++ /dev/null
@@ -1,475 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-//TODO: refactor common panel class
-//TODO: refactor common tree view class
-
-netgis.LayerTree = function()
-{
-	this.client = null;
-	this.root = null;
-	this.list = null;
-	this.folderImport = null;
-	this.folderDraw = null;
-};
-
-netgis.LayerTree.prototype.load = function()
-{
-	this.root = document.createElement( "section" );
-	this.root.className = "netgis-layer-list netgis-dialog netgis-shadow netgis-hide";
-	
-	this.list = document.createElement( "ul" );
-	this.list.className = "root";
-	this.root.appendChild( this.list );
-	
-	this.initDefaultFolders();
-	
-	this.tools = document.createElement( "div" );
-	this.tools.className = "netgis-layer-tools";
-	this.tools.innerHTML = "<hr/>";
-	this.root.appendChild( this.tools );
-	
-	this.buttonAddService = document.createElement( "button" );
-	this.buttonAddService.className = "netgis-text-primary netgis-hover-primary";
-	this.buttonAddService.innerHTML = "<i class='fas fa-folder-plus'></i> Dienst hinzufügen";
-	this.buttonAddService.setAttribute( "type", "button" );
-	this.buttonAddService.addEventListener( "click", this.onAddServiceClick.bind( this ) );
-	this.tools.appendChild( this.buttonAddService );
-	
-	this.client.root.appendChild( this.root );
-	
-	this.client.on( netgis.Events.CONTEXT_UPDATE, this.onContextUpdate.bind( this ) );
-	this.client.on( netgis.Events.LAYER_LIST_TOGGLE, this.onLayerListToggle.bind( this ) );
-	this.client.on( netgis.Events.LAYER_CREATED, this.onLayerCreated.bind( this ) );
-	this.client.on( netgis.Events.EDIT_FEATURES_CHANGE, this.onEditFeaturesChange.bind( this ) );
-	this.client.on( netgis.Events.ADD_SERVICE_WMS, this.onAddServiceWMS.bind( this ) );
-	this.client.on( netgis.Events.ADD_SERVICE_WFS, this.onAddServiceWFS.bind( this ) );
-	
-	//TODO: kind of hack to hide if parcel search open
-	this.client.on( netgis.Events.SET_MODE, this.onSetMode.bind( this ) );
-};
-
-netgis.LayerTree.prototype.initDefaultFolders = function()
-{
-	this.folderDraw = this.createFolder( "Zeichnung" );
-	this.folderDraw.classList.add( "netgis-hide" );
-	this.list.appendChild( this.folderDraw );
-	
-	this.folderImport = this.createFolder( "Importierte Ebenen" );
-	this.folderImport.classList.add( "netgis-hide" );
-	this.list.appendChild( this.folderImport );
-	
-	this.folderServices = this.createFolder( "Eigene Dienste" );
-	this.folderServices.classList.add( "netgis-hide" );
-	this.list.appendChild( this.folderServices );
-};
-
-netgis.LayerTree.prototype.clearAll = function()
-{
-	this.list.innerHTML = "";
-	
-	this.initDefaultFolders();
-};
-
-netgis.LayerTree.prototype.createFolder = function( title )
-{	
-	var item = document.createElement( "li" );
-	item.className = "netgis-folder netgis-hover-light";
-	item.setAttribute( "title", title );
-	//item.innerHTML = "<span class='caret'>" + title + "</span>";
-	
-	var label = document.createElement( "label" );
-	label.className = "netgis-icon";
-	item.appendChild( label );
-	
-	var checkbox = document.createElement( "input" );
-	checkbox.setAttribute( "type", "checkbox" );
-	//checkbox.checked = checked;
-	checkbox.addEventListener( "change", this.onFolderChange.bind( this ) );
-	label.appendChild( checkbox );
-	
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.className = "netgis-clip-text netgis-hover-text-primary";
-	button.innerHTML = '<i class="fas fa-folder-open"></i>' + title;
-	button.addEventListener( "click", this.onFolderClick.bind( this ) );
-	item.appendChild( button );
-	
-	var folder = document.createElement( "ul" );
-	item.appendChild( folder );
-	
-	return item;
-};
-
-netgis.LayerTree.prototype.createLayer = function( id, title, checked )
-{
-	var item = document.createElement( "li" );
-	//item.dataset.id = id;
-	item.setAttribute( "title", title );
-	item.className = "netgis-folder-item netgis-hover-text-primary";
-	
-	var label = document.createElement( "label" );
-	label.className = "netgis-label netgis-clip-text";
-	item.appendChild( label );
-	
-	var span = document.createElement( "span" );
-	span.className = "netgis-icon";
-	label.appendChild( span );
-	
-	var checkbox = document.createElement( "input" );
-	checkbox.setAttribute( "type", "checkbox" );
-	checkbox.dataset.id = id;
-	checkbox.checked = checked;
-	checkbox.addEventListener( "change", this.onItemChange.bind( this ) );
-	span.appendChild( checkbox );
-	
-	var icon = document.createElement( "i" );
-	//icon.className = "fas fa-file";
-	//icon.className = "fas fa-sticky-note";
-	//icon.className = "far fa-map";
-	icon.className = "fas fa-th-large";
-	label.appendChild( icon );
-	
-	var text = document.createTextNode( title );
-	label.appendChild( text );
-	
-	var appendix = document.createElement( "span" );
-	label.appendChild( appendix );
-	
-	return item;
-};
-
-netgis.LayerTree.prototype.addToFolder = function( folder, item, prepend )
-{
-	var list;
-	
-	if ( folder )
-	{
-		list = folder.getElementsByTagName( "ul" )[ 0 ]; //TODO: folder.children[ 0 ] ?
-		list.appendChild( item );
-	}
-	else
-	{
-		list = this.list;
-	}
-	
-	if ( ! prepend )
-	{
-		list.appendChild( item );
-	}
-	else
-	{
-		list.insertBefore( item, list.firstChild );
-	}
-};
-
-netgis.LayerTree.prototype.onFolderClick = function( e )
-{
-	/*
-	var folder = e.currentTarget.parentElement.parentElement;
-	folder.classList.toggle( "netgis-active" );
-	*/
-   
-	//e.currentTarget.parentElement.querySelector(".nested").classList.toggle("active");
-	
-	var folder = e.currentTarget.parentElement;
-	folder.classList.toggle( "netgis-active" );
-};
-
-/*netgis.LayerTree.prototype.updateFolderCheck = function( folder )
-{
-	var items = folder.getElementsByTagName( "input" );
-	
-	
-};*/
-
-netgis.LayerTree.prototype.onFolderChange = function( e )
-{
-	var checkbox = e.currentTarget;
-	var checked = checkbox.checked;
-	var folder = checkbox.parentElement.parentElement;
-	var items = folder.getElementsByTagName( "input" );
-	//var items = folder.getElementsByClassName( "netgis-folder-item" );
-	
-	//console.info( "Folder Change:", checked, folder, items );
-	
-	// Check Child Items
-	for ( var i = 1; i < items.length; i++ )
-	{
-		var item = items[ i ];
-		var childcheck = item;
-		//var childcheck = item.getElementsByTagName( "input" )[ 0 ];
-		
-		childcheck.checked = checked;
-		
-		//console.info( "Folder Child:", item, childcheck, id, items );
-		
-		//var id = parseInt( childcheck.dataset.id );
-		var id = childcheck.dataset.id;
-		
-		if ( netgis.util.isDefined( id ) )
-		{
-			id = parseInt( id );
-			this.client.invoke( checked ? netgis.Events.LAYER_SHOW : netgis.Events.LAYER_HIDE, { id: id } );
-		}
-	}
-	
-	this.updateFolderChecks( folder );
-	
-	// Check Parent Folder
-	var parentFolder = folder.parentElement.parentElement;
-	if ( parentFolder.className.search( "netgis-folder" ) !== -1 )
-		this.updateFolderChecks( parentFolder );
-};
-
-netgis.LayerTree.prototype.updateFolderChecks = function( folder )
-{
-	if ( ! netgis.util.isDefined( folder ) ) folder = this.list;
-	
-	// Count Child Checks
-	var items = folder.getElementsByClassName( "netgis-folder-item" );
-	
-	var checks = 0;
-	
-	for ( var i = 0; i < items.length; i++ )
-	{
-		var checkbox = items[ i ].getElementsByTagName( "input" )[ 0 ];
-		if ( checkbox.checked ) checks++;
-	}
-	
-	// Set Checkbox State
-	var checkbox = folder.getElementsByTagName( "input" )[ 0 ];
-	
-	var state = 0;
-	if ( checks > 0 ) state = 1;
-	if ( checks === items.length ) state = 2;
-	
-	switch ( state )
-	{
-		case 0:
-		{
-			// Unchecked
-			checkbox.checked = false;
-			checkbox.classList.remove( "netgis-partial" );
-			break;
-		}
-		
-		case 1:
-		{
-			// Partially Checked
-			checkbox.checked = true;
-			checkbox.classList.add( "netgis-partial" );
-			break;
-		}
-		
-		case 2:
-		{
-			// Fully Checked
-			checkbox.checked = true;
-			checkbox.classList.remove( "netgis-partial" );
-			break;
-		}
-	}
-	
-	//TODO: use nearest ancestor selector
-	var parentList = folder.parentElement;
-	
-	if ( parentList && parentList !== this.list )
-	{
-		// Recursion
-		var parentFolder = parentList.parentElement;
-		if ( parentFolder && parentFolder.className.search( "netgis-folder" ) !== -1 )
-			this.updateFolderChecks( parentFolder );
-	}
-};
-
-netgis.LayerTree.prototype.onItemChange = function( e )
-{
-	var checkbox = e.currentTarget;
-	var checked = checkbox.checked;
-	var listitem = checkbox.parentElement.parentElement.parentElement;
-	var id = parseInt( checkbox.dataset.id );
-	var folder = listitem.parentElement.parentElement;
-	var items = folder.getElementsByTagName( "input" );
-	
-	// Check Parent Folder
-	var checks = 0;
-	
-	for ( var i = 1; i < items.length; i++ )
-	{
-		var item = items[ i ];
-		if ( item.checked ) checks++;
-	}
-	
-	if ( folder.className.search( "netgis-folder" ) !== -1 )
-		this.updateFolderChecks( folder );
-	
-	this.client.invoke( checked ? netgis.Events.LAYER_SHOW : netgis.Events.LAYER_HIDE, { id: id } );
-};
-
-netgis.LayerTree.prototype.onLayerListToggle = function( e )
-{
-	this.root.classList.toggle( "netgis-hide" );
-};
-
-netgis.LayerTree.prototype.onContextUpdate = function( e )
-{
-	this.clearAll();
-	
-	var folders = e.folders;
-	var layers = e.layers;
-   
-	// Create Folders
-	var folderItems = [];
-   
-	for ( var f = 0; f < folders.length; f++ )
-	{
-		var folder = folders[ f ];
-		
-		var item = this.createFolder( folder.title );
-		folderItems.push( item );
-	}
-	
-	// Create Layers
-	for ( var l = 0; l < layers.length; l++ )
-	{
-		var layer = layers[ l ];
-		
-		var item = this.createLayer( l, layer.title, layer.active );
-		this.addToFolder( folderItems[ layer.folder ], item );
-	}
-	
-	// Append Folders
-	for ( var f = 0; f < folders.length; f++ )
-	{
-		var folder = folders[ f ];
-		var item = folderItems[ f ];
-		
-		if ( folder.parent === -1 )
-		{
-			this.list.appendChild( item );
-		}
-		else
-		{
-			this.addToFolder( folderItems[ folder.parent ], item );
-		}
-	}
-	
-	// Active State
-	for ( var l = 0; l < layers.length; l++ )
-	{
-		var layer = layers[ l ];
-		if ( layer.active ) this.client.invoke( netgis.Events.LAYER_SHOW, { id: l } );
-	}
-	for ( var f = 0; f < folderItems.length; f++ )
-	{
-		this.updateFolderChecks( folderItems[ f ] );
-	}
-};
-
-netgis.LayerTree.prototype.onLayerCreated = function( e )
-{
-	var item = this.createLayer( e.id, e.title, e.checked );
-	
-	var folder;
-	
-	//TODO: this is a hack to get special folders working	
-	if ( e.folder === "import" )
-	{
-		/*if ( ! this.folderImport )
-		{
-			this.folderImport = this.createFolder( "Importierte Ebenen" );
-			this.list.insertBefore( this.folderImport, this.folderDraw ? this.folderDraw.nextSibling : this.list.firstChild );
-		}
-		*/
-	   
-		this.folderImport.classList.remove( "netgis-hide" );
-	   
-		folder = this.folderImport;
-	}
-	else if ( e.folder === "draw" )
-	{
-		/*if ( ! this.folderDraw )
-		{
-			this.folderDraw = this.createFolder( "Zeichnung" );
-			this.list.insertBefore( this.folderDraw, this.list.firstChild );
-		}*/
-		
-		this.folderDraw.classList.remove( "netgis-hide" );
-		
-		folder = this.folderDraw;
-	}
-	
-	this.addToFolder( folder, item, true );
-	this.updateFolderChecks( folder );
-};
-
-netgis.LayerTree.prototype.onEditFeaturesChange = function( e )
-{
-	// Enable draw layer if not already
-	if ( this.folderDraw )
-	{		
-		var list = this.folderDraw.getElementsByTagName( "ul" )[ 0 ];
-		var checks = list.getElementsByTagName( "input" );
-		var checkbox = checks[ 0 ];
-		var id = parseInt( checkbox.dataset.id );
-		
-		if ( ! checkbox.checked )
-		{
-			checkbox.checked = true;
-
-			this.updateFolderChecks( this.folderDraw );
-			this.client.invoke( netgis.Events.LAYER_SHOW, { id: id } );
-		}
-		
-		// Update Area
-		var label = list.getElementsByTagName( "label" )[ 0 ];
-		var spans = label.getElementsByTagName( "span" );
-		var appendix = spans[ spans.length - 1 ];
-		
-		if ( e.area && e.area > 0.0 )
-		{
-			appendix.innerText = " (Fläche: " + netgis.util.formatArea( e.area, true ) + ")";
-		}
-		else
-		{
-			appendix.innerText = "";
-		}
-	};
-};
-
-netgis.LayerTree.prototype.onAddServiceWMS = function( e )
-{
-	var item = this.createLayer( e.id, e.title, true );
-	
-	this.folderServices.classList.remove( "netgis-hide" );
-	this.addToFolder( this.folderServices, item, true );
-	this.updateFolderChecks( this.folderServices );
-	
-	this.client.invoke( netgis.Events.LAYER_SHOW, { id: e.id } );
-};
-
-netgis.LayerTree.prototype.onAddServiceWFS = function( e )
-{
-	var item = this.createLayer( e.id, e.title, true );
-	
-	this.folderServices.classList.remove( "netgis-hide" );
-	this.addToFolder( this.folderServices, item, true );
-	this.updateFolderChecks( this.folderServices );
-	
-	this.client.invoke( netgis.Events.LAYER_SHOW, { id: e.id } );
-};
-
-netgis.LayerTree.prototype.onSetMode = function( e )
-{
-	if ( e === netgis.Modes.SEARCH_PARCEL )
-	{
-		this.root.classList.add( "netgis-hide" );
-	}
-};
-
-netgis.LayerTree.prototype.onAddServiceClick = function( e )
-{
-	this.client.invoke( netgis.Events.ADD_SERVICE_SHOW, null );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/LayerTypes.js b/templates/map/client/libs/netgis/LayerTypes.js
deleted file mode 100644
index 677a0392..00000000
--- a/templates/map/client/libs/netgis/LayerTypes.js
+++ /dev/null
@@ -1,14 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.LayerTypes = Object.freeze
-(
-	{
-		XYZ: "XYZ",
-		OSM: "OSM",
-		WMS: "WMS",
-		WFS: "WFS",
-		KML: "KML"
-	}
-);
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Map.css b/templates/map/client/libs/netgis/Map.css
deleted file mode 100644
index c9717b05..00000000
--- a/templates/map/client/libs/netgis/Map.css
+++ /dev/null
@@ -1,102 +0,0 @@
-.netgis-map
-{
-	position: absolute;
-	left: 0mm;
-	right: 0mm;
-	top: 12mm;
-	bottom: 0mm;
-	
-	background: #f2efe9;
-}
-
-/* Drag and Drop */
-
-/*
-.netgis-map.drop
-{
-	border: 10mm solid red;
-}
-*/
-
-.netgis-drop-target
-{
-	position: absolute;
-	left: 0mm;
-	right: 0mm;
-	top: 0mm;
-	bottom: 0mm;
-	line-height: 40mm;
-	text-align: center;
-	z-index: 1;
-	pointer-events: none;
-	background: rgba( 0, 0, 0, 0.5 );
-	color: #fff;
-}
-
-.netgis-drop-target.netgis-hide
-{
-	display: none;
-}
-
-/* Modes */
-
-.netgis-map
-{
-	cursor: default;
-}
-
-.netgis-map .netgis-toolbar,
-.netgis-map .netgis-dialog
-{
-	cursor: auto;
-}
-
-.netgis-map.netgis-mode-view,
-.netgis-map.netgis-mode-search-place
-{
-	cursor: default;
-    cursor: grab;
-    cursor: -moz-grab;
-    cursor: -webkit-grab;
-}
-
-.netgis-map.netgis-mode-panning
-{
-	cursor: move;
-	cursor: all-scroll;
-	cursor: grabbing;
-    cursor: -moz-grabbing;
-    cursor: -webkit-grabbing;
-}
-
-.netgis-map.netgis-mode-zooming-in
-{
-	cursor: zoom-in;
-}
-
-.netgis-map.netgis-mode-zooming-out
-{
-	cursor: zoom-out;
-}
-
-.netgis-map.netgis-mode-draw-points,
-.netgis-map.netgis-mode-draw-lines,
-.netgis-map.netgis-mode-draw-polygons,
-.netgis-map.netgis-mode-cut-feature-draw,
-.netgis-map.netgis-mode-modify-features
-{
-	cursor: pointer;
-	cursor: crosshair;
-}
-
-.netgis-map.netgis-mode-delete-features,
-.netgis-map.netgis-mode-cut-feature-begin,
-.netgis-map.netgis-mode-buffer-feature-begin
-{
-	cursor: pointer;
-}
-
-.netgis-map.netgis-mode-buffer-feature-edit
-{
-	cursor: default;
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Map.js b/templates/map/client/libs/netgis/Map.js
deleted file mode 100644
index c2a6ab8d..00000000
--- a/templates/map/client/libs/netgis/Map.js
+++ /dev/null
@@ -1,20 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-//TODO: this common Map class is probably deprecated, no need for inheritance ?
-
-netgis.Map = function()
-{
-	this.client = null;
-	this.root = null;
-	this.attribution = null;
-};
-
-netgis.Map.prototype.load = function()
-{
-	this.root = document.createElement( "section" );
-	this.root.className = "netgis-map";
-	
-	this.client.root.appendChild( this.root );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/MapOpenLayers.js b/templates/map/client/libs/netgis/MapOpenLayers.js
deleted file mode 100644
index 2ec152e8..00000000
--- a/templates/map/client/libs/netgis/MapOpenLayers.js
+++ /dev/null
@@ -1,2321 +0,0 @@
-/* global ol, jsts, shp, proj4 */
-
-"use strict";
-
-var netgis = netgis || {};
-
-/**
- * Map module implementation for OpenLayers 6+.
- */
-netgis.MapOpenLayers = function()
-{
-	netgis.Map.call( this );
-	
-	this.mode = null;
-	this.toolbars = {};
-	this.view = null;
-	this.map = null;
-	this.layers = [];
-	this.interactions = {};
-	this.snap = null;
-	this.snapFeatures = null;
-	this.editLayer = null;
-	this.parcelLayer = null;
-	
-	this.hover = null;
-	this.selected = null;
-	this.sketch = null;
-	
-	this.editEventsSilent = false;
-	
-	this.importLayerID = 20000;
-	this.editLayerID = 30000;
-	this.labelFont = "4mm Verdana, sans-serif";
-	this.drawBufferRadius = 100.0;
-	this.drawBufferSegments = 3;
-};
-
-netgis.MapOpenLayers.prototype = Object.create( netgis.Map.prototype );
-netgis.MapOpenLayers.prototype.constructor = netgis.MapOpenLayers;
-
-//TODO: not much benefits from Map class inheritance, may be dropped soon
-
-netgis.MapOpenLayers.prototype.load = function()
-{
-	// Elements
-	netgis.Map.prototype.load.call( this ); //TODO: ?
-	
-	this.dropTarget = document.createElement( "div" );
-	this.dropTarget.className = "netgis-drop-target netgis-hide";
-	this.dropTarget.innerHTML = "Datei hier ablegen!";
-	this.root.appendChild( this.dropTarget );
-	
-	this.root.addEventListener( "dragenter", this.onDragEnter.bind( this ) );
-	this.root.addEventListener( "dragover", this.onDragEnter.bind( this ) );
-	this.root.addEventListener( "dragend", this.onDragLeave.bind( this ) );
-	this.root.addEventListener( "dragleave", this.onDragLeave.bind( this ) );
-	this.root.addEventListener( "drop", this.onDragDrop.bind( this ) );
-	
-	// Map Renderer
-	this.initMap();
-	this.initDefaultLayers();
-	this.initInteractions();
-	
-	// Events
-	this.client.on( netgis.Events.CONTEXT_UPDATE, this.onContextUpdate.bind( this ) );
-	this.client.on( netgis.Events.MAP_UPDATE_STYLE, this.onUpdateStyle.bind( this ) );
-	this.client.on( netgis.Events.EDIT_FEATURES_LOADED, this.onEditFeaturesLoaded.bind( this ) );
-	this.client.on( netgis.Events.SET_MODE, this.onSetMode.bind( this ) );
-	this.client.on( netgis.Events.SNAP_ON, this.onSnapOn.bind( this ) );
-	this.client.on( netgis.Events.SNAP_OFF, this.onSnapOff.bind( this ) );
-	this.client.on( netgis.Events.TRACING_ON, this.onTracingOn.bind( this ) );
-	this.client.on( netgis.Events.TRACING_OFF, this.onTracingOff.bind( this ) );
-	this.client.on( netgis.Events.LAYER_SHOW, this.onLayerShow.bind( this ) );
-	this.client.on( netgis.Events.LAYER_HIDE, this.onLayerHide.bind( this ) );
-	this.client.on( netgis.Events.MAP_ZOOM_WKT, this.onZoomWKT.bind( this ) );
-	this.client.on( netgis.Events.MAP_SET_EXTENT, this.onSetExtent.bind( this ) );
-	this.client.on( netgis.Events.MAP_CHANGE_ZOOM, this.onChangeZoom.bind( this ) );
-	this.client.on( netgis.Events.BUFFER_CHANGE, this.onBufferChange.bind( this ) );
-	this.client.on( netgis.Events.BUFFER_ACCEPT, this.onBufferAccept.bind( this ) );
-	this.client.on( netgis.Events.BUFFER_CANCEL, this.onBufferCancel.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_GEOJSON, this.onImportGeoJSON.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_GML, this.onImportGML.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_SHAPEFILE, this.onImportShapefile.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_WKT, this.onImportWKT.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_SPATIALITE, this.onImportSpatialite.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_GEOPACKAGE, this.onImportGeopackage.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_PDF, this.onExportPDF.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_JPEG, this.onExportJPEG.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_PNG, this.onExportPNG.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_GIF, this.onExportGIF.bind( this ) );
-	this.client.on( netgis.Events.PARCEL_SHOW_PREVIEW, this.onParcelShowPreview.bind( this ) );
-	this.client.on( netgis.Events.PARCEL_HIDE_PREVIEW, this.onParcelHidePreview.bind( this ) );
-	this.client.on( netgis.Events.ADD_SERVICE_WMS, this.onAddServiceWMS.bind( this ) );
-	this.client.on( netgis.Events.ADD_SERVICE_WFS, this.onAddServiceWFS.bind( this ) );
-	this.client.on( netgis.Events.DRAW_BUFFER_ON, this.onDrawBufferOn.bind( this ) );
-	this.client.on( netgis.Events.DRAW_BUFFER_OFF, this.onDrawBufferOff.bind( this ) );
-	this.client.on( netgis.Events.DRAW_BUFFER_RADIUS_CHANGE, this.onDrawBufferRadiusChange.bind( this ) );
-	this.client.on( netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE, this.onDrawBufferSegmentsChange.bind( this ) );
-};
-
-netgis.MapOpenLayers.prototype.initMap = function()
-{
-	var config = this.client.config;
-	
-	// Projections ( WGS / Lon-Lat supported out of the box )
-	if ( typeof proj4 !== "undefined" )
-	{
-		proj4.defs( config.projections );
-		proj4.defs( "urn:ogc:def:crs:OGC:1.3:CRS84", proj4.defs( "EPSG:4326" ) );
-		ol.proj.proj4.register( proj4 );
-	}
-	
-	// View
-	var viewParams =
-	{
-		projection: config.map.projection,
-		center: config.map.center,
-		minZoom: config.map.minZoom,
-		maxZoom: config.map.maxZoom,
-		zoom: config.map.zoom
-	};
-	
-	this.view = new ol.View
-	(
-		viewParams
-	);
-
-	// Map
-	this.map = new ol.Map
-	(
-		{
-			target: this.root,
-			view: this.view,
-			pixelRatio: 1.0,
-			moveTolerance: 5,
-			controls: [
-				new ol.control.ScaleLine(),
-			]
-		}
-	);
-	
-	this.map.on( "pointermove", this.onPointerMove.bind( this ) );
-	this.map.on( "click", this.onSingleClick.bind( this ) );
-	
-	this.map.on( "movestart", this.onMoveStart.bind( this ) );
-	this.map.on( "moveend", this.onMoveEnd.bind( this ) );
-	
-	this.view.on( "change:resolution", this.onChangeResolution.bind( this ) );
-};
-
-netgis.MapOpenLayers.prototype.initDefaultLayers = function()
-{
-	//TODO: why id as z index ?
-	
-	this.editLayer = new ol.layer.Vector( { source: new ol.source.Vector( { features: [] } ), style: this.styleEdit.bind( this ), zIndex: this.editLayerID } );
-	this.map.addLayer( this.editLayer );
-	
-	this.previewLayer = new ol.layer.Vector( { source: new ol.source.Vector( { features: [] } ), style: this.styleSketch.bind( this ), zIndex: this.editLayerID + 10 } );
-	this.map.addLayer( this.previewLayer );
-	
-	this.parcelLayer = new ol.layer.Vector( { source: new ol.source.Vector( { features: [] } ), style: this.styleParcel.bind( this ), zIndex: this.editLayerID + 20 } );
-	this.map.addLayer( this.parcelLayer );
-	
-	this.editEventsOn();
-};
-
-netgis.MapOpenLayers.prototype.editEventsOn = function()
-{
-	this.editLayer.getSource().on( "addfeature", this.onEditLayerAdd.bind( this ) );
-	//this.editLayer.getSource().on( "changefeature", this.onEditLayerChange.bind( this ) ); //TODO: fired on feature style change? use only one style function with selected/hover states?
-	this.editLayer.getSource().on( "removefeature", this.onEditLayerRemove.bind( this ) );
-};
-
-netgis.MapOpenLayers.prototype.editEventsOff = function()
-{
-	//NOTE: this doesn't work because OL does not allow removing all listeners and listener function ref is changed by binding
-	//NOTE: see this.editEventsCommit
-	
-	//this.editLayer.getSource().un( "addfeature"/*, this.onEditLayerAdd*/ );
-	//this.editLayer.getSource().un( "changefeature", this.onEditLayerChange.bind( this ) ); //TODO: fired on feature style change? use only one style function with selected/hover states?
-	//this.editLayer.getSource().un( "removefeature"/*, this.onEditLayerRemove*/ );
-};
-
-netgis.MapOpenLayers.prototype.initInteractions = function()
-{
-	// View
-	this.interactions[ netgis.Modes.VIEW ] =
-	[
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.PANNING ] = this.interactions[ netgis.Modes.VIEW ];
-	this.interactions[ netgis.Modes.ZOOMING_IN ] = this.interactions[ netgis.Modes.VIEW ];
-	this.interactions[ netgis.Modes.ZOOMING_OUT ] = this.interactions[ netgis.Modes.VIEW ];
-	
-	// Draw
-	this.interactions[ netgis.Modes.DRAW_POINTS ] =
-	[
-		new ol.interaction.Draw( { type: "Point", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ) } ),
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.DRAW_POINTS ][ 0 ].on( "drawend", this.onDrawPointsEnd.bind( this ) );
-	
-	this.interactions[ netgis.Modes.DRAW_LINES ] =
-	[
-		new ol.interaction.Draw( { type: "LineString", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ) } ),
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.DRAW_LINES ][ 0 ].on( "drawend", this.onDrawLinesEnd.bind( this ) );
-	
-	this.interactions[ netgis.Modes.DRAW_POLYGONS ] =
-	[
-		new ol.interaction.Draw( { type: "Polygon", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ) } ),
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	// Edit
-	this.interactions[ netgis.Modes.CUT_FEATURE_BEGIN ] =
-	[
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.CUT_FEATURE_DRAW ] =
-	[
-		new ol.interaction.Draw( { type: "Polygon" /*, source: this.editLayer.getSource()*/, style: this.styleSketch.bind( this ) } ),
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.CUT_FEATURE_DRAW ][ 0 ].on( "drawend", this.onCutFeatureDrawEnd.bind( this ) );
-	
-	this.interactions[ netgis.Modes.MODIFY_FEATURES ] =
-	[
-		new ol.interaction.Modify( { source: this.editLayer.getSource(), deleteCondition: ol.events.condition.doubleClick, style: this.styleModify.bind( this ) } ),
-		new ol.interaction.DragPan( { condition: function( e ) { return ( e.originalEvent.which === 2 ); } } ),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.MODIFY_FEATURES ][ 0 ].on( "modifyend", this.onModifyFeaturesEnd.bind( this ) );
-	
-	this.interactions[ netgis.Modes.DELETE_FEATURES ] =
-	[
-		//new ol.interaction.Select( { layers: [ this.editLayer ], addCondition: ol.events.condition.pointerMove } ),
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.BUFFER_FEATURE_BEGIN ] =
-	[
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.BUFFER_FEATURE_EDIT ] =
-	[
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	// Snapping
-	this.snapFeatures = new ol.Collection();
-	
-	// Search
-	this.interactions[ netgis.Modes.SEARCH_PLACE ] =
-	[
-		new ol.interaction.DragPan(),
-		new ol.interaction.MouseWheelZoom()
-	];
-	
-	this.interactions[ netgis.Modes.SEARCH_PARCEL ] = this.interactions[ netgis.Modes.VIEW ];
-};
-
-netgis.MapOpenLayers.prototype.createLayer = function( data )
-{
-	var layer = null;
-	
-	// Create Specific Layer By Type
-	switch ( data.type )
-	{
-		case netgis.LayerTypes.XYZ:
-		{			
-			layer = this.createLayerXYZ( data.url );
-			break;
-		}
-		
-		case netgis.LayerTypes.OSM:
-		{
-			layer = this.createLayerOSM();
-			break;
-		}
-		
-		case netgis.LayerTypes.WMS:
-		{
-			layer = this.createLayerWMS( data.url, data.name, data.format, data.username, data.password );
-			break;
-		}
-		
-		case netgis.LayerTypes.WFS:
-		{
-			layer = this.createLayerWFS( data.url, data.name, this.client.config.map.projection, data.outputFormat, data.username, data.password );
-			break;
-		}
-	}
-	
-	// Common Settings
-	if ( layer )
-	{
-		if ( data.minZoom ) layer.setMinZoom( Number.parseFloat( data.minZoom ) - 1.0 );
-		if ( data.maxZoom ) layer.setMaxZoom( Number.parseFloat( data.maxZoom ) );
-	}
-	
-	return layer;
-};
-
-netgis.MapOpenLayers.prototype.createLayerXYZ = function( url )
-{
-	var layer = new ol.layer.Tile
-	(
-		{
-			source: new ol.source.XYZ
-			(
-				{
-					url: url,
-					crossOrigin: "anonymous"
-				}
-			)
-		}
-	);
-	
-	return layer;
-};
-
-netgis.MapOpenLayers.prototype.createLayerOSM = function()
-{
-	var layer = new ol.layer.Tile
-	(
-		{
-			source: new ol.source.XYZ
-			(
-				{
-					url: "https://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png",
-					crossOrigin: "anonymous"
-				}
-			)
-		}
-	);
-	
-	return layer;
-};
-
-netgis.MapOpenLayers.prototype.createLayerWMS = function( url, layerName, format, user, password )
-{	
-	var params =
-	{
-		url: url,
-		params:
-		{
-			"LAYERS":		layerName,
-			"FORMAT":		format ? format : "image/png",
-			"TRANSPARENT":	"true",
-			"VERSION":		"1.1.1"
-		},
-		serverType: "mapserver",
-		crossOrigin: "anonymous",
-		hidpi: false
-		//ratio: 3.0
-	};
-
-	// User Auth
-	if ( user && password )
-	{
-		params.imageLoadFunction = function( image, src )
-		{
-			var request = new XMLHttpRequest();
-			request.open( "GET", src );
-			request.setRequestHeader( "Authorization", "Basic " + window.btoa( user + ":" + password ) );
-
-			request.onload = function()
-			{
-				image.getImage().src = src;
-			};
-
-			request.send();
-		};
-	}
-
-	var source = new ol.source.ImageWMS( params );
-
-	var layer = new ol.layer.Image
-	(
-		{
-			source:	source,
-			//zIndex: index,
-			opacity: 1.0
-		}
-	);
-	
-	return layer;
-};
-
-netgis.MapOpenLayers.prototype.createLayerWFS = function( url, typeName, projection, outputFormat, user, password )
-{
-	url = url
-			+ "service=WFS"
-			+ "&version=1.1.0"
-			+ "&request=GetFeature";
-			
-	if ( ! outputFormat )
-		outputFormat = "application/json";
-	else
-		outputFormat = netgis.util.replace( outputFormat, " ", "+" ); //TODO: encode uri component ?
-
-	var source = new ol.source.Vector
-	(
-		{
-			format: new ol.format.GeoJSON(),
-			strategy: ol.loadingstrategy.bbox,
-			
-			loader: function( extent, resolution, proj, success, failure )
-			{
-				//proj = proj.getCode();
-				
-				var requestURL = url
-									+ "&typename=" + typeName
-									+ "&srsname=" + projection
-									+ "&bbox=" + extent.join( "," ) + "," + projection
-									+ "&outputFormat=" + outputFormat;
-				
-				var request = new XMLHttpRequest();
-				request.open( "GET", requestURL );
-				
-				if ( user && password )
-				{
-					request.setRequestHeader( "Authorization", "Basic " + window.btoa( user + ":" + password ) );
-				}
-				
-				request.onerror = function()
-				{
-					console.error( "WFS Request Error" );
-					failure();
-				};
-				
-				request.onload = function()
-				{
-					if ( request.status === 200 )
-					{
-						var features = source.getFormat().readFeatures( request.responseText );
-						source.addFeatures( features );
-						success( features );
-					}
-					else
-					{
-						console.error( "WFS Request Status", request.status );
-						failure();
-					}
-				};
-				
-				request.send();
-			}
-		}
-	);
-
-	var layer = new ol.layer.Vector
-	(
-		{
-			source: source
-		}
-	);
-
-	var self = this;
-	source.on( "featuresloadstart", function( e ) { self.removeSnapLayer( layer ); } );
-	source.on( "featuresloadend", function( e ) { window.setTimeout( function() { self.addSnapLayer( layer ); }, 10 ); } );
-	//source.on( "featuresloaderror", function( e ) { console.info( "Layer Error:", e ); } );
-	
-	return layer;
-};
-
-netgis.MapOpenLayers.prototype.clearAll = function()
-{
-	for ( var i = 0; i < this.layers.length; i++ )
-	{
-		this.map.removeLayer( this.layers[ i ] );
-	}
-	
-	this.layers = [];
-	
-	this.snapFeatures.clear();
-};
-
-netgis.MapOpenLayers.prototype.onUpdateStyle = function( e )
-{
-	var style = new ol.style.Style
-	(
-		{
-			//image: new ol.style.Circle( { radius: 7, fill: new ol.style.Fill( { color: "#ff0000" } ) } ),
-			fill: new ol.style.Fill( { color: e.polygon.fill } ),
-			stroke: new ol.style.Stroke( { color: e.polygon.stroke, width: e.polygon.strokeWidth } )
-		}
-	);
-	
-	this.editLayer.setStyle( style );
-};
-
-netgis.MapOpenLayers.prototype.styleEdit = function( feature )
-{
-	var radius = this.client.config.styles.editLayer.pointRadius;
-	var geom = feature.getGeometry();
-	
-	var style = new ol.style.Style
-	(
-		{
-			image: new ol.style.Circle( { radius: radius, fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.stroke } ) } ),
-			fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.fill } ),
-			stroke: new ol.style.Stroke( { color: this.client.config.styles.editLayer.stroke, width: this.client.config.styles.editLayer.strokeWidth } )
-		}
-	);
-	
-	if ( geom instanceof ol.geom.Polygon )
-	{
-		var area = geom.getArea();
-		
-		style.setText
-		(
-			new ol.style.Text
-			(
-				{
-					text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
-					font: this.labelFont,
-					fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.stroke } ),
-					backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
-					padding: [ 2, 4, 2, 4 ]
-				}
-			)
-		);
-	}
-	
-	return style;
-};
-
-netgis.MapOpenLayers.prototype.styleSelect = function( feature )
-{
-	var geom = feature.getGeometry();
-	
-	var style = new ol.style.Style
-	(
-		{
-			image: new ol.style.Circle( { radius: this.client.config.styles.select.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.select.stroke } ) } ),
-			fill: new ol.style.Fill( { color: this.client.config.styles.select.fill } ),
-			stroke: new ol.style.Stroke( { color: this.client.config.styles.select.stroke, width: this.client.config.styles.select.strokeWidth } )
-		}
-	);
-	
-	if ( geom instanceof ol.geom.Polygon )
-	{
-		var area = geom.getArea();
-		
-		style.setText
-		(
-			new ol.style.Text
-			(
-				{
-					text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
-					font: this.labelFont,
-					fill: new ol.style.Fill( { color: this.client.config.styles.select.stroke } ),
-					backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
-					padding: [ 2, 4, 2, 4 ]
-				}
-			)
-		);
-	}
-	
-	return style;
-};
-
-netgis.MapOpenLayers.prototype.styleModify = function( feature )
-{
-	var style = new ol.style.Style
-	(
-		{
-			image: new ol.style.Circle( { radius: this.client.config.styles.modify.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.modify.stroke } ) } ),
-			fill: new ol.style.Fill( { color: this.client.config.styles.modify.fill } ),
-			stroke: new ol.style.Stroke( { color: this.client.config.styles.modify.stroke, width: this.client.config.styles.modify.strokeWidth } )
-		}
-	);
-	
-	var vertex = new ol.style.Style
-	(
-		{
-			image: new ol.style.Circle( { radius: this.client.config.styles.modify.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.modify.stroke } ) } ),
-			geometry: this.getGeometryPoints( feature )
-		}
-	);
-	
-	var geom = feature.getGeometry();
-	
-	if ( geom instanceof ol.geom.Polygon )
-	{
-		var area = geom.getArea();
-		
-		style.setText
-		(
-			new ol.style.Text
-			(
-				{
-					text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
-					font: this.labelFont,
-					fill: new ol.style.Fill( { color: this.client.config.styles.modify.stroke } ),
-					backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
-					padding: [ 2, 4, 2, 4 ]
-				}
-			)
-		);
-	}
-	
-	return [ style, vertex ];
-};
-
-netgis.MapOpenLayers.prototype.styleSketch = function( feature )
-{	
-	var geom = feature.getGeometry();
-	
-	var style = new ol.style.Style
-	(
-		{
-			image: new ol.style.Circle( { radius: this.client.config.styles.sketch.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.sketch.stroke } ) } ),
-			fill: new ol.style.Fill( { color: this.client.config.styles.sketch.fill } ),
-			stroke: new ol.style.Stroke( { color: this.client.config.styles.sketch.stroke, width: this.client.config.styles.sketch.strokeWidth } )
-		}
-	);
-	
-	if ( geom instanceof ol.geom.Polygon )
-	{
-		var area = geom.getArea();
-		
-		style.setText
-		(
-			new ol.style.Text
-			(
-				{
-					text: [ netgis.util.formatArea( area, true ), "4mm sans-serif" ],
-					font: this.labelFont,
-					fill: new ol.style.Fill( { color: this.client.config.styles.sketch.stroke } ),
-					backgroundFill: new ol.style.Fill( { color: "rgba( 255, 255, 255, 0.5 )" } ),
-					padding: [ 2, 4, 2, 4 ]
-				}
-			)
-		);
-	}
-	
-	var vertex = new ol.style.Style
-	(
-		{
-			image: new ol.style.Circle( { radius: this.client.config.styles.sketch.pointRadius, fill: new ol.style.Fill( { color: this.client.config.styles.sketch.stroke } ) } ),
-			geometry: this.getGeometryPoints( feature )
-		}
-	);
-	
-	return [ style, vertex ];
-};
-
-netgis.MapOpenLayers.prototype.styleParcel = function()
-{
-	//var radius = this.client.config.styles.editLayer.pointRadius;
-	
-	var style = new ol.style.Style
-	(
-		{
-			//image: new ol.style.Circle( { radius: radius, fill: new ol.style.Fill( { color: this.client.config.styles.editLayer.stroke } ) } ),
-			fill: new ol.style.Fill( { color: this.client.config.styles.parcel.fill } ),
-			stroke: new ol.style.Stroke( { color: this.client.config.styles.parcel.stroke, width: this.client.config.styles.parcel.strokeWidth } )
-		}
-	);
-	
-	return style;
-};
-
-netgis.MapOpenLayers.prototype.getGeometryPoints = function( feature )
-{
-	var geometry = feature.getGeometry();
-
-	if ( geometry instanceof ol.geom.LineString )
-	{
-		return new ol.geom.MultiPoint( geometry.getCoordinates() );
-	}
-	else if ( geometry instanceof ol.geom.Polygon )
-	{
-		//return new ol.geom.MultiPoint( geometry.getCoordinates()[ 0 ] );
-
-		var points = [];
-		var geomCoords = geometry.getCoordinates();
-
-		for ( var g = 0; g < geomCoords.length; g++ )
-		{
-			var coords = geomCoords[ g ];
-
-			for ( var c = 0; c < coords.length; c++ )
-				points.push( coords[ c ] );
-		}
-
-		return new ol.geom.MultiPoint( points );
-	}
-	else if ( geometry instanceof ol.geom.MultiPolygon )
-	{
-		var points = [];
-		var polys = geometry.getPolygons();
-		
-		for ( var l = 0; l < polys.length; l++ )
-		{
-			var geomCoords = polys[ l ].getCoordinates();
-
-			for ( var g = 0; g < geomCoords.length; g++ )
-			{
-				var coords = geomCoords[ g ];
-
-				for ( var c = 0; c < coords.length; c++ )
-					points.push( coords[ c ] );
-			}
-		}
-		
-		return new ol.geom.MultiPoint( points );
-	}
-	else if ( geometry instanceof ol.geom.MultiLineString )
-	{
-		var points = [];
-		var lines = geometry.getPolygons();
-		
-		for ( var l = 0; l < lines.length; l++ )
-		{
-			var geomCoords = lines[ l ].getCoordinates();
-
-			for ( var g = 0; g < geomCoords.length; g++ )
-			{
-				var coords = geomCoords[ g ];
-
-				for ( var c = 0; c < coords.length; c++ )
-					points.push( coords[ c ] );
-			}
-		}
-		
-		return new ol.geom.MultiPoint( points );
-	}
-	
-	return geometry;
-};
-
-netgis.MapOpenLayers.prototype.getActiveVectorLayers = function()
-{
-	var vectorLayers = [];
-	var mapLayers = this.map.getLayers().getArray();
-	
-	var layers = this.layers; // this.map.getLayers().getArray();
-	
-	for ( var i = 0; i < layers.length; i++ )
-	{
-		//console.info( "Layer:", layers[ i ] );
-		
-		var layer = layers[ i ];
-		
-		if ( layer instanceof ol.layer.Vector && mapLayers.indexOf( layer ) > -1 )
-		{
-			vectorLayers.push( layer );
-		}
-	}
-	
-	return vectorLayers;
-};
-
-netgis.MapOpenLayers.prototype.setMode = function( mode )
-{
-	// Leave
-	switch ( this.mode )
-	{
-		case netgis.Modes.BUFFER_FEATURE_EDIT:
-		{
-			this.onBufferCancel( null );
-			break;
-		}
-		
-		case netgis.Modes.DRAW_POINTS:
-		case netgis.Modes.DRAW_LINES:
-		{
-			this.onDrawBufferOff( null );
-			break;
-		}
-	}
-	
-	// Enter
-	switch ( mode )
-	{
-	}
-	
-	// Interactions
-	this.map.getInteractions().clear();
-	
-	var interactions = this.interactions[ mode ];
-	
-	if ( interactions )
-	{
-		for ( var i = 0; i < interactions.length; i++ )
-		{
-			this.map.addInteraction( interactions[ i ] );
-		}
-	}
-	
-	//TODO: set to default pan interactions when none found for mode ?
-	
-	if ( this.snap )
-	{
-		if ( mode === netgis.Modes.DRAW_POINTS || mode === netgis.Modes.DRAW_LINES || mode === netgis.Modes.DRAW_POLYGONS )
-		{
-			this.map.addInteraction( this.snap );
-		}
-	}
-	
-	// Style	
-	switch ( mode )
-	{
-		default:
-		{
-			this.editLayer.setStyle( this.styleEdit.bind( this ) );
-			break;
-		}
-		
-		case netgis.Modes.MODIFY_FEATURES:
-		{
-			this.editLayer.setStyle( this.styleModify.bind( this ) );
-			break;
-		}
-	};
-	
-	// Cursors
-	if ( this.mode ) this.root.classList.remove( this.getModeClassName( this.mode ) );
-	if ( mode ) this.root.classList.add( this.getModeClassName( mode ) );
-	
-	this.mode = mode;
-};
-
-netgis.MapOpenLayers.prototype.getModeClassName = function( mode )
-{
-	var modeClass = mode.toLowerCase();
-	//modeClass = modeClass.replace( "_", "-" );
-	modeClass = netgis.util.replace( modeClass, "_", "-" );
-	modeClass = "netgis-mode-" + modeClass;
-	
-	return modeClass;
-};
-
-netgis.MapOpenLayers.prototype.setSnapOn = function()
-{
-	//this.snapFeatures = new ol.Collection();
-	this.snap = new ol.interaction.Snap( { features: this.snapFeatures } );
-	this.map.addInteraction( this.snap );
-	
-	this.snapFeatures.changed();
-	
-	//this.updateSnapLayers();
-	
-	//TODO: https://openlayers.org/en/latest/examples/tracing.html
-};
-
-netgis.MapOpenLayers.prototype.setSnapOff = function()
-{
-	if ( this.snap )
-	{
-		this.map.removeInteraction( this.snap );
-		this.snap = null;
-		//this.snapFeatures = null;
-	}
-};
-
-netgis.MapOpenLayers.prototype.setTracingOn = function()
-{
-	var source = new ol.source.Vector( { features: this.snapFeatures } );
-	
-	this.tracing = new ol.interaction.Draw( { type: "Polygon", source: this.editLayer.getSource(), style: this.styleSketch.bind( this ), trace: true, traceSource: source } );
-
-	var actions = this.interactions[ netgis.Modes.DRAW_POLYGONS ];
-	actions[ 0 ].setActive( false );
-	actions.push( this.tracing );
-	
-	this.setMode( this.mode );
-};
-
-netgis.MapOpenLayers.prototype.setTracingOff = function()
-{
-	var actions = this.interactions[ netgis.Modes.DRAW_POLYGONS ];
-	actions[ 0 ].setActive( true );
-	actions.splice( actions.indexOf( this.tracing ), 1 );
-	
-	this.setMode( this.mode );
-};
-
-/*
-netgis.MapOpenLayers.prototype.updateSnapLayers = function()
-{
-	var snapLayers = this.getActiveVectorLayers();
-	
-	this.snapFeatures.clear();
-	
-	if ( snapLayers.length > 0 )
-	{
-		for ( var i = 0; i < snapLayers.length; i++ )
-		{
-			var layerFeatures = snapLayers[ i ].getSource().getFeatures();
-			
-			for ( var j = 0; j < layerFeatures.length; j++ )
-			{
-				this.snapFeatures.push( layerFeatures[ j ] );
-			}
-		}
-		
-		console.info( "Snap Features:", this.snapFeatures.getLength() );
-	}
-};
-*/
-
-netgis.MapOpenLayers.prototype.addSnapLayer = function( vectorLayer )
-{
-	var layerFeatures = vectorLayer.getSource().getFeatures();
-			
-	for ( var j = 0; j < layerFeatures.length; j++ )
-	{
-		this.snapFeatures.push( layerFeatures[ j ] );
-	}
-};
-
-netgis.MapOpenLayers.prototype.removeSnapLayer = function( vectorLayer )
-{
-	var layerFeatures = vectorLayer.getSource().getFeatures();
-			
-	for ( var j = 0; j < layerFeatures.length; j++ )
-	{
-		this.snapFeatures.remove( layerFeatures[ j ] );
-	}
-};
-
-netgis.MapOpenLayers.prototype.onSnapOn = function( e )
-{
-	this.setSnapOn();
-};
-
-netgis.MapOpenLayers.prototype.onSnapOff = function( e )
-{
-	this.setSnapOff();
-};
-
-netgis.MapOpenLayers.prototype.onTracingOn = function( e )
-{
-	this.setTracingOn();
-};
-
-netgis.MapOpenLayers.prototype.onTracingOff = function( e )
-{
-	this.setTracingOff();
-};
-
-netgis.MapOpenLayers.prototype.onLayerShow = function( e )
-{
-	var layer = this.layers[ e.id ];
-	
-	if ( ! layer ) return;
-	
-	this.map.addLayer( layer );
-	
-	//if ( /*this.snap &&*/ layer instanceof ol.layer.Vector ) this.addSnapLayer( layer ); //this.updateSnapLayers();
-	
-	if ( layer instanceof ol.layer.Vector ) this.addSnapLayer( layer );
-};
-
-netgis.MapOpenLayers.prototype.onLayerHide = function( e )
-{
-	var layer = this.layers[ e.id ];
-	
-	if ( ! layer ) return;
-	
-	this.map.removeLayer( layer );
-	
-	if ( layer instanceof ol.layer.Vector ) this.removeSnapLayer( layer ); //this.updateSnapLayers();
-};
-
-netgis.MapOpenLayers.prototype.onContextUpdate = function( e )
-{
-	this.clearAll();
-	
-	var context = e;
-	
-	// Bounding Box
-	var bbox = context.bbox;
-	
-	if ( bbox )
-	{
-		var bbox1;
-		var bbox2;
-		
-		if ( netgis.util.isDefined( this.client.config.map ) && netgis.util.isDefined( this.client.config.map.projection ) )
-		{
-			bbox1 = ol.proj.fromLonLat( [ bbox[ 0 ], bbox[ 1 ] ], this.client.config.map.projection );
-			bbox2 = ol.proj.fromLonLat( [ bbox[ 2 ], bbox[ 3 ] ], this.client.config.map.projection );
-		}
-		else
-		{
-			bbox1 = ol.proj.fromLonLat( [ bbox[ 0 ], bbox[ 1 ] ] );
-			bbox2 = ol.proj.fromLonLat( [ bbox[ 2 ], bbox[ 3 ] ] );
-		}
-
-		bbox[ 0 ] = bbox1[ 0 ];
-		bbox[ 1 ] = bbox1[ 1 ];
-		bbox[ 2 ] = bbox2[ 0 ];
-		bbox[ 3 ] = bbox2[ 1 ];
-
-		this.view.fit( bbox );
-	}
-	
-	// Layers
-	//this.layers = [];
-	
-	for ( var l = 0; l < context.layers.length; l++ )
-	//for ( var l = context.layers.length - 1; l >= 0; l-- )
-	{
-		var data = context.layers[ l ];
-		var layer = this.createLayer( data );
-		
-		if ( layer )
-		{
-			layer.setZIndex( context.layers.length - l );
-			//this.layers.push( layer );
-			this.layers[ l ] = layer;
-		}
-	}
-	
-	//this.map.getLayers().clear();
-	
-	//TODO: active layers from context?
-	
-	// Active State
-	/*for ( var l = 0; l < context.layers.length; l++ )
-	{
-		var data = context.layers[ l ];
-		if ( data.active ) this.onLayerShow( { id: l } );
-	}*/
-};
-
-netgis.MapOpenLayers.prototype.onAddServiceWMS = function( e )
-{
-	var layer = this.createLayerWMS( e.url, e.name, e.format );
-	layer.setZIndex( e.id );
-	this.layers[ e.id ] = layer;
-};
-
-netgis.MapOpenLayers.prototype.onAddServiceWFS = function( e )
-{
-	var layer = this.createLayerWFS( e.url, e.name, this.client.config.map.projection, e.format );
-	layer.setZIndex( e.id );
-	this.layers[ e.id ] = layer;
-};
-
-netgis.MapOpenLayers.prototype.onSetMode = function( e )
-{
-	this.setMode( e );
-};
-
-netgis.MapOpenLayers.prototype.onSetExtent = function( e )
-{
-	var minxy = ol.proj.fromLonLat( [ e.minx, e.miny ], this.client.config.map.projection );
-	var maxxy = ol.proj.fromLonLat( [ e.maxx, e.maxy ], this.client.config.map.projection );
-	
-	this.view.fit( [ minxy[ 0 ], minxy[ 1 ], maxxy[ 0 ], maxxy[ 1 ] ] );
-};
-
-netgis.MapOpenLayers.prototype.onChangeZoom = function( e )
-{
-	var delta = e;
-	this.view.animate( { zoom: this.view.getZoom() + delta, duration: 200 } );
-};
-
-netgis.MapOpenLayers.prototype.onZoomWKT = function( e )
-{
-	var parser = new ol.format.WKT();
-	var geom = parser.readGeometry( e );
-	var padding = 40;
-	
-	this.view.fit( geom, { duration: 300, padding: [ padding, padding, padding, padding ] } );
-	
-	//TODO: take visible panels into account when zooming
-};
-
-netgis.MapOpenLayers.prototype.onPointerMove = function( e )
-{
-	var pixel = e.pixel;
-	var coords = e.coordinate;
-	
-	var hover = this.hover;
-	var styleSelect = this.styleSelect.bind( this );
-	
-	if ( hover )
-	{
-		hover.setStyle( this.styleEdit.bind( this ) );
-		hover = null;
-	}
-	
-	var self = this;
-	
-	switch ( this.mode )
-	{
-		case netgis.Modes.DELETE_FEATURES:
-		{
-			this.map.forEachFeatureAtPixel
-			(
-				pixel,
-				function( feature, layer ) //TODO: bind to this?
-				{
-					if ( layer === self.editLayer )
-					{
-						hover = feature;
-						feature.setStyle( styleSelect );
-					}
-					
-					return true;
-				}
-			);
-			
-			break;
-		}
-		
-		case netgis.Modes.CUT_FEATURE_BEGIN:
-		{
-			this.map.forEachFeatureAtPixel
-			(
-				pixel,
-				function( feature, layer ) //TODO: bind to this?
-				{
-					if ( layer === self.editLayer )
-					{
-						hover = feature;
-						feature.setStyle( styleSelect );
-					}
-					
-					return true;
-				}
-			);
-			
-			break;
-		}
-		
-		case netgis.Modes.BUFFER_FEATURE_BEGIN:
-		{
-			this.map.forEachFeatureAtPixel
-			(
-				pixel,
-				function( feature, layer ) //TODO: bind to this?
-				{
-					if ( layer === self.editLayer )
-					{
-						hover = feature;
-						feature.setStyle( styleSelect );
-					}
-					
-					return true;
-				}
-			);
-			
-			break;
-		}
-		
-		case netgis.Modes.DRAW_POINTS:
-		case netgis.Modes.DRAW_LINES:
-		{
-			this.updateDrawBufferPreview();
-			break;
-		}
-	}
-	
-	//TODO: refactor to default hover handler?
-	
-	this.hover = hover;
-};
-
-netgis.MapOpenLayers.prototype.onSingleClick = function( e )
-{
-	switch ( this.mode )
-	{
-		case netgis.Modes.DELETE_FEATURES:
-		{
-			if ( this.hover )
-			{
-				this.editLayer.getSource().removeFeature( this.hover );
-				this.hover = null;
-				
-				this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-			}
-			
-			break;
-		}
-		
-		case netgis.Modes.CUT_FEATURE_BEGIN:
-		{
-			if ( this.hover )
-			{
-				this.selected = this.hover;
-				this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.CUT_FEATURE_DRAW );
-			}
-			
-			break;
-		}
-		
-		case netgis.Modes.BUFFER_FEATURE_BEGIN:
-		{
-			if ( this.hover )
-			{
-				this.selected = this.hover;
-				this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.BUFFER_FEATURE_EDIT );
-			}
-			
-			break;
-		}
-	}
-};
-
-netgis.MapOpenLayers.prototype.onMoveStart = function( e )
-{
-	//TODO: problem with toolbars after head menu click
-	//this.client.invoke( netgis.Events.MAP_SET_MODE, netgis.MapModes.PANNING );
-};
-
-netgis.MapOpenLayers.prototype.onMoveEnd = function( e )
-{
-	//TODO: problem with toolbars after head menu click
-	//this.client.invoke( netgis.Events.MAP_SET_MODE, netgis.MapModes.VIEW );
-};
-
-netgis.MapOpenLayers.prototype.onChangeResolution = function( e )
-{
-	//var d = e.oldValue - this.view.getResolution();
-	//this.client.invoke( netgis.Events.MAP_SET_MODE, ( d > 0.0 ) ? netgis.MapModes.ZOOMING_IN : netgis.MapModes.ZOOMING_OUT );
-};
-
-netgis.MapOpenLayers.prototype.onCutFeatureDrawEnd = function( e )
-{
-	var cutter = e.feature;
-	var target = this.selected;
-	
-	if ( target )
-	{
-		// Cut Process
-		var parser = new jsts.io.OL3Parser();
-		
-		var a = parser.read( target.getGeometry() );
-		var b = parser.read( cutter.getGeometry() );
-		
-		var c = a.difference( b );
-		
-		// Output
-		var geom = parser.write( c );
-		var feature = new ol.Feature( { geometry: geom } );
-		
-		var source = this.editLayer.getSource();
-		source.removeFeature( target );
-		source.addFeature( feature );
-		
-		this.selected = feature;
-	}
-	
-	this.editEventsSilent = true;
-	this.splitMultiPolygons( this.editLayer );
-	this.editEventsSilent = false;
-	this.updateEditOutput();
-	
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-};
-
-netgis.MapOpenLayers.prototype.onModifyFeaturesEnd = function( e )
-{
-	this.updateEditOutput();
-	this.updateEditArea();
-};
-
-netgis.MapOpenLayers.prototype.createBufferFeature = function( srcgeom, radius, segments )
-{
-	var geom = this.createBufferGeometry( srcgeom, radius, segments );
-	var feature = new ol.Feature( { geometry: geom } );
-	
-	return feature;
-};
-
-netgis.MapOpenLayers.prototype.createBufferGeometry = function( srcgeom, radius, segments )
-{
-	var parser = new jsts.io.OL3Parser();
-		
-	var a = parser.read( srcgeom );
-	var b = a.buffer( radius, segments );
-	
-	var geom = parser.write( b );
-	
-	return geom;
-};
-
-netgis.MapOpenLayers.prototype.onBufferChange = function( e )
-{
-	var source = this.editLayer.getSource();
-	var target = this.selected;
-	
-	if ( this.sketch )
-	{
-		source.removeFeature( this.sketch );
-	}
-	
-	if ( target )
-	{
-		var feature = this.createBufferFeature( target.getGeometry(), e.radius, e.segments );
-		
-		//source.removeFeature( target );
-		source.addFeature( feature );
-		
-		this.sketch = feature;
-	}
-};
-
-netgis.MapOpenLayers.prototype.onBufferAccept = function( e )
-{
-	if ( this.selected && this.sketch )
-	{
-		var source = this.editLayer.getSource();
-		
-		// Delete Input Feature
-		//if ( ! ( this.selected.getGeometry() instanceof ol.geom.Point ) )
-			source.removeFeature( this.selected );
-	}
-	
-	this.sketch = null;
-	this.selected = null;
-};
-
-netgis.MapOpenLayers.prototype.onBufferCancel = function( e )
-{
-	if ( this.sketch )
-	{
-		this.editLayer.getSource().removeFeature( this.sketch );
-		this.sketch = null;
-	}
-	
-	this.selected = null;
-};
-
-netgis.MapOpenLayers.prototype.onDrawPointsEnd = function( e )
-{
-	var preview = this.previewLayer.getSource().getFeatures()[ 0 ];
-	
-	if ( preview )
-	{
-		var src = this.editLayer.getSource();
-		
-		// Add Buffer Feature
-		src.addFeature( preview.clone() );
-		
-		// Remove Sketch Feature
-		window.setTimeout
-		(
-			function()
-			{
-				src.removeFeature( e.feature );
-			},
-			10
-		);
-	}
-};
-
-netgis.MapOpenLayers.prototype.onDrawLinesEnd = function( e )
-{
-	var preview = this.previewLayer.getSource().getFeatures()[ 0 ];
-	
-	if ( preview )
-	{
-		var src = this.editLayer.getSource();
-		
-		// Add Buffer Feature
-		src.addFeature( preview.clone() );
-	
-		// Remove Sketch Feature
-		window.setTimeout
-		(
-			function()
-			{
-				src.removeFeature( e.feature );
-			},
-			10
-		);
-	}
-};
-
-netgis.MapOpenLayers.prototype.onDrawBufferOn = function( e )
-{
-	var feature = this.createBufferFeature( new ol.geom.Point( this.client.config.map.center ), this.drawBufferRadius, this.drawBufferSegments );
-	this.previewLayer.getSource().addFeature( feature );
-	
-	//TODO: send all draw buffer params with events ?
-};
-
-netgis.MapOpenLayers.prototype.onDrawBufferOff = function( e )
-{
-	this.previewLayer.getSource().clear();
-};
-
-netgis.MapOpenLayers.prototype.onDrawBufferRadiusChange = function( e )
-{
-	var radius = e;
-	this.drawBufferRadius = radius;
-	
-	this.updateDrawBufferPreview();
-};
-
-netgis.MapOpenLayers.prototype.onDrawBufferSegmentsChange = function( e )
-{
-	var segs = e;
-	this.drawBufferSegments = segs;
-	
-	this.updateDrawBufferPreview();
-};
-
-netgis.MapOpenLayers.prototype.updateDrawBufferPreview = function()
-{
-	var draw = this.interactions[ this.mode ][ 0 ];
-	var overlays = draw.getOverlay().getSource().getFeatures();
-	if ( overlays.length < 1 ) return;
-	
-	var preview = this.previewLayer.getSource().getFeatures()[ 0 ];
-	if ( ! preview ) return;
-	
-	var geom = overlays[ 0 ].getGeometry();
-	var buffer = this.createBufferGeometry( geom, this.drawBufferRadius, this.drawBufferSegments );
-	preview.setGeometry( buffer );
-};
-
-netgis.MapOpenLayers.prototype.onEditLayerAdd = function( e )
-{
-	////this.updateEditOutput();
-	this.updateEditLayerItem();
-	this.updateEditOutput();
-	this.snapFeatures.push( e.feature );
-};
-
-netgis.MapOpenLayers.prototype.onEditLayerRemove = function( e )
-{
-	this.updateEditOutput();
-	this.snapFeatures.remove( e.feature );
-};
-
-netgis.MapOpenLayers.prototype.onEditLayerChange = function( e )
-{
-	this.updateEditOutput();
-};
-
-netgis.MapOpenLayers.prototype.updateEditOutput = function()
-{
-	var features = this.editLayer.getSource().getFeatures();
-	
-	var proj = this.client.config.map.projection;
-	var format = new ol.format.GeoJSON();
-	var output = format.writeFeaturesObject( features, { dataProjection: proj, featureProjection: proj } );
-	
-	// Projection
-	output[ "crs" ] =
-	{
-		"type": "name",
-		"properties": { "name": "urn:ogc:def:crs:" + proj.replace( ":", "::" ) }
-	};
-	
-	// Total Area
-	var area = 0.0;
-	
-	for ( var i = 0; i < features.length; i++ )
-	{
-		var geom = features[ i ].getGeometry();
-		if ( geom instanceof ol.geom.Polygon ) area += geom.getArea();
-	}
-	
-	output[ "area" ] = area;
-	
-	if ( ! this.editEventsSilent )
-	{
-		this.client.invoke( netgis.Events.EDIT_FEATURES_CHANGE, output );
-	}
-};
-
-netgis.MapOpenLayers.prototype.updateEditLayerItem = function()
-{
-	// Create layer item if not existing
-	var id = this.editLayerID;
-	
-	if ( ! this.layers[ id ] )
-	{
-		this.layers[ id ] = this.editLayer;
-		this.client.invoke( netgis.Events.LAYER_CREATED, { id: id, title: "Zeichnung", checked: true, folder: "draw" } );
-	}
-};
-
-netgis.MapOpenLayers.prototype.updateEditArea = function()
-{
-	
-};
-
-netgis.MapOpenLayers.prototype.onEditFeaturesLoaded = function( e )
-{
-	var json = e;	
-	var self = this;
-	window.setTimeout( function() { self.createLayerGeoJSON( "Import", json ); }, 10 );
-};
-
-netgis.MapOpenLayers.prototype.onDragEnter = function( e )
-{
-	e.preventDefault();
-	
-	this.dropTarget.classList.remove( "netgis-hide" );
-	
-	//TODO: refactor into dragdrop module + events ?
-	
-	return false;
-};
-
-netgis.MapOpenLayers.prototype.onDragLeave = function( e )
-{
-	this.dropTarget.classList.add( "netgis-hide" );
-	
-	return false;
-};
-
-netgis.MapOpenLayers.prototype.onDragDrop = function( e )
-{
-	console.info( "Drag Drop" );
-	
-	this.dropTarget.classList.add( "netgis-hide" );
-	
-	e.preventDefault();
-		
-	var file = e.dataTransfer.files[ 0 ];
-	var reader = new FileReader();
-
-	reader.onload = this.onDragLoad.bind( this );
-
-	console.log( "File:", file );
-
-	//reader.readAsDataURL( file );
-	reader.readAsArrayBuffer( file );
-
-	return false;
-};
-
-netgis.MapOpenLayers.prototype.onDragLoad = function( e )
-{
-	console.log( "On Load:", e.target );
-	
-	this.loadShape( e.target.result );
-};
-
-netgis.MapOpenLayers.prototype.loadShape = function( data )
-{
-	var self = this;
-	
-	shp( data ).then
-	(
-		function( geojson )
-		{
-			self.onShapeLoad( geojson );
-		}
-	);
-};
-
-netgis.MapOpenLayers.prototype.onShapeLoad = function( geojson )
-{
-	console.info( "Shapefile To Geojson:", geojson );
-			
-	var features = new ol.format.GeoJSON( { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } ).readFeatures( geojson );
-	this.importLayer.getSource().addFeatures( features );
-
-	this.view.fit( this.importLayer.getSource().getExtent(), {} );
-};
-
-netgis.MapOpenLayers.prototype.onImportGeoJSON = function( e )
-{
-	var file = e;
-	var title = file.name;
-	var self = this;
-	
-	var reader = new FileReader();
-	reader.onload = function( e ) { self.createLayerGeoJSON( title, e.target.result ); };
-	reader.readAsText( file );
-};
-
-netgis.MapOpenLayers.prototype.onImportGML = function( e )
-{
-	var file = e;
-	var title = file.name;
-	var self = this;
-	
-	var reader = new FileReader();
-	reader.onload = function( e ) { self.createLayerGML( title, e.target.result ); };
-	reader.readAsText( file );
-};
-
-netgis.MapOpenLayers.prototype.onImportShapefile = function( e )
-{
-	var file = e;
-	var title = file.name;
-	var self = this;
-	
-	var reader = new FileReader();
-	reader.onload = function( e ) { self.createLayerShapefile( title, e.target.result ); };
-	reader.readAsArrayBuffer( file );
-};
-
-netgis.MapOpenLayers.prototype.onImportSpatialite = function( e )
-{
-	var file = e;
-	var title = file.name;
-	var self = this;
-	
-	var reader = new FileReader();
-	reader.onload = function( e ) { self.createLayerSpatialite( title, e.target.result ); };
-	reader.readAsArrayBuffer( file );
-};
-
-netgis.MapOpenLayers.prototype.onImportGeopackage = function( e )
-{
-	var file = e;
-	var title = file.name;
-	var self = this;
-	
-	var reader = new FileReader();
-	reader.onload = function( e ) { self.createLayerGeopackage( title, e.target.result ); };
-	reader.readAsArrayBuffer( file );
-};
-
-netgis.MapOpenLayers.prototype.createLayerGeoJSON = function( title, data )
-{	
-	var format = new ol.format.GeoJSON();
-	var projection = format.readProjection( data );
-	var features = format.readFeatures( data, { featureProjection: this.client.config.map.projection } );
-
-	//NOTE: proj4.defs[ "EPSG:4326" ]
-	//NOTE: netgis.util.foreach( proj4.defs, function( k,v ) { console.info( "DEF:", k, v ); } )
-	
-	var projcode = projection.getCode();
-	
-	switch ( projcode )
-	{
-		case "EPSG:3857":
-		case "EPSG:4326":
-		case this.client.config.map.projection:
-		{
-			// Projection OK
-			break;
-		}
-		
-		default:
-		{
-			// Projection Not Supported
-			console.warn( "Unsupported Import Projection:", projcode );
-			break;
-		}
-	}	
-
-	this.addImportedFeatures( features );
-};
-
-netgis.MapOpenLayers.prototype.createLayerGML = function( title, data )
-{	
-	//NOTE: https://stackoverflow.com/questions/35935184/opening-qgis-exported-gml-in-openlayers-3
-	//NOTE: https://github.com/openlayers/openlayers/issues/5023
-	
-	console.warn( "GML support is experimental!" );
-	
-	//var format = new ol.format.GML3( { srsName: "EPSG::25832", featureType: "Test", featureNS: "http://www.opengis.net/gml" } );
-	//var format = new ol.format.GML( { featureNS: "ogr" } );
-	//var format = new ol.format.WFS( /*{ srsName: "EPSG:4326", featureType: "ogr:RLP_OG_utf8_epsg4326" }*/ );
-	//var format = new ol.format.GML( { featureNS: "ogr", featureType: "ogr:RLP_OG_utf8_epsg4326" } );
-	//var format = new ol.format.WFS();
-	//var format = new ol.format.WFS( { featureNS: "ogr", featureType: "RLP_OG_utf8_epsg4326" } );
-	//var projection = format.readProjection( data );
-	//var features = format.readFeatures( data, { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } );
-	
-	//var features = format.readFeatures( data, { dataProjection: this.client.config.map.projection, featureProjection: this.client.config.map.projection } );
-
-	//console.info( "GML:", projection, features, features[ 0 ].getGeometry() );
-
-	var features = [];
-	
-	var parser = new DOMParser();
-	var xml = parser.parseFromString( data, "text/xml" );
-	
-	// Features
-	var featureMembers = xml.getElementsByTagName( "gml:featureMember" );
-	
-	for ( var f = 0; f < featureMembers.length; f++ )
-	{
-		var props = {};
-		
-		var node = featureMembers[ f ];
-		var child = node.children[ 0 ];
-		
-		// Attributes
-		for ( var a = 0; a < child.attributes.length; a++ )
-		{
-			var attribute = child.attributes[ a ];
-			props[ attribute.nodeName ] = attribute.nodeValue;
-		}
-		
-		for ( var c = 0; c < child.children.length; c++ )
-		{
-			var childNode = child.children[ c ];
-			
-			if ( childNode.nodeName === "ogr:geometryProperty" ) continue;
-			
-			var parts = childNode.nodeName.split( ":" );
-			var k = parts[ parts.length - 1 ];
-			var v = childNode.innerHTML;
-			
-			props[ k ] = v;
-		}
-		
-		// Geometry
-		var geomprop = child.getElementsByTagName( "ogr:geometryProperty" )[ 0 ];
-		
-		//for ( var g = 0; g < geomprop.children.length; g++ )
-		{
-			var geom = geomprop.children[ 0 ];
-			var proj = geom.getAttribute( "srsName" );
-			
-			if ( proj && proj !== "EPSG:4326" && proj !== this.client.config.map.projection )
-				console.warn( "Unsupported Import Projection:", proj );
-			
-			switch ( geom.nodeName )
-			{
-				case "gml:Polygon":
-				{
-					props[ "geometry" ] = this.gmlParsePolygon( geom, proj );
-					break;
-				}
-				
-				case "gml:MultiPolygon":
-				{
-					props[ "geometry" ] = this.gmlParseMultiPolygon( geom, proj );
-					break;
-				}
-			}
-		}
-		
-		var feature = new ol.Feature( props );
-		features.push( feature );
-	}
-
-	this.addImportedFeatures( features );
-};
-
-netgis.MapOpenLayers.prototype.gmlParsePolygon = function( node, proj )
-{
-	var rings = [];
-	
-	var linearRings = node.getElementsByTagName( "gml:LinearRing" );
-	
-	for ( var r = 0; r < linearRings.length; r++ )
-	{
-		var ring = linearRings[ r ];
-		var coords = ring.getElementsByTagName( "gml:coordinates" )[ 0 ].innerHTML;
-		rings.push( this.gmlParseCoordinates( coords, proj ) );
-	}
-	
-	return new ol.geom.Polygon( rings );
-};
-
-netgis.MapOpenLayers.prototype.gmlParseMultiPolygon = function( node, proj )
-{
-	var polygons = [];
-					
-	var polygonMembers = node.getElementsByTagName( "gml:polygonMember" );
-
-	for ( var p = 0; p < polygonMembers.length; p++ )
-	{
-		var polygonMember = polygonMembers[ p ];
-		var polygonNode = polygonMember.getElementsByTagName( "gml:Polygon" )[ 0 ];
-		polygons.push( this.gmlParsePolygon( polygonNode, proj ) );
-	}
-	
-	return new ol.geom.MultiPolygon( polygons );
-};
-
-netgis.MapOpenLayers.prototype.gmlParseCoordinates = function( s, proj )
-{
-	var coords = s.split( " " );
-						
-	for ( var c = 0; c < coords.length; c++ )
-	{
-		// Split
-		coords[ c ] = coords[ c ].split( "," );
-
-		// Parse
-		for ( var xy = 0; xy < coords[ c ].length; xy++ )
-		{
-			coords[ c ][ xy ] = Number.parseFloat( coords[ c ][ xy ] );
-		}
-		
-		// Transform
-		if ( proj ) coords[ c ] = ol.proj.transform( coords[ c ], proj, this.client.config.map.projection );
-	}
-	
-	return coords;
-};
-
-netgis.MapOpenLayers.prototype.createLayerShapefile = function( title, shapeData )
-{
-	var self = this;
-	
-	shp( shapeData ).then
-	(
-		function( geojson )
-		{			
-			//var format = new ol.format.GeoJSON( { dataProjection: "EPSG:4326", featureProjection: "EPSG:3857" } );
-			var format = new ol.format.GeoJSON();
-			var projection = format.readProjection( geojson );
-			var features = format.readFeatures( geojson, { featureProjection: self.client.config.map.projection } );
-			
-			self.addImportedFeatures( features );
-		}
-	);
-};
-
-netgis.MapOpenLayers.prototype.createLayerSpatialite = function( title, data )
-{
-	var self = this;
-	
-	window.initSqlJs().then
-	(
-		function( SQL )
-		{
-			var features = [];
-			
-			var arr = new Uint8Array( data );
-			var db = new SQL.Database( arr );
-			
-			// Tables
-			var results = db.exec
-			(
-				"SELECT name FROM sqlite_schema WHERE type = 'table' \n\
-					AND name NOT LIKE 'sqlite_%' \n\
-					AND name NOT LIKE 'sql_%' \n\
-					AND name NOT LIKE 'idx_%' \n\
-					AND name NOT LIKE 'spatial_ref_sys%' \n\
-					AND name NOT LIKE 'spatialite_%' \n\
-					AND name NOT LIKE 'geometry_columns%' \n\
-					AND name NOT LIKE 'views_%' \n\
-					AND name NOT LIKE 'virts_%' \n\
-					AND name NOT LIKE 'SpatialIndex' \n\
-					AND name NOT LIKE 'ElementaryGeometries' \n\
-				;" );
-			
-			var tables = results[ 0 ].values;
-			
-			for ( var t = 0; t < tables.length; t++ )
-			{
-				var table = tables[ t ][ 0 ];
-
-				results = db.exec( "SELECT * FROM " + table );
-				var result = results[ 0 ];
-
-				// Columns
-				var geomcol = null;
-
-				for ( var c = 0; c < result.columns.length; c++ )
-				{
-					if ( result.columns[ c ].toLowerCase() === "geometry" ) { geomcol = c; break; }
-					if ( result.columns[ c ].toLowerCase() === "geom" ) { geomcol = c; break; }
-				}
-
-				// Rows
-				var rows = result.values;
-
-				for ( var r = 0; r < rows.length; r++ )
-				{
-					var row = rows[ r ];
-					
-					// Convert WKB
-					var input = row[ geomcol ];
-					var output = new Uint8Array( input.length - 43 - 1 + 5 );
-
-					// Byte Order
-					output[ 0 ] = input[ 1 ];
-
-					// Type
-					output[ 1 ] = input[ 39 ];
-					output[ 2 ] = input[ 40 ];
-					output[ 3 ] = input[ 41 ];
-					output[ 4 ] = input[ 42 ];
-
-					// Geometry
-					var geomlen = input.length - 43 - 1;
-
-					for ( var i = 0; i < geomlen; i++ )
-					{
-						output[ 5 + i ] = input[ 43 + i ];
-					}
-
-					var wkb = new ol.format.WKB();
-					var geom = wkb.readGeometry( output, { featureProjection: self.client.config.map.projection } );
-
-					features.push( new ol.Feature( { geometry: geom } ) );
-				}
-			}
-			
-			self.addImportedFeatures( features );
-		}
-	);
-};
-
-netgis.MapOpenLayers.prototype.createLayerGeopackage = function( title, data )
-{
-	var self = this;
-	var arr = new Uint8Array( data );
-	
-	window.GeoPackage.setSqljsWasmLocateFile( function( file ) { return self.client.config.import.geopackageLibURL + file; } );
-	
-	window.GeoPackage.GeoPackageAPI.open( arr ).then( function( geoPackage )
-	{
-		var features = [];
-		var format = new ol.format.GeoJSON();
-		var tables = geoPackage.getFeatureTables();
-		
-		for ( var t = 0; t < tables.length; t++ )
-		{
-			var table = tables[ t ];
-			var rows = geoPackage.queryForGeoJSONFeaturesInTable( table );
-			
-			for ( var r = 0; r < rows.length; r++ )
-			{
-				var row = rows[ r ];
-				var geom = format.readGeometry( row.geometry, { featureProjection: self.client.config.map.projection } );
-				var feature = new ol.Feature( { geometry: geom } );
-				features.push( feature );
-			}
-		}
-		
-		self.addImportedFeatures( features );
-	} );
-};
-
-netgis.MapOpenLayers.prototype.addImportedFeatures = function( features )
-{
-	// Add To Edit Layer
-	this.editEventsSilent = true;
-	this.editLayer.getSource().addFeatures( features );
-	this.editEventsSilent = false;
-	this.updateEditOutput();
-	
-	// Zoom Imported Features
-	if ( features.length > 0 )
-	{
-		var extent = features[ 0 ].getGeometry().getExtent();
-		
-		for ( var f = 1; f < features.length; f++ )
-		{
-			ol.extent.extend( extent, features[ f ].getGeometry().getExtent() );
-		}
-		
-		var padding = 40;
-		this.view.fit( extent, { duration: 300, padding: [ padding, padding, padding, padding ] } );
-	}
-};
-
-netgis.MapOpenLayers.prototype.onImportWKT = function( e )
-{
-	var parser = new ol.format.WKT();
-	var geom = parser.readGeometry( e );
-	var feature = new ol.Feature( { geometry: geom } );
-	
-	this.addImportedFeatures( [ feature ] );
-};
-
-netgis.MapOpenLayers.prototype.onExportPDF = function( e )
-{
-	this.exportImage( "pdf", e.resx, e.resy, e.mode, e.margin );
-};
-
-netgis.MapOpenLayers.prototype.onExportJPEG = function( e )
-{
-	this.exportImage( "jpeg", e.resx, e.resy );
-};
-
-netgis.MapOpenLayers.prototype.onExportPNG = function( e )
-{
-	this.exportImage( "png", e.resx, e.resy );
-};
-
-netgis.MapOpenLayers.prototype.onExportGIF = function( e )
-{
-	this.exportImage( "gif", e.resx, e.resy );
-};
-
-netgis.MapOpenLayers.prototype.onParcelShowPreview = function( e )
-{
-	var parser = new ol.format.WKT();
-	var geom = parser.readGeometry( e.geom );
-	var feature = new ol.Feature( { geometry: geom } );
-	
-	this.parcelLayer.getSource().clear();
-	this.parcelLayer.getSource().addFeature( feature );
-};
-
-netgis.MapOpenLayers.prototype.onParcelHidePreview = function( e )
-{
-	this.parcelLayer.getSource().clear();
-};
-
-netgis.MapOpenLayers.prototype.getWidth = function()
-{
-	return this.map.getSize()[ 0 ];
-};
-
-netgis.MapOpenLayers.prototype.getHeight = function()
-{
-	return this.map.getSize()[ 1 ];
-};
-
-/**
-* 
-* @param {format} string Format identifier (jpeg, png, gif)
-* @param {resx} integer Map image x resolution (pixels)
-* @param {resy} integer Map image y resolution (pixels)
-* @param {mode} boolean PDF mode (true = landscape, false = portrait)
-* @param {margin} integer PDF page margin (millimeters)
-*/
-netgis.MapOpenLayers.prototype.exportImage = function( format, resx, resy, mode, margin )
-{
-	this.client.invoke( netgis.Events.EXPORT_BEGIN, null );
-	
-	var self = this;
-	var root = this.root;
-	var map = this.map;
-	var config = this.client.config;
-	
-	// Request Logo Image
-	var logo = new Image();
-	
-	logo.onload = function()
-	{
-		//TODO: refactor map render image and image export
-		//NOTE: https://github.com/openlayers/openlayers/issues/9100
-		//NOTE: scaling / quality bugs when map pixel ratio is not 1.0
-
-		// Render Target
-		var renderContainer = document.createElement( "div" );
-		renderContainer.style.position = "fixed";
-		renderContainer.style.top = "0px";
-		renderContainer.style.left = "0px";
-		renderContainer.style.width = resx + "px";
-		renderContainer.style.height = resy + "px";
-		renderContainer.style.background = "white";
-		renderContainer.style.zIndex = -1;
-		renderContainer.style.opacity = 0.0;
-		renderContainer.style.pointerEvents = "none";
-		root.appendChild( renderContainer );
-		
-		map.setTarget( renderContainer );
-		
-		// Request Render
-		map.once
-		(
-			"rendercomplete",
-			function()
-			{
-				var mapCanvas = document.createElement( "canvas" );
-				mapCanvas.width = resx;
-				mapCanvas.height = resy;
-
-				var mapContext = mapCanvas.getContext( "2d" );
-				mapContext.webkitImageSmoothingEnabled = false;
-				mapContext.mozImageSmoothingEnabled = false;
-				mapContext.imageSmoothingEnabled = false;
-
-				// Loop Map Layers
-				Array.prototype.forEach.call
-				(
-					document.querySelectorAll( ".ol-layer canvas" ),
-					function( canvas )
-					{
-						if ( canvas.width > 0 )
-						{
-							var opacity = canvas.parentNode.style.opacity;
-							mapContext.globalAlpha = ( opacity === '' ) ? 1.0 : Number( opacity );
-
-							var transform = canvas.style.transform;
-							var matrix = transform.match( /^matrix\(([^\(]*)\)$/ )[ 1 ].split( "," ).map( Number );
-
-							CanvasRenderingContext2D.prototype.setTransform.apply( mapContext, matrix );
-
-							mapContext.drawImage( canvas, 0, 0 );
-						}
-					}
-				);
-
-				// Watermark Logo
-				mapContext.drawImage( logo, 0, 0 );
-				
-				// Timestamp
-				mapContext.fillStyle = "#fff";
-				mapContext.fillRect( 0, mapCanvas.height - 30, 140, 30 );
-				mapContext.fillStyle = "#000";
-				mapContext.font = "4mm sans-serif";
-				mapContext.fillText( netgis.util.getTimeStamp(), 10, mapCanvas.height - 10 );
-
-				// Export Map Image
-				var link = document.createElement( "a" );
-
-				switch ( format )
-				{
-					case "pdf":
-					{
-						// Dimensions
-						var landscape = mode;
-						margin = margin ? margin : 0;
-						var widthA4 = 297 - margin - margin;
-						var heightA4 = 210 - margin - margin;
-						var ratio = mapCanvas.width / mapCanvas.height;
-						
-						if ( ! landscape )
-						{
-							var w = widthA4;
-							widthA4 = heightA4;
-							heightA4 = w;
-						}
-
-						var width;
-						var height;
-
-						if ( mapCanvas.height > mapCanvas.width )
-						{
-							// Tall Canvas
-							height = heightA4;
-							width = height * ratio;
-							
-							if ( width > widthA4 )
-							{
-								width = widthA4;
-								height = width / ratio;
-							}
-						}
-						else
-						{
-							// Wide Canvas
-							width = widthA4;
-							height = width / ratio;
-							
-							if ( height > heightA4 )
-							{
-								height = heightA4;
-								width = height * ratio;
-							}
-						}
-
-						var pdf = new jsPDF( landscape ? "l" : "p" );
-
-						var x = margin;
-						x += ( widthA4 - width ) / 2;
-
-						var y = margin;
-						y += ( heightA4 - height ) / 2;
-
-						// Map Image
-						pdf.addImage( mapCanvas.toDataURL( "image/png,1.0", 1.0 ), "PNG", x, y, width, height );
-
-						// Text
-						pdf.setFillColor( 255, 255, 255 );
-						pdf.rect( x, y + height - 11, 80, 11, "F" );
-						
-						pdf.setFontSize( 8 );
-						pdf.text( "Datum: " + netgis.util.getTimeStamp(), x + 2, y + height - 2 - 4 );
-						pdf.text( "Quelle: " + window.location.href, x + 2, y + height - 2 );
-
-						// Same Tab
-						//pdf.output( "save", { filename: config.export.defaultFilename + ".pdf" } );
-
-						// New Tab (without Name)
-						var data = pdf.output( "bloburl", { filename: config.export.defaultFilename + ".pdf" } );
-						window.open( data, "_blank" );
-
-						/*
-						// Download (with Name)
-						var data = pdf.output( "blob", { filename: config.export.defaultFilename + ".pdf" } );
-						var blob = new Blob( [ data ], { type: "octet/stream" } );
-						link.setAttribute( "download", "Export.pdf" );
-						link.setAttribute( "href", window.URL.createObjectURL( blob ) );
-						link.click();
-						//window.URL.revokeObjectURL( url );
-						*/
-
-						break;
-					}
-
-					case "jpeg":
-					{					
-						if ( window.navigator.msSaveBlob )
-						{
-							window.navigator.msSaveBlob( mapCanvas.msToBlob(), config.export.defaultFilename + ".jpg" );
-						}
-						else
-						{
-							link.setAttribute( "download", config.export.defaultFilename + ".jpg" );
-							link.setAttribute( "href", mapCanvas.toDataURL( "image/jpeg", 1.0 ) );
-							link.click();
-						}
-
-						break;
-					}
-
-					case "png":
-					{					
-						if ( window.navigator.msSaveBlob )
-						{
-							//if ( ! config.export.openNewTab )
-								window.navigator.msSaveBlob( mapCanvas.msToBlob(), config.export.defaultFilename + ".png" );
-							/*else
-								window.open( mapCanvas.msToBlob(), "_blank" );*/
-						}
-						else
-						{
-							/*if ( ! config.export.openNewTab )
-							{*/
-								link.setAttribute( "download", config.export.defaultFilename + ".png" );
-								link.setAttribute( "href", mapCanvas.toDataURL( "image/png", 1.0 ) );
-								link.click();
-							/*}
-							else
-								window.open( mapCanvas.toDataURL( "image/png", 1.0 ), "_blank" );*/
-						}
-
-						break;
-					}
-
-					case "gif":
-					{
-						link.setAttribute( "download", config.export.defaultFilename + ".gif" );
-						
-						var gif = new GIF( { workerScript: config.export.gifWebWorker, quality: 1 } );
-						gif.addFrame( mapCanvas );
-						
-						gif.on
-						(
-							"finished",
-							function( blob )
-							{
-								link.setAttribute( "href", window.URL.createObjectURL( blob ) );
-								link.click();
-							}
-						);
-
-						gif.render();
-
-						break;
-					}
-				}   
-				
-				/// Done
-				map.setTarget( root );
-				root.removeChild( renderContainer );
-				
-				self.client.invoke( netgis.Events.EXPORT_END, null );
-			}
-		);
-
-		// Begin Map Render
-		map.renderSync();
-	};
-	
-	// Begin Logo Load & Render
-	logo.src = config.export.logo;
-};
-
-netgis.MapOpenLayers.prototype.splitMultiPolygons = function( layer )
-{
-	//TODO: split only selected feature ( parameter )
-	
-	var source = layer.getSource();
-	var features = source.getFeatures();
-
-	var removeFeatures = [];
-	var newFeatures = [];
-
-	// Find Multi Features
-	for ( var i = 0; i < features.length; i++ )
-	{
-		var feature = features[ i ];
-		var geom = feature.getGeometry();
-
-		if ( geom instanceof ol.geom.MultiPolygon )
-		{
-			var polygons = geom.getPolygons();
-
-			// Create Single Features
-			for ( var j = 0; j < polygons.length; j++ )
-			{
-				var polygon = polygons[ j ];
-				var newFeature = new ol.Feature( { geometry: polygon } );
-				newFeatures.push( newFeature );
-			}
-
-			removeFeatures.push( feature );
-		}
-	}
-
-	// Remove Multi Features
-	for ( var i = 0; i < removeFeatures.length; i++ )
-	{
-		source.removeFeature( removeFeatures[ i ] );
-	}
-
-	// Add Single Features
-	source.addFeatures( newFeatures );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Menu.css b/templates/map/client/libs/netgis/Menu.css
deleted file mode 100644
index ffc24de1..00000000
--- a/templates/map/client/libs/netgis/Menu.css
+++ /dev/null
@@ -1,118 +0,0 @@
-.netgis-menu
-{
-	position: absolute;
-	left: 0mm;
-	right: 0mm;
-	top: 0mm;
-	height: 12mm;
-	/*min-height: 12mm;*/
-	
-	/*min-height: 12mm;*/
-	line-height: 12mm;
-	/*overflow-x: auto;
-	overflow-y: hidden;*/
-	
-	white-space: nowrap;
-	font-size: 0mm;
-	
-	z-index: 1000;
-	
-	background: lightsalmon;
-}
-
-.netgis-menu > div
-{
-	height: 12mm;
-	/*min-height: 12mm;*/
-	white-space: nowrap;
-	/*font-size: 0mm;*/
-}
-
-/*.netgis-menu > * */
-.netgis-menu > div > *
-{
-	display: inline-block;
-	height: 100%;
-	/*font-size: 4mm;*/
-	margin: 0mm;
-	/*padding: 0mm 4mm;*/
-	/*float: left;*/
-	
-	font-size: 4mm;
-}
-
-.netgis-menu .netgis-right
-{
-	float: right;
-	padding-right: 0mm;
-	padding-left: 4mm;
-}
-
-.netgis-menu span
-{
-	padding: 0mm 4mm 0mm 0mm;
-}
-
-.netgis-menu button i
-{
-	font-size: 5mm;
-	width: 12mm;
-	line-height: 12mm;
-	text-align: center;
-}
-
-.netgis-dropdown
-{
-	position: relative;
-	padding: 0mm;
-	/*bottom: 2px;*/
-}
-
-.netgis-dropdown .netgis-dropdown-content
-{
-	display: none;
-	/*position: fixed;*/
-	position: absolute;
-	/*top: 12mm;*/
-	min-width: 100%;
-	/*min-width: 40mm;*/
-	padding: 0mm;
-	margin: 0mm;
-	margin-top: -1px;
-	z-index: 1;
-	
-	font-size: 4mm;
-	list-style-type: none;
-}
-
-/*.netgis-dropdown:hover
-{
-	z-index: 10;
-}*/
-
-.netgis-dropdown:hover .netgis-dropdown-content
-{
-	display: block;
-}
-
-.netgis-dropdown .netgis-dropdown-content i
-{
-	font-size: 4mm;
-	color: #bbb;
-}
-
-.netgis-dropdown button
-{
-	width: 100%;
-	/* padding: 0mm 4mm; */
-	padding: 0mm 4mm 0mm 0mm;
-	white-space: nowrap;
-	text-align: left;
-}
-
-/*.netgis-dropdown i
-{
-	width: 12mm;
-	line-height: 12mm;
-	text-align: center;
-}*/
diff --git a/templates/map/client/libs/netgis/Menu.js b/templates/map/client/libs/netgis/Menu.js
deleted file mode 100644
index eacacad1..00000000
--- a/templates/map/client/libs/netgis/Menu.js
+++ /dev/null
@@ -1,261 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.Menu = function()
-{
-	this.client = null;
-	this.root = null;
-	this.sections = [];
-};
-
-netgis.Menu.prototype.load = function()
-{
-	this.root = document.createElement( "header" );
-	this.root.className = "netgis-menu netgis-primary netgis-shadow";
-	
-	//TODO: refactor into abstract bar class (see toolbar) ?
-	var wrapper = document.createElement( "div" );
-	this.root.appendChild( wrapper );
-	
-	var toggle = this.createButton( 'Ebenen<i class="fab fa-buffer"></i>', true );
-	toggle.addEventListener( "click", this.onToggleClick.bind( this ) );
-	////this.root.appendChild( toggle );
-	wrapper.appendChild( toggle );
-	
-	var search = this.createButton( 'Suche<i class="fas fa-search" style="position: relative; top: 0.3mm;"></i>', true );
-	search.addEventListener( "click", this.onSearchPlaceClick.bind( this ) );
-	////this.root.appendChild( search );
-	wrapper.appendChild( search );
-	
-	var searchParcel = this.createButton( 'Flurstücke<i class="fas fa-vector-square" style="position: relative; top: 0.3mm;"></i>', true );
-	searchParcel.addEventListener( "click", this.onSearchParcelClick.bind( this ) );
-	wrapper.appendChild( searchParcel );
-	
-	/*var title = this.createButton( '<span>GeoPortal</span>', false );
-	title.classList.remove( "netgis-hover-primary" ); //TODO: createText function?
-	//title.style.padding = "0mm";
-	this.root.appendChild( title );*/
-	
-	if ( this.client.editable )
-	{
-		// Draw Menu
-		var draw = this.createMenu( '<i class="fas fa-caret-down"></i>Zeichnen' );
-		var drawItems = draw.getElementsByTagName( "ul" )[ 0 ];
-		////this.root.appendChild( draw );
-		wrapper.appendChild( draw );
-
-		drawItems.appendChild( this.createMenuItem( '<i class="fas fa-map-marker-alt"></i>Punkte', this.onDrawPointClick.bind( this ) ) );
-		drawItems.appendChild( this.createMenuItem( '<i class="fas fa-minus"></i>Linien', this.onDrawLineClick.bind( this ) ) );
-		drawItems.appendChild( this.createMenuItem( '<i class="fas fa-vector-square"></i>Polygone', this.onDrawPolygonClick.bind( this ) ) );
-
-		// Edit Menu
-		var edit = this.createMenu( '<i class="fas fa-caret-down"></i>Bearbeiten' );
-		var editItems = edit.getElementsByTagName( "ul" )[ 0 ];
-		////this.root.appendChild( edit );
-		wrapper.appendChild( edit );
-
-		editItems.appendChild( this.createMenuItem( '<i class="fas fa-cut"></i>Ausschneiden', this.onCutFeatureClick.bind( this ) ) );
-		editItems.appendChild( this.createMenuItem( '<i class="fas fa-arrows-alt"></i>Verschieben', this.onModifyFeaturesClick.bind( this ) ) );
-		editItems.appendChild( this.createMenuItem( '<i class="fas fa-eraser"></i>Löschen', this.onDeleteFeaturesClick.bind( this ) ) );
-		editItems.appendChild( this.createMenuItem( '<i class="far fa-dot-circle"></i>Puffern', this.onBufferFeatureClick.bind( this ) ) );
-		
-		// Import Menu
-		var importMenu = this.createMenu( '<i class="fas fa-caret-down"></i>Import' );
-		//this.root.appendChild( importMenu );
-		wrapper.appendChild( importMenu );
-
-		//fileItems.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>OWS-Context', this.onImportOWSClick.bind( this ) ) );
-
-		var importItem = importMenu.getElementsByTagName( "ul" )[ 0 ];
-		importItem.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>GeoJSON', this.onImportGeoJSONClick.bind( this ) ) );
-		//fileItems.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>KML', this.onImportKMLClick.bind( this ) ) );
-		importItem.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>GML', this.onImportGMLClick.bind( this ) ) );
-		importItem.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>Shapefile', this.onImportShapefileClick.bind( this ) ) );
-		importItem.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>Spatialite', this.onImportSpatialiteClick.bind( this ) ) );
-		importItem.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>GeoPackage', this.onImportGeopackageClick.bind( this ) ) );
-		
-		// Export
-		var exportMenu = this.createMenu( '<i class="fas fa-caret-down"></i>Export' );
-		////this.root.appendChild( exportMenu );
-		wrapper.appendChild( exportMenu );
-
-		var exportItems = exportMenu.getElementsByTagName( "ul" )[ 0 ];
-		exportItems.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>PDF', this.onExportPDFClick.bind( this ) ) );
-		exportItems.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>JPEG', this.onExportJPEGClick.bind( this ) ) );
-		exportItems.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>PNG', this.onExportPNGClick.bind( this ) ) );
-		exportItems.appendChild( this.createMenuItem( '<i class="fas fa-file"></i>GIF', this.onExportGIFClick.bind( this ) ) );
-	}
-	
-	// Search Menu
-	/*var search = this.createMenu( '<i class="fas fa-caret-down"></i>Suche' );
-	var searchItems = search.getElementsByTagName( "ul" )[ 0 ];
-	this.root.appendChild( search );
-	
-	searchItems.appendChild( this.createMenuItem( '<i class="fas fa-search"></i>Ortssuche', this.onSearchPlaceClick.bind( this ) ) );
-	searchItems.appendChild( this.createMenuItem( '<i class="fas fa-search"></i>Datensuche', this.onSearchDataClick.bind( this ) ) );*/
-	
-	// Right Buttons
-	/*
-	var settings = this.createButton( '<i class="fas fa-cog"></i>', true );
-	this.root.appendChild( settings );
-	
-	var help = this.createButton( '<i class="fas fa-question"></i>', true );
-	this.root.appendChild( help );
-	*/
-	
-	this.client.root.appendChild( this.root );
-};
-
-netgis.Menu.prototype.createButton = function( label, right )
-{
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.className = "netgis-primary netgis-hover-primary";
-	if ( right ) button.className += " netgis-right";
-	button.innerHTML = label;
-	
-	return button;
-};
-
-netgis.Menu.prototype.createMenu = function( title )
-{
-	var menu = document.createElement( "div" );
-	menu.className = "netgis-dropdown";
-	
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.className = "netgis-primary netgis-hover-primary";
-	button.innerHTML = title;
-	menu.appendChild( button );
-	
-	var content = document.createElement( "ul" );
-	content.className = "netgis-dropdown-content netgis-dialog netgis-shadow";
-	menu.appendChild( content );
-	
-	return menu;
-};
-
-netgis.Menu.prototype.createMenuItem = function( title, callback )
-{
-	var item = document.createElement( "li" );
-	item.className = "netgis-hover-light";
-	
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.innerHTML = title;
-	button.addEventListener( "click", callback );
-	item.appendChild( button );
-	
-	return item;
-};
-
-netgis.Menu.prototype.onToggleClick = function( e )
-{
-	this.client.invoke( netgis.Events.LAYER_LIST_TOGGLE, null );
-};
-
-netgis.Menu.prototype.onDrawPointClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.DRAW_POINTS );
-};
-
-netgis.Menu.prototype.onDrawLineClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.DRAW_LINES );
-};
-
-netgis.Menu.prototype.onDrawPolygonClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.DRAW_POLYGONS );
-};
-
-netgis.Menu.prototype.onCutFeatureClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.CUT_FEATURE_BEGIN );
-};
-
-netgis.Menu.prototype.onModifyFeaturesClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.MODIFY_FEATURES );
-};
-
-netgis.Menu.prototype.onDeleteFeaturesClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.DELETE_FEATURES );
-};
-
-netgis.Menu.prototype.onBufferFeatureClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.BUFFER_FEATURE_BEGIN );
-};
-
-netgis.Menu.prototype.onSearchPlaceClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.SEARCH_PLACE );
-};
-
-netgis.Menu.prototype.onSearchParcelClick = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.SEARCH_PARCEL );
-};
-
-netgis.Menu.prototype.onSearchDataClick = function( e )
-{
-	alert( "TODO: data search interface" );
-};
-
-netgis.Menu.prototype.onImportOWSClick = function( e )
-{
-	alert( "TODO: ows import interface, try setting url parameter '?ows=<url>'" );
-};
-
-netgis.Menu.prototype.onImportShapefileClick = function( e )
-{
-	this.client.invoke( netgis.Events.IMPORT_SHAPEFILE_SHOW, null );
-};
-
-netgis.Menu.prototype.onImportGeoJSONClick = function( e )
-{
-	this.client.invoke( netgis.Events.IMPORT_GEOJSON_SHOW, null );
-};
-
-netgis.Menu.prototype.onImportKMLClick = function( e )
-{
-	alert( "TODO: kml import interface" );
-};
-
-netgis.Menu.prototype.onImportGMLClick = function( e )
-{
-	this.client.invoke( netgis.Events.IMPORT_GML_SHOW, null );
-};
-
-netgis.Menu.prototype.onImportSpatialiteClick = function( e )
-{
-	this.client.invoke( netgis.Events.IMPORT_SPATIALITE_SHOW, null );
-};
-
-netgis.Menu.prototype.onImportGeopackageClick = function( e )
-{
-	this.client.invoke( netgis.Events.IMPORT_GEOPACKAGE_SHOW, null );
-};
-
-netgis.Menu.prototype.onExportPDFClick = function( e )
-{
-	this.client.invoke( netgis.Events.EXPORT_PDF_SHOW, null );
-};
-
-netgis.Menu.prototype.onExportJPEGClick = function( e )
-{
-	this.client.invoke( netgis.Events.EXPORT_JPEG_SHOW, null );
-};
-
-netgis.Menu.prototype.onExportPNGClick = function( e )
-{
-	this.client.invoke( netgis.Events.EXPORT_PNG_SHOW, null );
-};
-
-netgis.Menu.prototype.onExportGIFClick = function( e )
-{
-	this.client.invoke( netgis.Events.EXPORT_GIF_SHOW, null );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Modal.css b/templates/map/client/libs/netgis/Modal.css
deleted file mode 100644
index 39b7d02e..00000000
--- a/templates/map/client/libs/netgis/Modal.css
+++ /dev/null
@@ -1,161 +0,0 @@
-.netgis-modal
-{
-	display: none;
-	
-	position: absolute;
-	width: 100%;
-	height: 100%;
-	top: 0mm;
-	left: 0mm;
-	padding: 6mm;
-	z-index: 5000;
-	
-	background: rgba( 0, 0, 0, 0.6 );
-}
-
-.netgis-modal.netgis-show
-{
-	display: block;
-}
-
-.netgis-modal .netgis-dialog
-{
-	display: none;
-	
-	max-width: 160mm;
-	max-height: 160mm;
-	margin: auto;
-	
-	border-radius: 1mm;
-	border: 1mm solid #a7233f;
-	
-	overflow: hidden;
-	overflow-y: auto;
-	
-	cursor: default;
-	
-	/*transform: scale( 0.0 );
-	transition: transform 2000ms ease;*/
-}
-
-.netgis-modal .netgis-dialog.netgis-show
-{
-	display: block;
-	
-	/*transform: scale( 1.0 );
-	transition: transform 2000ms ease;*/
-}
-
-.netgis-modal header
-{
-	/*position: absolute;*/
-	width: 100%;
-	height: 12mm;
-	/*left: 0mm;
-	top: 0mm;*/
-	line-height: 12mm;
-	text-align: center;
-}
-
-.netgis-modal header button
-{
-	position: relative;
-	width: 100%;
-	min-height: 12mm;
-}
-
-.netgis-modal header button span
-{
-	display: block;
-	position: absolute;
-	right: 0mm;
-	top: 0mm;
-	line-height: 12mm;
-	padding: 0mm 4mm;
-	text-align: center;
-}
-
-.netgis-modal-content
-{
-	/*position: absolute;
-	left: 4mm;
-	right: 4mm;
-	top: 16mm;
-	bottom: 4mm;*/
-	padding: 6mm;
-	overflow: auto;
-}
-
-.netgis-modal-content > table
-{
-	width: 100%;
-	border: none;
-	border-spacing: 0mm;
-}
-
-.netgis-modal-content > table td,
-.netgis-modal-content > table th
-{
-	width: 50%;
-	overflow: hidden;
-	vertical-align: top;
-	text-align: left;
-}
-
-.netgis-modal-content .netgis-padding
-{
-	padding: 4mm 4mm;
-}
-
-.netgis-modal-content .netgis-space
-{
-	height: 6mm;
-}
-
-.netgis-modal-content button,
-.netgis-modal-content label
-{
-	width: 100%;
-	min-height: 12mm;
-	/*line-height: 12mm;*/
-}
-
-.netgis-modal-content button i
-{
-	margin-right: 4mm;
-}
-
-.netgis-modal-content button[disabled]
-{
-	opacity: 0.5;
-	cursor: not-allowed;
-}
-
-.netgis-modal-content input,
-.netgis-modal-content select
-{
-	width: 100%;
-}
-
-.netgis-modal-content input[type=file]
-{
-	cursor: pointer;
-}
-
-.netgis-modal-content ul
-{
-	margin: 0mm;
-	padding: 0mm;
-	padding-left: 4mm;
-	list-style-type: square;
-}
-
-.netgis-modal-content li:not( :last-child )
-{
-	margin-bottom: 4mm;
-}
-
-.netgis-modal h3
-{
-	margin: 0mm;
-}
diff --git a/templates/map/client/libs/netgis/Modal.js b/templates/map/client/libs/netgis/Modal.js
deleted file mode 100644
index 7a411f85..00000000
--- a/templates/map/client/libs/netgis/Modal.js
+++ /dev/null
@@ -1,1020 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-/**
- * Modal Module
- * 
- * Notes:
- * - Putting all modals in here for ease of implementation
- * - This may be split up into one class for each modal (?)
- * 
- * @returns {netgis.Modal}
- */
-netgis.Modal = function()
-{
-	this.client = null;
-	this.importGeoJSON = null;
-	this.importGML = null;
-	this.importShapefile = null;
-	this.exportPDF = null;
-	this.exportJPEG = null;
-	this.exportPNG = null;
-	this.exportGIF = null;
-	this.addService = null;
-	
-	this.addServiceID = 10000;
-};
-
-netgis.Modal.prototype.load = function()
-{
-	this.root = document.createElement( "section" );
-	this.root.className = "netgis-modal";
-	this.root.addEventListener( "click", this.onRootClick.bind( this ) );
-	
-	// Import
-	this.importGeoJSON = this.createImportGeoJSON();
-	this.root.appendChild( this.importGeoJSON );
-	
-	this.importGML = this.createImportGML();
-	this.root.appendChild( this.importGML );
-	
-	this.importShapefile = this.createImportShapefile();
-	this.root.appendChild( this.importShapefile );
-	
-	this.importSpatialite = this.createImportSpatialite();
-	this.root.appendChild( this.importSpatialite );
-	
-	this.importGeopackage = this.createImportGeopackage();
-	this.root.appendChild( this.importGeopackage );
-	
-	// Export
-	this.exportPDF = this.createExportPDF();
-	this.root.appendChild( this.exportPDF );
-	
-	this.exportJPEG = this.createExportJPEG();
-	this.root.appendChild( this.exportJPEG );
-	
-	this.exportPNG = this.createExportPNG();
-	this.root.appendChild( this.exportPNG );
-	
-	this.exportGIF = this.createExportGIF();
-	this.root.appendChild( this.exportGIF );
-	
-	// Layers
-	this.addService = this.createAddService();
-	this.root.appendChild( this.addService );
-	
-	// Done
-	this.client.root.appendChild( this.root );
-	
-	// Events
-	this.client.on( netgis.Events.IMPORT_GEOJSON_SHOW, this.onImportGeoJSONShow.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_GML_SHOW, this.onImportGMLShow.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_SHAPEFILE_SHOW, this.onImportShapefileShow.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_SPATIALITE_SHOW, this.onImportSpatialiteShow.bind( this ) );
-	this.client.on( netgis.Events.IMPORT_GEOPACKAGE_SHOW, this.onImportGeopackageShow.bind( this ) );
-	
-	this.client.on( netgis.Events.EXPORT_PDF_SHOW, this.onExportPDFShow.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_JPEG_SHOW, this.onExportJPEGShow.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_PNG_SHOW, this.onExportPNGShow.bind( this ) );
-	this.client.on( netgis.Events.EXPORT_GIF_SHOW, this.onExportGIFShow.bind( this ) );
-	
-	this.client.on( netgis.Events.ADD_SERVICE_SHOW, this.onAddServiceShow.bind( this ) );
-};
-
-netgis.Modal.prototype.createImportGeoJSON = function()
-{
-	var container = this.createContainer( "Import GeoJSON" );
-	
-	this.createText( container, "Unterstützte Koordinatensysteme:", "<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>" );
-	this.createInputFile( container, "Datei auswählen / ablegen:", ".geojson,.json", this.onImportGeoJSONChange.bind( this ) );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Importieren", this.onImportGeoJSONAccept.bind( this ) );
-	
-	return container;
-};
-
-netgis.Modal.prototype.createImportGML = function()
-{
-	var container = this.createContainer( "Import GML" );
-	
-	this.createText( container, "Unterstützte Koordinatensysteme:", "<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>" );
-	this.createInputFile( container, "Datei auswählen / ablegen:", ".gml,.xml", this.onImportGMLChange.bind( this ) );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Importieren", this.onImportGMLAccept.bind( this ) );
-	
-	return container;
-};
-
-netgis.Modal.prototype.createImportShapefile = function()
-{
-	var container = this.createContainer( "Import Shapefile" );
-	
-	this.createText( container, "Unterstützte Koordinatensysteme:", "<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>" );
-	this.createInputFile( container, "Datei auswählen / ablegen:", "application/zip", this.onImportShapefileChange.bind( this ) );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Importieren", this.onImportShapefileAccept.bind( this ) );
-	
-	return container;
-};
-
-netgis.Modal.prototype.createImportSpatialite = function()
-{
-	var container = this.createContainer( "Import Spatialite" );
-	
-	this.createText( container, "Unterstützte Koordinatensysteme:", "<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>" );
-	this.createInputFile( container, "Datei auswählen / ablegen:", ".sqlite", this.onImportSpatialiteChange.bind( this ) );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Importieren", this.onImportSpatialiteAccept.bind( this ) );
-	
-	return container;
-};
-
-netgis.Modal.prototype.createImportGeopackage = function()
-{
-	var container = this.createContainer( "Import GeoPackage" );
-	
-	this.createText( container, "Unterstützte Koordinatensysteme:", "<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>" );
-	this.createInputFile( container, "Datei auswählen / ablegen:", ".gpkg", this.onImportGeopackageChange.bind( this ) );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Importieren", this.onImportGeopackageAccept.bind( this ) );
-	
-	return container;
-};
-
-netgis.Modal.prototype.createExportPDF = function()
-{
-	var container = this.createContainer( "Export PDF" );
-	
-	this.createInputInteger( container, "Breite (Pixel):", 800, 0, 4096 );
-	this.createInputInteger( container, "Höhe (Pixel):", 600, 0, 4096 );
-	this.createInputInteger( container, "Seitenränder (Millimeter):", 10, 0, 100 );
-	this.createInputCheckbox( container, "Querformat:", true );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Exportieren", this.onExportPDFAccept.bind( this ) );
-
-	return container;
-};
-
-netgis.Modal.prototype.createExportJPEG = function()
-{
-	var container = this.createContainer( "Export JPEG" );
-	
-	this.createInputInteger( container, "Breite (Pixel):", 800, 0, 4096 );
-	this.createInputInteger( container, "Höhe (Pixel):", 600, 0, 4096 );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Exportieren", this.onExportJPEGAccept.bind( this ) );
-
-	return container;
-};
-
-netgis.Modal.prototype.createExportPNG = function()
-{
-	var container = this.createContainer( "Export PNG" );
-	
-	this.createInputInteger( container, "Breite (Pixel):", 800, 0, 4096 );
-	this.createInputInteger( container, "Höhe (Pixel):", 600, 0, 4096 );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Exportieren", this.onExportPNGAccept.bind( this ) );
-
-	return container;
-};
-
-netgis.Modal.prototype.createExportGIF = function()
-{
-	var container = this.createContainer( "Export GIF" );
-	
-	this.createInputInteger( container, "Breite (Pixel):", 800, 0, 4096 );
-	this.createInputInteger( container, "Höhe (Pixel):", 600, 0, 4096 );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Exportieren", this.onExportGIFAccept.bind( this ) );
-
-	return container;
-};
-
-netgis.Modal.prototype.createAddService = function()
-{
-	var container = this.createContainer( "Dienst hinzufügen" );
-	
-	this.createInputText( container, "WMS/WFS URL:" );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-cloud-download-alt'></i>Dienst laden", this.onAddServiceLoad.bind( this ) );
-	
-	/*var details = document.createElement( "div" );
-	details.className = "netgis-hide";
-	container.appendChild( details );*/
-	
-	this.createSpace( container );
-	this.createInputHidden( container );
-	this.createInputHidden( container );
-	this.createText( container, "Bezeichnung:", "" );
-	this.createInputSelect( container, "Kartenebene:", [] );
-	this.createInputSelect( container, "Format:", [] );
-	this.createSpace( container );
-	this.createButton( container, "<i class='fas fa-check'></i>Dienst hinzufügen", this.onAddServiceAccept.bind( this ) );
-	
-	return container;
-};
-
-netgis.Modal.prototype.show = function( container )
-{
-	this.root.classList.add( "netgis-show" );
-	
-	// Active Container
-	var containers = this.root.getElementsByClassName( "netgis-dialog" );
-	for ( var i = 0; i < containers.length; i++ )
-	{
-		containers[ i ].classList.remove( "netgis-show" );
-	}
-	
-	container.classList.add( "netgis-show" );
-};
-
-netgis.Modal.prototype.hide = function()
-{
-	this.root.classList.remove( "netgis-show" );
-};
-
-netgis.Modal.prototype.createContainer = function( title )
-{
-	var container = document.createElement( "section" );
-	container.className = "netgis-dialog netgis-shadow";
-	
-	/*var header = document.createElement( "header" );
-	header.className = "netgis-primary";
-	*/
-	
-	var header = document.createElement( "header" );
-	
-	var headerButton = document.createElement( "button" );
-	headerButton.setAttribute( "type", "button" );
-	headerButton.className = "netgis-primary netgis-hover-primary";
-	headerButton.innerHTML = "<h3>" + title + "</h3>";
-	headerButton.addEventListener( "click", this.onHeaderClick.bind( this ) );
-	header.appendChild( headerButton );
-	
-	var headerIcon = document.createElement( "span" );
-	headerIcon.innerHTML = "<i class='fas fa-times'></i>";
-	headerButton.appendChild( headerIcon );
-	
-	container.appendChild( header );
-	
-	var content = document.createElement( "div" );
-	content.className = "netgis-modal-content";
-	container.appendChild( content );
-	
-	var table = document.createElement( "table" );
-	content.appendChild( table );
-	
-	return container;
-};
-
-netgis.Modal.prototype.createSpace = function( container )
-{
-	var row = document.createElement( "tr" );
-	row.className = "netgis-space";
-	
-	var cell = document.createElement( "td" );
-	cell.setAttribute( "colspan", 100 );
-	row.appendChild( cell );
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return cell;
-};
-
-netgis.Modal.prototype.createButton = function( container, title, callback )
-{
-	var row = document.createElement( "tr" );
-	
-	var cell = document.createElement( "td" );
-	cell.setAttribute( "colspan", 100 );
-	row.appendChild( cell );
-	
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.className = "netgis-primary netgis-hover-primary";
-	button.innerHTML = title;
-	if ( callback ) button.addEventListener( "click", callback );
-	cell.appendChild( button );
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return button;
-};
-
-netgis.Modal.prototype.createInputHidden = function( container )
-{
-	var row = document.createElement( "tr" );
-	row.className = "netgis-hidden";
-	
-	var cell = document.createElement( "td" );
-	row.appendChild( cell );
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "hidden" );
-	cell.appendChild( input );
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return input;
-};
-
-netgis.Modal.prototype.createInputText = function( container, title )
-{
-	var row = document.createElement( "tr" );
-	//row.className = "netgis-hover-light";
-	
-	var head = document.createElement( "th" );
-	head.className = "netgis-padding";
-	
-	var label = document.createElement( "label" );
-	label.innerHTML = title;
-	head.appendChild( label );
-	row.appendChild( head );
-	
-	var cell = document.createElement( "td" );
-	cell.className = "netgis-padding";
-	row.appendChild( cell );
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "text" );
-	cell.appendChild( input );
-	
-	label.htmlFor = input;
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return input;
-};
-
-netgis.Modal.prototype.createInputSelect = function( container, title, keyValues )
-{
-	var row = document.createElement( "tr" );
-	//row.className = "netgis-hover-light";
-	
-	var head = document.createElement( "th" );
-	head.className = "netgis-padding";
-	
-	var label = document.createElement( "label" );
-	label.innerHTML = title;
-	head.appendChild( label );
-	row.appendChild( head );
-	
-	var cell = document.createElement( "td" );
-	cell.className = "netgis-padding";
-	row.appendChild( cell );
-	
-	var input = document.createElement( "select" );
-	cell.appendChild( input );
-	
-	label.htmlFor = input;
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return input;
-};
-
-netgis.Modal.prototype.createInputInteger = function( container, title, value, min, max )
-{
-	var row = document.createElement( "tr" );
-	//row.className = "netgis-hover-light";
-	
-	var head = document.createElement( "th" );
-	head.className = "netgis-padding";
-	
-	var label = document.createElement( "label" );
-	label.innerHTML = title;
-	head.appendChild( label );
-	row.appendChild( head );
-	
-	var cell = document.createElement( "td" );
-	cell.className = "netgis-padding";
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "number" );
-	input.setAttribute( "min", min );
-	input.setAttribute( "max", max );
-	input.value = Number.parseInt( value );
-	cell.appendChild( input );
-	row.appendChild( cell );
-	
-	label.htmlFor = input;
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return input;
-};
-
-netgis.Modal.prototype.createInputCheckbox = function( container, title, checked )
-{
-	var row = document.createElement( "tr" );
-	//row.className = "netgis-hover-light";
-	
-	var head = document.createElement( "th" );
-	head.className = "netgis-padding";
-	
-	var label = document.createElement( "label" );
-	label.innerHTML = title;
-	head.appendChild( label );
-	row.appendChild( head );
-	
-	var cell = document.createElement( "td" );
-	cell.className = "netgis-padding";
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "checkbox" );
-	input.checked = checked;
-	cell.appendChild( input );
-	row.appendChild( cell );
-	
-	label.htmlFor = input;
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return input;
-};
-
-netgis.Modal.prototype.createInputFile = function( container, title, filetypes, callback )
-{
-	var row = document.createElement( "tr" );
-	//row.className = "netgis-hover-light";
-	
-	var head = document.createElement( "th" );
-	head.className = "netgis-padding";
-	
-	var label = document.createElement( "label" );
-	label.innerHTML = title;
-	head.appendChild( label );
-	row.appendChild( head );
-	
-	var cell = document.createElement( "td" );
-	cell.className = "netgis-padding";
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "file" );
-	input.setAttribute( "accept", filetypes );
-	if ( callback ) input.addEventListener( "change", callback );
-	cell.appendChild( input );
-	row.appendChild( cell );
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return input;
-};
-
-netgis.Modal.prototype.createText = function( container, title, text )
-{
-	var row = document.createElement( "tr" );
-	//row.className = "netgis-padding";
-	
-	var head = document.createElement( "th" );
-	head.className = "netgis-padding";
-	head.innerHTML = title;
-	row.appendChild( head );
-	
-	var cell = document.createElement( "td" );
-	cell.className = "netgis-padding";
-	cell.innerHTML = text;
-	row.appendChild( cell );
-	
-	var content = container.getElementsByClassName( "netgis-modal-content" )[ 0 ];
-	var table = content.getElementsByTagName( "table" )[ 0 ];
-	table.appendChild( row );
-	
-	return cell;
-};
-
-netgis.Modal.prototype.onRootClick = function( e )
-{
-	if ( e.target !== this.root ) return;
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onHeaderClick = function( e )
-{
-	this.hide();
-};
-
-netgis.Modal.prototype.onImportGeoJSONShow = function( e )
-{
-	var input = this.importGeoJSON.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importGeoJSON.getElementsByTagName( "button" )[ 1 ];
-	input.value = "";
-	button.disabled = true;
-	
-	this.show( this.importGeoJSON );
-};
-
-netgis.Modal.prototype.onImportGeoJSONChange = function( e )
-{
-	var input = this.importGeoJSON.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importGeoJSON.getElementsByTagName( "button" )[ 1 ];
-	
-	if ( input.value && input.value.length > 0 )
-	{
-		button.disabled = false;
-	}
-	else
-	{
-		button.disabled = true;
-	}
-};
-
-netgis.Modal.prototype.onImportGeoJSONAccept = function( e )
-{
-	var input = this.importGeoJSON.getElementsByTagName( "input" )[ 0 ];
-	var file = input.files[ 0 ];
-	this.client.invoke( netgis.Events.IMPORT_GEOJSON, file );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onImportGMLShow = function( e )
-{
-	var input = this.importGML.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importGML.getElementsByTagName( "button" )[ 1 ];
-	input.value = "";
-	button.disabled = true;
-	
-	this.show( this.importGML );
-};
-
-netgis.Modal.prototype.onImportGMLChange = function( e )
-{
-	var input = this.importGML.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importGML.getElementsByTagName( "button" )[ 1 ];
-	
-	if ( input.value && input.value.length > 0 )
-	{
-		button.disabled = false;
-	}
-	else
-	{
-		button.disabled = true;
-	}
-};
-
-netgis.Modal.prototype.onImportGMLAccept = function( e )
-{
-	var input = this.importGML.getElementsByTagName( "input" )[ 0 ];
-	var file = input.files[ 0 ];
-	this.client.invoke( netgis.Events.IMPORT_GML, file );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onImportShapefileShow = function( e )
-{
-	var input = this.importShapefile.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importShapefile.getElementsByTagName( "button" )[ 1 ];
-	input.value = "";
-	button.disabled = true;
-	
-	this.show( this.importShapefile );
-};
-
-netgis.Modal.prototype.onImportShapefileChange = function( e )
-{
-	var input = this.importShapefile.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importShapefile.getElementsByTagName( "button" )[ 1 ];
-	
-	if ( input.value && input.value.length > 0 )
-	{
-		button.disabled = false;
-	}
-	else
-	{
-		button.disabled = true;
-	}
-};
-
-netgis.Modal.prototype.onImportShapefileAccept = function( e )
-{
-	var input = this.importShapefile.getElementsByTagName( "input" )[ 0 ];
-	var file = input.files[ 0 ];
-	this.client.invoke( netgis.Events.IMPORT_SHAPEFILE, file );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onImportSpatialiteShow = function( e )
-{
-	var input = this.importShapefile.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importShapefile.getElementsByTagName( "button" )[ 1 ];
-	input.value = "";
-	button.disabled = true;
-	
-	this.show( this.importSpatialite );
-};
-
-netgis.Modal.prototype.onImportSpatialiteChange = function( e )
-{
-	var input = this.importSpatialite.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importSpatialite.getElementsByTagName( "button" )[ 1 ];
-	
-	if ( input.value && input.value.length > 0 )
-	{
-		button.disabled = false;
-	}
-	else
-	{
-		button.disabled = true;
-	}
-};
-
-netgis.Modal.prototype.onImportSpatialiteAccept = function( e )
-{
-	var input = this.importSpatialite.getElementsByTagName( "input" )[ 0 ];
-	var file = input.files[ 0 ];
-	this.client.invoke( netgis.Events.IMPORT_SPATIALITE, file );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onImportGeopackageShow = function( e )
-{
-	var input = this.importGeopackage.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importGeopackage.getElementsByTagName( "button" )[ 1 ];
-	input.value = "";
-	button.disabled = true;
-	
-	this.show( this.importGeopackage );
-};
-
-netgis.Modal.prototype.onImportGeopackageChange = function( e )
-{
-	var input = this.importGeopackage.getElementsByTagName( "input" )[ 0 ];
-	var button = this.importGeopackage.getElementsByTagName( "button" )[ 1 ];
-	
-	if ( input.value && input.value.length > 0 )
-	{
-		button.disabled = false;
-	}
-	else
-	{
-		button.disabled = true;
-	}
-};
-
-netgis.Modal.prototype.onImportGeopackageAccept = function( e )
-{
-	var input = this.importGeopackage.getElementsByTagName( "input" )[ 0 ];
-	var file = input.files[ 0 ];
-	this.client.invoke( netgis.Events.IMPORT_GEOPACKAGE, file );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onExportPDFShow = function( e )
-{
-	var inputs = this.exportPDF.getElementsByTagName( "input" );
-	inputs[ 0 ].value = this.client.map.getWidth();
-	inputs[ 1 ].value = this.client.map.getHeight();
-	inputs[ 2 ].value = this.client.config.export.defaultMargin;
-	inputs[ 3 ].checked = true;
-	
-	//TODO: refactor into single export modal with format select?
-	
-	this.show( this.exportPDF );
-};
-
-netgis.Modal.prototype.onExportJPEGShow = function( e )
-{
-	var inputs = this.exportJPEG.getElementsByTagName( "input" );
-	inputs[ 0 ].value = this.client.map.getWidth();
-	inputs[ 1 ].value = this.client.map.getHeight();
-	
-	//TODO: refactor into single export modal with format select?
-	
-	this.show( this.exportJPEG );
-};
-
-netgis.Modal.prototype.onExportPNGShow = function( e )
-{
-	var inputs = this.exportPNG.getElementsByTagName( "input" );
-	inputs[ 0 ].value = this.client.map.getWidth();
-	inputs[ 1 ].value = this.client.map.getHeight();
-	
-	//TODO: refactor into single export modal with format select?
-	
-	this.show( this.exportPNG );
-};
-
-netgis.Modal.prototype.onExportGIFShow = function( e )
-{
-	var inputs = this.exportGIF.getElementsByTagName( "input" );
-	inputs[ 0 ].value = this.client.map.getWidth();
-	inputs[ 1 ].value = this.client.map.getHeight();
-	
-	//TODO: refactor into single export modal with format select?
-	
-	this.show( this.exportGIF );
-};
-
-netgis.Modal.prototype.onExportPDFAccept = function( e )
-{
-	var inputs = this.exportPDF.getElementsByTagName( "input" );
-	var resx = Number.parseInt( inputs[ 0 ].value );
-	var resy = Number.parseInt( inputs[ 1 ].value );
-	var margin = Number.parseInt( inputs[ 2 ].value );
-	var mode = inputs[ 3 ].checked;
-	this.client.invoke( netgis.Events.EXPORT_PDF, { resx: resx, resy: resy, mode: mode, margin: margin } );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onExportJPEGAccept = function( e )
-{
-	var inputs = this.exportJPEG.getElementsByTagName( "input" );
-	var resx = Number.parseInt( inputs[ 0 ].value );
-	var resy = Number.parseInt( inputs[ 1 ].value );
-	this.client.invoke( netgis.Events.EXPORT_JPEG, { resx: resx, resy: resy } );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onExportPNGAccept = function( e )
-{
-	var inputs = this.exportPNG.getElementsByTagName( "input" );
-	var resx = Number.parseInt( inputs[ 0 ].value );
-	var resy = Number.parseInt( inputs[ 1 ].value );
-	this.client.invoke( netgis.Events.EXPORT_PNG, { resx: resx, resy: resy } );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onExportGIFAccept = function( e )
-{
-	var inputs = this.exportGIF.getElementsByTagName( "input" );
-	var resx = Number.parseInt( inputs[ 0 ].value );
-	var resy = Number.parseInt( inputs[ 1 ].value );
-	this.client.invoke( netgis.Events.EXPORT_GIF, { resx: resx, resy: resy } );
-	
-	this.hide();
-};
-
-netgis.Modal.prototype.onAddServiceShow = function( e )
-{
-	//this.addService.getElementsByTagName( "input" )[ 0 ].value = "";
-	
-	this.show( this.addService );
-	
-	// Hide Details
-	var rows = this.addService.getElementsByTagName( "tr" );
-	
-	for ( var r = 3; r < rows.length; r++ )
-	{
-		rows[ r ].classList.add( "netgis-hide" );
-	}
-};
-
-netgis.Modal.prototype.onAddServiceLoad = function( e )
-{
-	var inputs = this.addService.getElementsByTagName( "input" );
-	var url = inputs[ 0 ].value;
-	
-	// Get Base URL
-	var qmark = url.indexOf( "?" );
-	var baseURL = ( qmark > -1 ) ? url.substr( 0, qmark ) : url;
-	var inputBaseURL = inputs[ 2 ];
-	inputBaseURL.value = baseURL;
-	
-	// Get Params
-	var params = [ "request=GetCapabilities" ];
-	
-	if ( qmark > -1 )
-	{
-		// Existing Params
-		var parts = url.substr( qmark + 1 );
-		parts = parts.split( "&" );
-		
-		for ( var p = 0; p < parts.length; p++ )
-		{
-			var part = parts[ p ];
-			part = part.toLowerCase();
-			
-			if ( part.search( "service" ) > -1 ) { params.push( part ); continue; }
-			if ( part.search( "version" ) > -1 ) { params.push( part ); continue; }
-		}
-	}
-	
-	// Capabilities URL
-	var getCaps = baseURL + "?" + params.join( "&" );
-	
-	netgis.util.request( getCaps, this.onAddServiceCapsResponse.bind( this ) );
-};
-
-netgis.Modal.prototype.onAddServiceCapsResponse = function( e )
-{
-	var parser = new DOMParser();
-	var xml = parser.parseFromString( e, "text/xml" );
-	var caps = xml.documentElement;
-	
-	var rows = this.addService.getElementsByTagName( "tr" );
-	var rowTitle = rows[ 6 ];
-	
-	var inputs = this.addService.getElementsByTagName( "input" );
-	var inputType = inputs[ 1 ];
-	
-	var selects = this.addService.getElementsByTagName( "select" );
-	var selectLayer = selects[ 0 ];
-	var selectFormat = selects[ 1 ];
-	
-	for ( var i = selectLayer.options.length - 1; i >= 0; i-- ) selectLayer.options.remove( i );
-	for ( var i = selectFormat.options.length - 1; i >= 0; i-- ) selectFormat.options.remove( i );
-	
-	switch ( caps.nodeName )
-	{
-		// WMS
-		case "WMS_Capabilities":
-		case "WMT_MS_Capabilities":
-		{
-			inputType.value = "wms";
-			
-			var version = caps.getAttribute( "version" );
-			var service = caps.getElementsByTagName( "Service" )[ 0 ];
-			var title = service.getElementsByTagName( "Title" )[ 0 ].textContent;
-			rowTitle.children[ 1 ].innerHTML = title;
-			
-			var layerItems = caps.getElementsByTagName( "Layer" );
-			var layers = [];
-			
-			for ( var l = 0; l < layerItems.length; l++ )
-			{
-				var item = layerItems[ l ];
-				var layerName = item.getElementsByTagName( "Name" )[ 0 ].textContent;
-				var layerTitle = item.getElementsByTagName( "Title" )[ 0 ].textContent;
-				
-				layers.push( { name: layerName, title: layerTitle } );
-				
-				var option = document.createElement( "option" );
-				option.text = layerTitle;
-				option.value = layerName;
-				selectLayer.options.add( option ); 
-			}
-			
-			var getMap = caps.getElementsByTagName( "GetMap" )[ 0 ];
-			var formatItems = getMap.getElementsByTagName( "Format" );
-			var formats = [];
-			
-			for ( var f = 0; f < formatItems.length; f++ )
-			{
-				var item = formatItems[ f ];
-				var format = item.textContent;
-				
-				formats.push( format );
-				
-				var option = document.createElement( "option" );
-				option.text = format;
-				option.value = format;
-				selectFormat.options.add( option );
-			}
-			
-			break;
-		}
-		
-		// WFS
-		case "WFS_Capabilities":
-		case "wfs:WFS_Capabilities":
-		{
-			inputType.value = "wfs";
-			
-			var version = caps.getAttribute( "version" );
-			var service = caps.getElementsByTagName( "ows:ServiceIdentification" )[ 0 ];
-			var title = service.getElementsByTagName( "ows:Title" )[ 0 ].textContent;
-			rowTitle.children[ 1 ].innerHTML = title;
-			
-			var featureTypeItems = caps.getElementsByTagName( "FeatureType" );
-			var types = [];
-			
-			for ( var l = 0; l < featureTypeItems.length; l++ )
-			{
-				var item = featureTypeItems[ l ];
-				var typeName = item.getElementsByTagName( "Name" )[ 0 ].textContent;
-				var typeTitle = item.getElementsByTagName( "Title" )[ 0 ].textContent;
-				
-				types.push( { name: typeName, title: typeTitle } );
-				
-				var option = document.createElement( "option" );
-				option.text = typeTitle;
-				option.value = typeName;
-				selectLayer.options.add( option ); 
-			}
-			
-			var operations = caps.getElementsByTagName( "ows:Operation" );
-			var getFeature = null;
-			
-			for ( var o = 0; o < operations.length; o++ )
-			{
-				if ( operations[ o ].getAttribute( "name" ) === "GetFeature" )
-				{
-					getFeature = operations[ o ];
-					break;
-				}
-			}
-			
-			if ( getFeature )
-			{
-				var parameters = getFeature.getElementsByTagName( "ows:Parameter" );
-				
-				for ( var p = 0; p < parameters.length; p++ )
-				{
-					var parameter = parameters[ p ];
-					
-					if ( parameter.getAttribute( "name" ) === "outputFormat" )
-					{
-						var formatItems = parameter.getElementsByTagName( "ows:Value" );
-
-						for ( var f = 0; f < formatItems.length; f++ )
-						{
-							var item = formatItems[ f ];
-							var format = item.textContent;
-
-							var option = document.createElement( "option" );
-							option.text = format;
-							option.value = format;
-							selectFormat.options.add( option );
-						}
-						
-						break;
-					}
-				}
-			}
-			
-			selectFormat.value = "application/json";
-			
-			break;
-		}
-	}
-	
-	// Show Details
-	var rows = this.addService.getElementsByTagName( "tr" );
-	
-	for ( var r = 3; r < rows.length; r++ )
-	{
-		rows[ r ].classList.remove( "netgis-hide" );
-	}
-};
-
-netgis.Modal.prototype.onAddServiceAccept = function( e )
-{
-	var inputs = this.addService.getElementsByTagName( "input" );
-	var selects = this.addService.getElementsByTagName( "select" );
-	
-	var url = inputs[ 0 ].value;
-	var type = inputs[ 1 ].value;
-	var baseURL = inputs[ 2 ].value;
-	
-	var selectLayer = selects[ 0 ];
-	var selectFormat = selects[ 1 ];
-	
-	var layerOption = selectLayer.options.item( selectLayer.options.selectedIndex );
-	var formatOption = selectFormat.options.item( selectFormat.options.selectedIndex );
-	
-	var id = this.addServiceID++;
-	
-	var params =
-	{
-		id: id,
-		url: baseURL,
-		title: layerOption.text,
-		name: layerOption.value,
-		format: formatOption.value
-	};
-	
-	switch ( type )
-	{
-		case "wms":
-		{
-			this.client.invoke( netgis.Events.ADD_SERVICE_WMS, params );
-			break;
-		}
-		
-		case "wfs":
-		{
-			this.client.invoke( netgis.Events.ADD_SERVICE_WFS, params );
-			break;
-		}
-	}
-	
-	this.hide();
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Modes.js b/templates/map/client/libs/netgis/Modes.js
deleted file mode 100644
index b339d0bb..00000000
--- a/templates/map/client/libs/netgis/Modes.js
+++ /dev/null
@@ -1,27 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.Modes = Object.freeze
-(
-	{
-		VIEW: "VIEW",
-		PANNING: "PANNING",
-		ZOOMING_IN: "ZOOMING_IN",
-		ZOOMING_OUT: "ZOOMING_OUT",
-		
-		DRAW_POINTS: "DRAW_POINTS",
-		DRAW_LINES: "DRAW_LINES",
-		DRAW_POLYGONS: "DRAW_POLYGONS",
-		
-		CUT_FEATURE_BEGIN: "CUT_FEATURE_BEGIN",
-		CUT_FEATURE_DRAW: "CUT_FEATURE_DRAW",
-		MODIFY_FEATURES: "MODIFY_FEATURES",
-		DELETE_FEATURES: "DELETE_FEATURES",
-		BUFFER_FEATURE_BEGIN: "BUFFER_FEATURE_BEGIN",
-		BUFFER_FEATURE_EDIT: "BUFFER_FEATURE_EDIT",
-		
-		SEARCH_PLACE: "SEARCH_PLACE",
-		SEARCH_PARCEL: "SEARCH_PARCEL"
-	}
-);
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/OWS.js b/templates/map/client/libs/netgis/OWS.js
deleted file mode 100644
index d41a0e1d..00000000
--- a/templates/map/client/libs/netgis/OWS.js
+++ /dev/null
@@ -1,237 +0,0 @@
-var netgis = netgis || {};
-
-netgis.OWS =
-(
-	function ()
-	{
-		"use strict";
-
-		// Variables
-
-		// Methods
-		var read = function( json, client )
-		{
-			var config =
-			{
-				layers: [],
-				folders: []
-			};
-			
-			// Properties
-			if ( netgis.util.isDefined( json.properties ) )
-			{
-				// BBox
-				var bbox = json.properties.bbox;
-
-				/*if ( netgis.util.isDefined( bbox ) )
-				{
-					client.invoke( netgis.Events.MAP_SET_EXTENT, { minx: bbox[ 0 ], miny: bbox[ 1 ], maxx: bbox[ 2 ], maxy: bbox[ 3 ] } );
-				}*/
-				
-				config.bbox = bbox;
-			}
-			
-			// Folders
-			var features = json.features;
-			
-			for ( var i = 0; i < features.length; i++ )
-			{
-				var feature = features[ i ];
-
-				if ( feature.type === "Feature" )
-				{
-					// Feature Properties
-					var props = feature.properties;
-					var path = props.folder;
-					
-					// Check Existing					
-					var found = false;
-					
-					for ( var f = 0; f < config.folders.length; f++ )
-					{
-						if ( config.folders[ f ].id === path )
-						{
-							found = true;
-							break;
-						}
-					}
-					
-					if ( found ) continue;
-					
-					// Path Parts
-					var partsRaw = path.split( "/" );
-					var parts = [];
-					
-					for ( var p = 0; p < partsRaw.length; p++ )
-					{
-						var part = partsRaw[ p ];
-						if ( part.length > 0 ) parts.push( part );
-					}
-					
-					// Find Parent
-					var parent = -1;
-					
-					for ( var p = 0; p < parts.length; p++ )
-					{
-						var part = parts[ p ];
-						var partpath = "/" + parts.slice( 0, p + 1 ).join( "/" );
-						
-						// Existing Folder
-						var exists = false;
-						
-						for ( var f = 0; f < config.folders.length; f++ )
-						{
-							if ( config.folders[ f ].path === partpath )
-							{
-								parent = f;
-								exists = true;
-								break;
-							}
-						}
-						
-						if ( exists ) continue;
-						
-						// Create New Folder
-						var index = config.folders.length;
-						
-						config.folders.push
-						(
-							{
-								title: part,
-								parent: parent,
-								path: partpath
-							}
-						);
-				
-						parent = index;
-					}
-				}
-			}
-			
-			// Features / Layers			
-			for ( var i = 0; i < features.length; i++ )
-			{
-				var feature = features[ i ];
-
-				if ( feature.type === "Feature" )
-				{
-					//TODO: refactor to read feature function
-
-					// Feature Properties
-					var props = feature.properties;
-					
-					// Folder
-					var folderIndex = -1;
-								
-					for ( var f = 0; f < config.folders.length; f++ )
-					{
-						if ( config.folders[ f ].path === props.folder )
-						{
-							folderIndex = f;
-							break;
-						}
-					}
-
-					// Offerings
-					var offers = props.offerings;
-
-					for ( var o = 0; o < offers.length; o++ )
-					{
-						var offer = offers[ o ];
-						
-						// Operationos
-						var ops = offer.operations;
-
-						// Types
-						switch ( offer.code )
-						{
-							// WMS
-							case "http://www.opengis.net/spec/owc-geojson/1.0/req/wms":
-							{
-								var getCaps = ops[ 0 ];
-								var url = getCaps.href;
-								
-								config.layers.push
-								(
-									{
-										folder: folderIndex,
-										type: netgis.LayerTypes.WMS,
-										url: url,
-										title: props.title,
-										attribution: props.rights,
-										active: props.active
-									}
-								);
-								
-								break;
-							}
-							
-							// XYZ
-							case "http://www.opengis.net/spec/owc-geojson/1.0/req/xyz":
-							{
-								var getTile = ops[ 0 ];
-								
-								config.layers.push
-								(
-									{
-										folder: folderIndex,
-										type: netgis.LayerTypes.XYZ,
-										url: getTile.href,
-										title: props.title,
-										attribution: props.rights,
-										active: props.active
-									}
-								);
-
-								break;
-							}
-
-							// OSM / XYZ
-							case "http://www.opengis.net/spec/owc-geojson/1.0/req/osm":
-							{
-								// Operations
-								/*for ( var oi = 0; oi < ops.length; oi++ )
-								{
-									var op = ops[ oi ];
-
-									switch ( op.code )
-									{
-										case ""
-									}
-								}*/
-
-								var getTile = ops[ 0 ];
-								
-								config.layers.push
-								(
-									{
-										folder: folderIndex,
-										type: netgis.LayerTypes.XYZ,
-										url: getTile.href,
-										title: props.title,
-										attribution: props.rights,
-										active: props.active
-									}
-								);
-
-								break;
-							}
-						}
-					}
-
-				}
-				
-			} // end for each feature
-			
-			client.invoke( netgis.Events.CONTEXT_UPDATE, config );
-		};
-
-		// Public Interface
-		var iface =
-		{
-			read: read
-		};
-
-		return iface;
-	}
-)();
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/SLD.js b/templates/map/client/libs/netgis/SLD.js
deleted file mode 100644
index b12db138..00000000
--- a/templates/map/client/libs/netgis/SLD.js
+++ /dev/null
@@ -1,79 +0,0 @@
-var netgis = netgis || {};
-
-//NOTE: https://portal.ogc.org/files/?artifact_id=22364 p. 53
-
-netgis.SLD =
-(
-	function ()
-	{
-		"use strict";
-
-		// Variables
-
-		// Methods
-		var read = function( data, client )
-		{
-			var parser = new DOMParser();
-			var xml = parser.parseFromString( data, "text/xml" );
-			
-			var style = {};
-			
-			// Layers
-			var layers = xml.getElementsByTagName( "NamedLayer" );
-			
-			for ( var i = 0; i < layers.length; i++ )
-			{
-				var layer = layers[ i ];
-				var name = layer.getElementsByTagName( "se:Name" )[ 0 ].innerHTML;
-				
-				console.info( "Layer:", name );
-				
-				// Type Styles
-				var typestyles = layer.getElementsByTagName( "se:FeatureTypeStyle" );
-				
-				for ( var j = 0; j < typestyles.length; j++ )
-				{
-					var typestyle = typestyles[ j ];
-					
-					// Rules
-					var rules = typestyle.getElementsByTagName( "se:Rule" );
-					
-					for ( var k = 0; k < rules.length; k++ )
-					{
-						var rule = rules[ k ];
-						var rulename = rule.getElementsByTagName( "se:Name" )[ 0 ].innerHTML;
-						
-						console.info( "Rule:", rulename );
-						
-						// Polygon Symbolizer
-						var polysymbol = rule.getElementsByTagName( "se:PolygonSymbolizer" )[ 0 ];
-						var polyfill = polysymbol.getElementsByTagName( "se:Fill" )[ 0 ];
-						var polystroke = polysymbol.getElementsByTagName( "se:Stroke" )[ 0 ];
-						
-						style[ "polygon" ] =
-						{
-							//fill: polyfill.getElementsByTagName( "se:SvgParameter" )
-							fill: polyfill.querySelector( "[name='fill']" ).innerHTML,
-							stroke: polystroke.querySelector( "[name='stroke']" ).innerHTML,
-							strokeWidth: Number.parseFloat( polystroke.querySelector( "[name='stroke-width']" ).innerHTML )
-						};
-					}
-				}
-			}
-			
-			console.info( "SLD:", style );
-			
-			client.invoke( netgis.Events.MAP_UPDATE_STYLE, style );
-			
-			return style;
-		};
-
-		// Public Interface
-		var iface =
-		{
-			read: read
-		};
-
-		return iface;
-	}
-)();
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/SearchParcel.css b/templates/map/client/libs/netgis/SearchParcel.css
deleted file mode 100644
index a5e4c9e7..00000000
--- a/templates/map/client/libs/netgis/SearchParcel.css
+++ /dev/null
@@ -1,131 +0,0 @@
-
-/* TODO: refactor into common panel class */
-
-.netgis-search-parcel
-{
-	position: absolute;
-	right: 0mm;
-	width: 100%;
-	max-width: 100mm;
-	top: 12mm;
-	bottom: 0mm;
-	overflow: auto;
-	z-index: 200;
-	
-	padding: 4mm;
-	
-	-webkit-transform: none;
-	transform: none;
-	transition: transform 150ms ease;
-}
-
-.netgis-search-parcel.netgis-hide
-{
-	display: initial;
-	
-	-webkit-transform: translateX( 110% );
-	transform: translateX( 110% );
-	transition: transform 150ms ease;
-	will-change: transform;
-}
-
-.netgis-search-parcel h3
-{
-	margin: 0mm;
-	margin-bottom: 4mm;
-}
-
-.netgis-search-parcel label
-{
-	display: block;
-	margin: 3mm 0mm;
-	margin-bottom: 0mm;
-	cursor: pointer;
-}
-
-.netgis-search-parcel input
-{
-	width: 100%;
-	height: 12mm;
-	margin: 3mm 0mm;
-	padding: 0mm 3mm;
-}
-
-.netgis-search-parcel .netgis-loader
-{
-	width: 6mm;
-	height: 6mm;
-	top: 8mm;
-	right: 6mm;
-	font-size: 6mm;
-}
-
-.netgis-search-parcel ul
-{
-	margin: 0mm;
-	padding: 0mm;
-	list-style-type: none;
-}
-
-.netgis-search-parcel li button
-{
-	text-align: left;
-}
-
-.netgis-search-parcel button
-{
-	display: block;
-	width: 100%;
-	height: 12mm;
-	padding: 0mm 3mm;
-	margin: 0mm;
-}
-
-.netgis-search-parcel .netgis-table-wrapper
-{
-	width: 100%;
-	/*height: 144mm; /* 12mm * 12 */
-	max-height: 120mm;
-	margin-top: 4mm;
-	overflow: auto;
-}
-
-.netgis-search-parcel table
-{
-	border-collapse: collapse;
-	white-space: nowrap;
-}
-
-.netgis-search-parcel tr
-{
-	height: 12mm;
-}
-
-.netgis-search-parcel th, .netgis-search-parcel td
-{
-	text-align: left;
-	padding: 0mm 3mm;
-}
-
-.netgis-search-parcel td
-{
-	cursor: pointer;
-}
-
-.netgis-search-parcel td:first-child
-{
-	padding: 0mm;
-}
-
-.netgis-search-parcel table button
-{
-	display: inline-block;
-	width: 12mm;
-	height: 12mm;
-}
-
-.netgis-search-parcel p
-{
-	margin: 4mm 3mm;
-	font-style: italic;
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/SearchParcel.js b/templates/map/client/libs/netgis/SearchParcel.js
deleted file mode 100644
index a2eef145..00000000
--- a/templates/map/client/libs/netgis/SearchParcel.js
+++ /dev/null
@@ -1,428 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.SearchParcel = function()
-{
-	this.client = null;
-};
-
-netgis.SearchParcel.prototype.load = function()
-{
-	this.root = document.createElement( "section" );
-	this.root.className = "netgis-search-parcel netgis-dialog netgis-shadow netgis-hide";
-	
-	// Head
-	var head = document.createElement( "h3" );
-	head.innerHTML = "Flurstücks-Suche:";
-	this.root.appendChild( head );
-	
-	// Form
-	var form = document.createElement( "div" );
-	this.root.appendChild( form );
-	
-	// Name Input ( "Gemarkung" )
-	var nameLabel = this.createInput( "Gemarkungsname:" );
-	nameLabel.style.position = "relative";
-	form.appendChild( nameLabel );
-	
-	this.nameInput = nameLabel.children[ 0 ];
-	this.nameInput.setAttribute( "title", "ENTER: Auswählen, ESCAPE: Zurücksetzen" );
-	this.nameInput.addEventListener( "keyup", this.onInputNameKey.bind( this ) );
-	
-	this.nameLoader = document.createElement( "div" );
-	this.nameLoader.className = "netgis-loader netgis-text-primary netgis-hide";
-	this.nameLoader.innerHTML = "<i class='fas fa-spinner'></i>";
-	nameLabel.appendChild( this.nameLoader );
-	
-	// Name Results
-	this.nameList = document.createElement( "ul" );	
-	form.appendChild( this.nameList );
-	
-	// District Input ( "Gemarkung" )
-	var districtLabel = this.createInput( "Gemarkungsnummer:" );
-	this.districtInput = districtLabel.children[ 0 ];
-	form.appendChild( districtLabel );
-	
-	// Field Input ( "Flur" )
-	var fieldLabel = this.createInput( "Flurnummer:" );
-	this.fieldInput = fieldLabel.children[ 0 ];
-	form.appendChild( fieldLabel );
-	
-	// Parcel Input ( "Flurstück" )
-	var parcelLabel = this.createInput( "Flurstücksnummer (Zähler/Nenner):" );
-	this.parcelInputA = parcelLabel.children[ 0 ];
-	this.parcelInputA.style.width = "48%";
-	this.parcelInputB = this.parcelInputA.cloneNode( true );
-	this.parcelInputB.style.marginLeft = "4%";
-	parcelLabel.appendChild( this.parcelInputB );
-	form.appendChild( parcelLabel );
-	
-	// Parcel Search
-	var parcelButton = document.createElement( "button" );
-	parcelButton.setAttribute( "type", "button" );
-	parcelButton.addEventListener( "click", this.onParcelSearchClick.bind( this ) );
-	parcelButton.className = "netgis-primary netgis-hover-primary";
-	parcelButton.innerHTML = "Flurstücke suchen";
-	parcelButton.style.marginTop = "4mm";
-	form.appendChild( parcelButton );
-	
-	// Parcel Results
-	this.parcelInfo = document.createElement( "p" );
-	form.appendChild( this.parcelInfo );
-	
-	this.parcelTable = this.createTable( [ "", "Flur", "FS Zähler", "FS Nenner", "FKZ", "Fläche (qm)" ] );
-	this.parcelTable.classList.add( "netgis-hide" );
-	form.appendChild( this.parcelTable );
-	
-	this.parcelList = this.parcelTable.getElementsByTagName( "tbody" )[ 0 ];
-	
-	this.parcelReset = document.createElement( "button" );
-	this.parcelReset.setAttribute( "type", "button" );
-	this.parcelReset.addEventListener( "click", this.onParcelResetClick.bind( this ) );
-	this.parcelReset.className = "netgis-primary netgis-hover-primary";
-	this.parcelReset.innerHTML = "Zurücksetzen";
-	this.parcelReset.style.marginTop = "4mm";
-	form.appendChild( this.parcelReset );
-	
-	// Initial State
-	this.reset();
-	
-	// Attach To Client
-	this.client.root.appendChild( this.root );
-	
-	this.client.on( netgis.Events.SET_MODE, this.onSetMode.bind( this ) );
-	this.client.on( netgis.Events.LAYER_LIST_TOGGLE, this.onLayerListToggle.bind( this ) );
-};
-
-netgis.SearchParcel.prototype.createInput = function( title )
-{
-	var label = document.createElement( "label" );
-	label.className = "netgis-hover-text-primary";
-	label.innerHTML = title;
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "text" );
-	label.appendChild( input );
-	
-	return label;
-};
-
-netgis.SearchParcel.prototype.createNameItem = function( title )
-{
-	var li = document.createElement( "li" );
-	
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.addEventListener( "click", this.onNameItemClick.bind( this ) );
-	button.className = "netgis-text-primary netgis-hover-light";
-	button.innerHTML = title;
-	li.appendChild( button );
-	
-	return li;
-};
-
-netgis.SearchParcel.prototype.createTable = function( columnNames )
-{
-	var wrapper = document.createElement( "div" );
-	wrapper.className = "netgis-table-wrapper";
-	
-	var table = document.createElement( "table" );
-	wrapper.appendChild( table );
-	
-	// Head
-	var head = document.createElement( "thead" );
-	table.appendChild( head );
-	
-	var row = document.createElement( "tr" );
-	row.className = "netgis-light";
-	row.style.position = "sticky";
-	head.appendChild( row );
-	
-	for ( var i = 0; i < columnNames.length; i++ )
-	{
-		var th = document.createElement( "th" );
-		th.innerHTML = columnNames[ i ];
-		row.appendChild( th );
-	}
-	
-	// Body
-	var body = document.createElement( "tbody" );
-	table.appendChild( body );
-	
-	return wrapper;
-};
-
-netgis.SearchParcel.prototype.createParcelItem = function( field, parcelA, parcelB, id, area, bbox, geom )
-{
-	//TODO: store geometry data on element vs. seperate data array ?
-	
-	var tr = document.createElement( "tr" );
-	tr.className = "netgis-hover-light netgis-hover-text-primary";
-	tr.setAttribute( "title", "Klicken zum zoomen" );
-	tr.setAttribute( "data-bbox", bbox );
-	tr.setAttribute( "data-geom", geom );
-	tr.addEventListener( "mouseenter", this.onParcelEnter.bind( this ) );
-	tr.addEventListener( "mouseleave", this.onParcelLeave.bind( this ) );
-	tr.addEventListener( "click", this.onParcelClick.bind( this ) );
-	
-	var buttonCell = document.createElement( "td" );
-	tr.appendChild( buttonCell );
-	
-	var importButton = document.createElement( "button" );
-	importButton.setAttribute( "type", "button" );
-	importButton.setAttribute( "title", "Geometrie übernehmen" );
-	importButton.addEventListener( "click", this.onParcelImportClick.bind( this ) );
-	importButton.className = "netgis-text-primary netgis-hover-primary";
-	importButton.innerHTML = "<i class='fas fa-paste'></i>";
-	buttonCell.appendChild( importButton );
-	
-	var fieldCell = document.createElement( "td" );
-	fieldCell.innerHTML = field;
-	tr.appendChild( fieldCell );
-	
-	var parcelCellA = document.createElement( "td" );
-	parcelCellA.innerHTML = parcelA;
-	tr.appendChild( parcelCellA );
-	
-	var parcelCellB = document.createElement( "td" );
-	parcelCellB.innerHTML = parcelB;
-	tr.appendChild( parcelCellB );
-	
-	var idCell = document.createElement( "td" );
-	idCell.innerHTML = id;
-	tr.appendChild( idCell );
-	
-	var areaCell = document.createElement( "td" );
-	areaCell.innerHTML = area;
-	tr.appendChild( areaCell );
-	
-	return tr;
-};
-
-netgis.SearchParcel.prototype.reset = function()
-{
-	this.nameLoader.classList.add( "netgis-hide" );
-	
-	this.nameInput.value = "";
-	this.districtInput.value = "";
-	this.fieldInput.value = "";
-	this.parcelInputA.value = "";
-	this.parcelInputB.value = "";
-	
-	this.nameList.innerHTML = "";
-	this.parcelInfo.innerHTML = "";
-	this.parcelList.innerHTML = "";
-	this.parcelTable.classList.add( "netgis-hide" );
-	
-	this.parcelReset.classList.add( "netgis-hide" );
-	
-	this.root.scrollTop = 0;
-};
-
-netgis.SearchParcel.prototype.onInputNameKey = function( e )
-{
-	switch ( e.keyCode )
-	{
-		// Enter
-		case 13:
-		{
-			this.selectFirstName();
-			break;
-		}
-		
-		// Escape
-		case 27:
-		{
-			this.reset();
-			break;
-		}
-		
-		default:
-		{
-			this.requestName( this.nameInput.value.trim() );
-			break;
-		}
-	}
-};
-
-netgis.SearchParcel.prototype.requestName = function( query )
-{
-	if ( this.nameDebounce ) window.clearTimeout( this.nameDebounce );
-	
-	if ( query.length === 0 ) return;
-	
-	/*var url = "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/gem_search.php?placename={q}";
-	url = "/geoportal/client/proxy.php?" + url;*/
-	var url = this.client.config.searchParcel.nameURL;
-	url = netgis.util.replace( url, "{q}", window.encodeURIComponent( query ) );
-	
-	this.nameDebounce = window.setTimeout( this.onInputNameDebounce.bind( this, url ), 200 );
-	
-	this.nameLoader.classList.remove( "netgis-hide" );
-};
-
-netgis.SearchParcel.prototype.onInputNameDebounce = function( url )
-{
-	netgis.util.request( url, this.onInputNameResponse.bind( this ) );
-};
-
-netgis.SearchParcel.prototype.onInputNameResponse = function( data )
-{
-	this.nameLoader.classList.add( "netgis-hide" );
-	
-	this.nameList.innerHTML = "";
-	
-	if ( data.charAt( 0 ) !== '{' && data.charAt( 0 ) !== '[' ) return;
-	
-	var json = JSON.parse( data );
-	
-	for ( var i = 0; i < json.data.length; i++ )
-	{
-		var item = json.data[ i ];
-		var li = this.createNameItem( item[ "gmk_name" ] );
-		li.getElementsByTagName( "button" )[ 0 ].setAttribute( "data-id", item[ "gmk_gmn" ] );
-		this.nameList.appendChild( li );
-	}
-};
-
-netgis.SearchParcel.prototype.onNameItemClick = function( e )
-{
-	var button = e.target;
-	var id = button.getAttribute( "data-id" );
-	
-	this.nameInput.value = button.innerHTML;
-	this.nameList.innerHTML = "";
-	
-	this.districtInput.value = id;
-};
-
-netgis.SearchParcel.prototype.selectFirstName = function()
-{
-	var buttons = this.nameList.getElementsByTagName( "button" );
-	
-	if ( buttons.length > 0 )
-	{
-		buttons[ 0 ].click();
-	}
-};
-
-netgis.SearchParcel.prototype.onParcelSearchClick = function( e )
-{
-	this.requestParcel
-	(
-		this.districtInput.value.trim(),
-		this.fieldInput.value.trim(),
-		this.parcelInputA.value.trim(),
-		this.parcelInputB.value.trim()
-	);
-};
-
-netgis.SearchParcel.prototype.requestParcel = function( district, field, parcelA, parcelB )
-{
-	//var url = "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/mod_alkis/flur_search.php?gmk_gmn={district}&fln={field}&fsn_zae={parcelA}&fsn_nen={parcelB}&export=json";
-	
-	var url = this.client.config.searchParcel.parcelURL;
-	
-	url = netgis.util.replace( url, "{district}", district ? district : "" );
-	url = netgis.util.replace( url, "{field}", field ? field : "" );
-	url = netgis.util.replace( url, "{parcelA}", parcelA ? parcelA : "" );
-	url = netgis.util.replace( url, "{parcelB}", parcelB ? parcelB : "" );
-	
-	//url = "/geoportal/client/proxy.php?" + url;
-	
-	this.parcelTable.classList.add( "netgis-hide" );
-	this.parcelList.innerHTML = "";
-	this.parcelInfo.innerHTML = "Suche Flurstücke...";
-	
-	netgis.util.request( url, this.onParcelResponse.bind( this ) );
-};
-
-netgis.SearchParcel.prototype.onParcelResponse = function( data )
-{
-	var json = JSON.parse( data );
-	
-	if ( json.count === 0 )
-	{
-		//TODO: if ( json.count === 0 ) -> json.Info
-		this.parcelInfo.innerHTML = json[ "Info" ];
-	}
-	else
-	{
-		this.parcelInfo.innerHTML = "Flurstücke gefunden: <span class='netgis-text-primary'>" + json[ "count" ] + "</span>";
-		
-		for ( var i = 0; i < json.data.length; i++ )
-		{
-			var result = json.data[ i ];
-			var item = this.createParcelItem
-			(
-				result[ "fln" ],
-				result[ "fsn_zae" ],
-				result[ "fsn_nen" ],
-				result[ "fsk" ],
-				result[ "flaeche" ],
-				result[ "bbox" ],
-				result[ "geometry" ]
-			);
-			this.parcelList.appendChild( item );
-		}
-		
-		this.parcelTable.classList.remove( "netgis-hide" );
-	}
-	
-	this.parcelReset.classList.remove( "netgis-hide" );
-	
-	if ( ! this.root.classList.contains( "netgis-hide" ) )
-		this.parcelTable.scrollIntoView();
-};
-
-netgis.SearchParcel.prototype.onParcelEnter = function( e )
-{
-	var tr = e.target;
-	var geom = tr.getAttribute( "data-geom" );
-	
-	this.client.invoke( netgis.Events.PARCEL_SHOW_PREVIEW, { geom: geom } );
-};
-
-netgis.SearchParcel.prototype.onParcelLeave = function( e )
-{
-	this.client.invoke( netgis.Events.PARCEL_HIDE_PREVIEW, null );
-};
-
-netgis.SearchParcel.prototype.onParcelClick = function( e )
-{
-	var tr = e.currentTarget;
-	var bbox = tr.getAttribute( "data-bbox" );
-	
-	this.client.invoke( netgis.Events.MAP_ZOOM_WKT, bbox );
-};
-
-netgis.SearchParcel.prototype.onParcelImportClick = function( e )
-{
-	var tr = e.currentTarget.parentElement.parentElement;
-	var geom = tr.getAttribute( "data-geom" );
-	
-	this.client.invoke( netgis.Events.IMPORT_WKT, geom );
-};
-
-netgis.SearchParcel.prototype.onParcelResetClick = function( e )
-{
-	this.reset();
-};
-
-netgis.SearchParcel.prototype.onSetMode = function( e )
-{
-	if ( e === netgis.Modes.SEARCH_PARCEL && this.root.classList.contains( "netgis-hide" ) )
-	{
-		this.root.classList.remove( "netgis-hide" );
-	}
-	else
-	{
-		this.root.classList.add( "netgis-hide" );
-	}
-};
-
-netgis.SearchParcel.prototype.onLayerListToggle = function( e )
-{
-	this.root.classList.add( "netgis-hide" );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/SearchPlace.js b/templates/map/client/libs/netgis/SearchPlace.js
deleted file mode 100644
index b6775070..00000000
--- a/templates/map/client/libs/netgis/SearchPlace.js
+++ /dev/null
@@ -1,59 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.SearchPlace = function()
-{
-	this.client = null;
-	this.timeout = null;
-	this.lastRequest = null;
-};
-
-netgis.SearchPlace.prototype.load = function()
-{
-	this.client.on( netgis.Events.SEARCH_PLACE_REQUEST, this.onSearchPlaceRequest.bind( this ) );
-};
-
-netgis.SearchPlace.prototype.request = function( query )
-{	
-	//NOTE: https://www.geoportal.rlp.de/mapbender/geoportal/gaz_geom_mobile.php?outputFormat=json&resultTarget=web&searchEPSG=25832&maxResults=5&maxRows=5&searchText=trier&featureClass=P&style=full&name_startsWith=trier
-	
-	//TODO: get url with query template from config
-	////var url = "https://www.geoportal.rlp.de/mapbender/geoportal/gaz_geom_mobile.php?outputFormat=json&resultTarget=web&searchEPSG={epsg}&maxResults=5&maxRows=5&featureClass=P&style=full&searchText={q}&name_startsWith={q}";
-	////url = "./proxy.php?" + url;
-	
-	if ( this.client.config.search && this.client.config.search.url )
-	{
-		var url = this.client.config.search.url;
-
-		var q = query;
-		q = q.trim();
-
-		url = netgis.util.replace( url, "{q}", window.encodeURIComponent( q ) );
-		url = netgis.util.replace( url, "{epsg}", 4326 ); // 25823
-		url = window.encodeURI( url );
-
-		this.lastRequest = netgis.util.request( url, this.onSearchPlaceResponse.bind( this ) );
-	}
-	else
-	{
-		console.warn( "No search API url configured for place search!" );
-	}
-};
-
-netgis.SearchPlace.prototype.onSearchPlaceRequest = function( e )
-{	
-	var query = e.query;
-	var self = this;
-	
-	// Debounce Request
-	if ( this.lastRequest ) this.lastRequest.abort();
-	if ( this.timeout ) window.clearTimeout( this.timeout );
-	this.timeout = window.setTimeout( function() { self.request( query ); }, 300 );
-};
-
-netgis.SearchPlace.prototype.onSearchPlaceResponse = function( data )
-{
-	var json = JSON.parse( data );
-	this.client.invoke( netgis.Events.SEARCH_PLACE_RESPONSE, json );
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Theme.css b/templates/map/client/libs/netgis/Theme.css
deleted file mode 100644
index 9bd2c470..00000000
--- a/templates/map/client/libs/netgis/Theme.css
+++ /dev/null
@@ -1,69 +0,0 @@
-/* TODO: rename to config.css ? */
-
-/* Font */
-
-.netgis-client, .netgis-client button
-{
-	font-family: Verdana, sans-serif;
-	font-size: 4mm;
-}
-
-/* Colors */
-
-/* TODO: !important on colors necessary ? */
-
-.netgis-primary { background-color: #a7233f !important; color: white !important; }
-.netgis-hover-primary:hover { background-color: #c82a4b !important; color: white !important; }
-.netgis-light { background-color: #f4f4f4 !important; }
-.netgis-hover-light:hover { background-color: #f4f4f4 !important; }
-.netgis-text-primary { color: #a7233f !important; }
-.netgis-hover-text-primary:hover { color: #c82a4b !important; }
-.netgis-dialog { background: #fff; color: #000; }
-.netgis-dropdown:hover > button { background-color: #c82a4b !important; }
-
-/* Effects */
-
-.netgis-shadow
-{
-	box-shadow: 0mm 0.5mm 1mm 0mm rgba( 0, 0, 0, 0.2 ), 0mm 1mm 2.5mm 0mm rgba( 0, 0, 0, 0.1 ) !important;
-}
-
-.netgis-shadow-large
-{
-	box-shadow: 0mm 1mm 2mm 0mm rgba( 0, 0, 0, 0.3 ), 0mm 2mm 5mm 0mm rgba( 0, 0, 0, 0.15 ) !important;
-}
-
-.netgis-text-shadow
-{
-	text-shadow: 0mm 0mm 1mm rgba( 0, 0, 0, 1.0 );
-}
-
-/* Elements */
-/*
-.netgis-client button
-{
-	min-height: 12mm;
-	min-width: 12mm;
-	/*padding: 0mm;*
-	border: none;
-	background: none;
-	/*color: white;*
-	cursor: pointer;
-}
-*/
-
-.netgis-client button
-{
-	border: none;
-	background: none;
-	cursor: pointer;
-}
-
-/* Format */
-
-.netgis-clip-text
-{
-	overflow: hidden;
-	white-space: nowrap;
-	text-overflow: ellipsis;
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Toolbar.css b/templates/map/client/libs/netgis/Toolbar.css
deleted file mode 100644
index 2bcfff4d..00000000
--- a/templates/map/client/libs/netgis/Toolbar.css
+++ /dev/null
@@ -1,139 +0,0 @@
-.netgis-toolbars
-{
-	position: absolute;
-	left: 0mm;
-	right: 0mm;
-	top: 0mm;
-}
-
-.netgis-toolbar
-{
-	position: absolute;
-	left: 0mm;
-	right: 0mm;
-	/*min-width: 100%; /* NOTE: https://stackoverflow.com/questions/10891293/prevent-float-left-div-from-going-to-a-new-line */
-	top: 12mm;
-	min-height: 12mm;
-	line-height: 12mm;
-	font-size: 0mm;
-	white-space: nowrap;
-	z-index: 1;
-	
-	-webkit-transform: none;
-	transform: none;
-	transition: transform 150ms ease;
-}
-
-.netgis-toolbar.netgis-hide
-{
-	-webkit-transform: translateY( -24mm );
-	transform: translateY( -24mm );
-	transition: transform 150ms ease;
-	will-change: transform;
-}
-
-.netgis-toolbar > div
-{
-	height: 12mm;
-	white-space: nowrap;
-}
-
-.netgis-toolbar > div > *
-{
-	display: inline-block;
-	font-size: 4mm;
-	/*float: left; /* TODO: float cause line breaks */
-}
-
-.netgis-toolbar button
-{
-	/*padding: 0mm 4mm;*/
-	padding: 0mm 4mm 0mm 0mm;
-}
-
-.netgis-toolbar > div > button
-{
-	line-height: 12mm;
-}
-
-.netgis-toolbar button i
-{
-	/*margin-right: 4mm;*/
-	width: 12mm;
-}
-
-.netgis-toolbar button:last-child
-{
-	padding-right: 0mm;
-}
-
-.netgis-toolbar button:last-child span
-{
-	margin-right: 4mm;
-}
-
-/*.netgis-toolbar button i:last-child
-{
-	margin-right: 0mm;
-}*/
-
-.netgis-toolbar label
-{
-	display: inline-block;
-	height: 12mm;
-	padding: 0mm 4mm;
-	cursor: pointer;
-}
-
-.netgis-toolbar input[type=checkbox]
-{
-	margin-right: 2mm;
-}
-
-.netgis-toolbar input[type=number]
-{
-	margin-left: 2mm;
-	width: 20mm;
-}
-
-.netgis-toolbar input[type=text]
-{
-	/*margin-left: 2mm;*/
-	width: 60mm;
-}
-
-/* TODO: refactor to abstract common dropdown list style ( see head menu ) */
-
-.netgis-toolbar .netgis-search-list
-{
-	position: absolute;
-	min-width: 68mm; /* 60mm + 4mm + 4mm ( input width + padding ) */
-	padding: 0mm;
-	margin: 0mm;
-	margin-left: -4mm;
-	z-index: 1;
-	list-style-type: none;
-	overflow: hidden;
-	box-shadow: 0mm 0.5mm 0.5mm 0mm rgba( 0, 0, 0, 0.2 )/*, 0mm 1mm 2.5mm 0mm rgba( 0, 0, 0, 0.1 )*/ !important;
-}
-
-.netgis-toolbar .netgis-search-list.netgis-hide
-{
-	display: none;
-}
-
-.netgis-toolbar .netgis-search-list li
-{
-	width: 100%;
-	padding: 0mm;
-	margin: 0mm;
-}
-
-.netgis-toolbar .netgis-search-list li button
-{
-	width: 100%;
-	height: 12mm;
-	padding: 0mm 4mm 0mm 4mm;
-	white-space: nowrap;
-	text-align: left;
-}
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Toolbar.js b/templates/map/client/libs/netgis/Toolbar.js
deleted file mode 100644
index 5cbe8ddb..00000000
--- a/templates/map/client/libs/netgis/Toolbar.js
+++ /dev/null
@@ -1,564 +0,0 @@
-"use strict";
-
-var netgis = netgis || {};
-
-netgis.Toolbar = function()
-{
-	this.client = null;
-	this.toolbars = {};
-	this.searchValue = "";
-};
-
-netgis.Toolbar.prototype.load = function()
-{
-	var config = this.client.config;
-	
-	this.root = document.createElement( "section" ); // header?
-	this.root.className = "netgis-toolbars";
-	
-	if ( this.client.editable )
-	{
-		var bufferDefaultRadius = 1000;
-		var bufferDefaultSegments = 3;
-		
-		if ( netgis.util.isDefined( config.tools ) )
-		{
-			if ( netgis.util.isDefined( config.tools.buffer.defaultRadius ) ) bufferDefaultRadius = config.tools.buffer.defaultRadius;
-			if ( netgis.util.isDefined( config.tools.buffer.defaultSegments ) ) bufferDefaultSegments = config.tools.buffer.defaultSegments;
-		}	
-		
-		// Draw
-		this.toolbars[ netgis.Modes.DRAW_POINTS ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.DRAW_POINTS ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Punkte zeichnen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_POINTS ], this.createToolbarCheckbox( "Einrasten", this.onSnapChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_POINTS ], this.createToolbarCheckbox( "Puffern", this.onDrawBufferChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_POINTS ], this.createToolbarInput( "Radius (Meter):", bufferDefaultRadius, this.onDrawBufferRadiusChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_POINTS ], this.createToolbarInput( "Segmente:", bufferDefaultSegments, this.onDrawBufferSegmentsChange.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.DRAW_POINTS ] );
-
-		this.toolbars[ netgis.Modes.DRAW_LINES ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.DRAW_LINES ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Linien zeichnen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_LINES ], this.createToolbarCheckbox( "Einrasten", this.onSnapChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_LINES ], this.createToolbarCheckbox( "Puffern", this.onDrawBufferChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_LINES ], this.createToolbarInput( "Radius (Meter):", bufferDefaultRadius, this.onDrawBufferRadiusChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_LINES ], this.createToolbarInput( "Segmente:", bufferDefaultSegments, this.onDrawBufferSegmentsChange.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.DRAW_LINES ] );
-		
-		this.showDrawBufferOptions( false );
-
-		this.toolbars[ netgis.Modes.DRAW_POLYGONS ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.DRAW_POLYGONS ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Polygone zeichnen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_POLYGONS ], this.createToolbarCheckbox( "Einrasten", this.onSnapChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.DRAW_POLYGONS ], this.createToolbarCheckbox( "Tracing", this.onTracingChange.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.DRAW_POLYGONS ] );
-
-		// Edit
-		this.toolbars[ netgis.Modes.CUT_FEATURE_BEGIN ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.CUT_FEATURE_BEGIN ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Feature zum Ausschneiden wählen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.CUT_FEATURE_BEGIN ] );
-
-		this.toolbars[ netgis.Modes.CUT_FEATURE_DRAW ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.CUT_FEATURE_DRAW ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Fläche zum Ausschneiden zeichnen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.CUT_FEATURE_DRAW ] );
-
-		this.toolbars[ netgis.Modes.MODIFY_FEATURES ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.MODIFY_FEATURES ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Feature-Eckpunkte verschieben:</span>', this.onToolbarClose.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.MODIFY_FEATURES ] );
-
-		this.toolbars[ netgis.Modes.DELETE_FEATURES ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.DELETE_FEATURES ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Features löschen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.DELETE_FEATURES ] );
-
-		this.toolbars[ netgis.Modes.BUFFER_FEATURE_BEGIN ] = this.createToolbar();
-		this.append( this.toolbars[ netgis.Modes.BUFFER_FEATURE_BEGIN ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Feature zum Puffern wählen:</span>', this.onToolbarClose.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.BUFFER_FEATURE_BEGIN ] );
-
-		this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ] = this.createToolbar();
-		
-		//var wrapper = document.createElement( "div" );
-		//this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].appendChild( wrapper );
-		
-		this.append( this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Feature puffern:</span>', this.onBufferCancel.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ], this.createToolbarInput( "Radius (Meter):", bufferDefaultRadius, this.onBufferChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ], this.createToolbarInput( "Segmente:", bufferDefaultSegments, this.onBufferChange.bind( this ) ) );
-		this.append( this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ], this.createToolbarButton( '<i class="fas fa-check"></i><span>OK</span>', this.onBufferAccept.bind( this ) ) );
-		
-		//var self = this;
-		//setTimeout( function() { self.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].classList.remove( "netgis-hide" ); }, 100 );
-		
-		/*
-		this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].appendChild( this.createToolbarButton( '<i class="fas fa-times"></i><span>Feature puffern:</span>', this.onBufferCancel.bind( this ) ) );
-		this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].appendChild( this.createToolbarInput( "Radius in Meter:", this.client.config.tools.buffer.defaultRadius, this.onBufferChange.bind( this ) ) );
-		this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].appendChild( this.createToolbarInput( "Segmente:", this.client.config.tools.buffer.defaultSegments, this.onBufferChange.bind( this ) ) );
-		*/
-		
-		var bufferInputs = this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].getElementsByTagName( "input" );
-		bufferInputs[ 0 ].addEventListener( "keyup", this.onBufferKeyUp.bind( this ) );
-		bufferInputs[ 1 ].addEventListener( "keyup", this.onBufferKeyUp.bind( this ) );
-		bufferInputs[ 1 ].setAttribute( "min", 1 );
-		
-		//this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].appendChild( this.createToolbarButton( '<i class="fas fa-check"></i><span>OK</span>', this.onBufferAccept.bind( this ) ) );
-		this.root.appendChild( this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ] );
-	}
-	
-	// Search
-	this.toolbars[ netgis.Modes.SEARCH_PLACE ] = this.createToolbar();
-	this.append( this.toolbars[ netgis.Modes.SEARCH_PLACE ], this.createToolbarButton( '<i class="fas fa-times"></i><span>Suche:</span>', this.onToolbarClose.bind( this ) ) );
-	
-	var searchInput = this.createToolbarInputText( "Adresse...", "", null );
-	searchInput.style.position = "relative";
-	
-	this.searchInput = searchInput.getElementsByTagName( "input" )[ 0 ];
-	//this.searchInput.addEventListener( "change", this.onSearchChange.bind( this ) );
-	//this.searchInput.addEventListener( "keypress", this.onSearchKeyPress.bind( this ) );
-	this.searchInput.addEventListener( "keyup", this.onSearchKeyUp.bind( this ) );
-	this.searchInput.addEventListener( "focus", this.onSearchFocus.bind( this ) );
-	this.searchInput.addEventListener( "blur", this.onSearchBlur.bind( this ) );
-	
-	/*var searchClear = document.createElement( "button" );
-	searchClear.innerHTML = "<i class='fas fa-undo-alt'></i>";
-	searchInput.appendChild( searchClear );*/
-	
-	this.append( this.toolbars[ netgis.Modes.SEARCH_PLACE ], searchInput );
-	
-	this.searchList = document.createElement( "ul" );
-	this.searchList.className = "netgis-dropdown-content netgis-search-list netgis-dialog netgis-shadow netgis-hide";
-	searchInput.appendChild( this.searchList );
-	
-	//TODO: search dropdown not working if toolbar has overflow-y hidden
-	
-	//TODO: refactor search list to abstract dropdown component ( see head menus )
-	
-	//this.toolbars[ netgis.MapModes.SEARCH_PLACE ].appendChild( this.createToolbarButton( '<i class="fas fa-check"></i>OK', this.onBufferAccept.bind( this ) ) );
-	this.append( this.toolbars[ netgis.Modes.SEARCH_PLACE ], this.createToolbarButton( '<i class="fas fa-undo"></i>', this.onSearchClear.bind( this ) ) );
-	
-	this.root.appendChild( this.toolbars[ netgis.Modes.SEARCH_PLACE ] );
-	
-	this.client.root.appendChild( this.root );
-	
-	// Events
-	this.client.on( netgis.Events.SET_MODE, this.onSetMode.bind( this ) );
-	this.client.on( netgis.Events.SEARCH_PLACE_RESPONSE, this.onSearchPlaceResponse.bind( this ) );
-};
-
-netgis.Toolbar.prototype.createToolbar = function()
-{
-	var toolbar = document.createElement( "div" );
-	toolbar.className = "netgis-toolbar netgis-dialog netgis-shadow netgis-hide";
-	
-	var wrapper = document.createElement( "div" );
-	toolbar.appendChild( wrapper );
-	
-	return toolbar;
-};
-
-netgis.Toolbar.prototype.append = function( toolbar, child )
-{
-	var wrapper = toolbar.getElementsByTagName( "div" )[ 0 ];
-	wrapper.appendChild( child );
-};
-
-netgis.Toolbar.prototype.createToolbarButton = function( content, callback )
-{
-	var button = document.createElement( "button" );
-	button.setAttribute( "type", "button" );
-	button.className = "netgis-hover-light";
-	button.innerHTML = content;
-	button.addEventListener( "click", callback );
-	
-	return button;
-};
-
-netgis.Toolbar.prototype.createToolbarCheckbox = function( title, callback )
-{
-	var label = document.createElement( "label" );
-	label.className = "netgis-hover-light";
-	
-	var checkbox = document.createElement( "input" );
-	checkbox.setAttribute( "type", "checkbox" );
-	checkbox.addEventListener( "change", callback );
-	label.appendChild( checkbox );
-	
-	var text = document.createTextNode( title );
-	label.appendChild( text );
-	
-	return label;
-};
-
-netgis.Toolbar.prototype.createToolbarInput = function( title, value, callback )
-{
-	var label = document.createElement( "label" );
-	label.className = "netgis-hover-light";
-	
-	var text = document.createTextNode( title );
-	label.appendChild( text );
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "number" );
-	input.setAttribute( "min", 0 );
-	input.setAttribute( "step", 0.01 );
-	input.value = value;
-	input.addEventListener( "change", callback );
-	input.addEventListener( "keyup", callback );
-	label.appendChild( input );
-	
-	return label;
-};
-
-netgis.Toolbar.prototype.createToolbarInputText = function( title, value, callback )
-{
-	var label = document.createElement( "label" );
-	label.className = "netgis-hover-light";
-	
-	/*var text = document.createTextNode( title );
-	label.appendChild( text );*/
-	
-	var input = document.createElement( "input" );
-	input.setAttribute( "type", "text" );
-	input.setAttribute( "placeholder", title );
-	input.value = value;
-	if ( callback ) input.addEventListener( "change", callback );
-	label.appendChild( input );
-	
-	return label;
-};
-
-netgis.Toolbar.prototype.onSetMode = function( e )
-{
-	var mode = e;
-	
-	// Store old search mode to allow toggling search toolbar
-	var searchMode = ! this.toolbars[ netgis.Modes.SEARCH_PLACE ].classList.contains( "netgis-hide" );
-	
-	// Toggle Toolbars
-	netgis.util.foreach
-	(
-		this.toolbars,
-		function( index, toolbar )
-		{
-			if ( index === mode )
-				toolbar.classList.remove( "netgis-hide" );
-			else
-				toolbar.classList.add( "netgis-hide" );
-		}
-	);
-	
-	// Mode
-	switch ( mode )
-	{
-		case netgis.Modes.SEARCH_PLACE:
-		{
-			//TODO: toggle mode event ?
-			
-			if ( ! searchMode )
-				this.searchInput.focus();
-			else
-				this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-			
-			break;
-		}
-		
-		case netgis.Modes.BUFFER_FEATURE_EDIT:
-		{
-			this.updateBuffer();
-			break;
-		}
-		
-		case netgis.Modes.DRAW_POINTS:
-		case netgis.Modes.DRAW_LINES:
-		{
-			var checkbox = this.toolbars[ netgis.Modes.DRAW_POINTS ].getElementsByTagName( "input" )[ 1 ];
-			
-			if ( checkbox.checked )
-			{
-				this.client.invoke( netgis.Events.DRAW_BUFFER_ON, null );
-			}
-			
-			break;
-		}
-	}
-};
-
-netgis.Toolbar.prototype.onToolbarClose = function( e )
-{
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-};
-
-netgis.Toolbar.prototype.searchRequest = function( value )
-{
-	value = value.trim();
-	
-	if ( value !== this.searchValue )
-	{
-		this.searchValue = value;
-
-		if ( value.length > 0 )
-		{
-			this.client.invoke( netgis.Events.SEARCH_PLACE_REQUEST, { query: value } );
-		}
-	}
-	
-	//TODO: refactor into search module ?
-};
-
-netgis.Toolbar.prototype.searchClear = function()
-{
-	this.searchInput.value = "";
-	this.searchList.innerHTML = "";
-};
-
-netgis.Toolbar.prototype.searchSelectFirst = function()
-{
-	var buttons = this.searchList.getElementsByTagName( "button" );
-	
-	if ( buttons.length > 0 )
-	{
-		this.onSearchItemClick( { target: buttons[ 0 ] } );
-	}
-};
-
-netgis.Toolbar.prototype.onSearchKeyUp = function( e )
-{
-	var input = e.target;
-	var key = e.keyCode;
-	
-	// a-z = 65-90
-	// 0-9 = 48-57
-	
-	switch ( key )
-	{
-		// Enter
-		case 13:
-		{
-			this.searchSelectFirst();
-			this.searchList.classList.add( "netgis-hide" );
-			break;
-		}
-		
-		// Escape
-		case 27:
-		{
-			this.searchClear();
-			break;
-		}
-		
-		default:
-		{
-			this.searchRequest( input.value );
-			break;
-		}
-	}
-};
-
-netgis.Toolbar.prototype.onSearchChange = function( e )
-{
-	var input = e.target;
-	this.searchRequest( input.value );
-	
-	/*this.client.invoke( netgis.Events.SEARCH_PLACE_REQUEST, { query: input.value } );
-	console.info( "Search Change:", input.value );*/
-};
-
-netgis.Toolbar.prototype.onSearchClear = function( e )
-{
-	this.searchClear();
-	this.searchInput.focus();
-};
-
-netgis.Toolbar.prototype.onSearchFocus = function( e )
-{
-	this.searchList.classList.remove( "netgis-hide" );
-};
-
-netgis.Toolbar.prototype.onSearchBlur = function( e )
-{
-	this.searchList.classList.add( "netgis-hide" );
-};
-
-netgis.Toolbar.prototype.onSearchPlaceResponse = function( e )
-{
-	this.searchList.innerHTML = "";
-	
-	var results = e.geonames;
-	
-	for ( var i = 0; i < results.length; i++ )
-	{
-		var result = results[ i ];
-		
-		var item = document.createElement( "li" );
-		item.className = "netgis-hover-light";
-
-		var button = document.createElement( "button" );
-		button.setAttribute( "type", "button" );
-		button.innerHTML = result.title;
-		button.dataset.title = result.title;
-		button.dataset.minx = result.minx;
-		button.dataset.miny = result.miny;
-		button.dataset.maxx = result.maxx;
-		button.dataset.maxy = result.maxy;
-		button.addEventListener( "mousedown", this.onSearchItemClick.bind( this ) );
-		item.appendChild( button );
-		
-		this.searchList.appendChild( item );
-	}
-};
-
-netgis.Toolbar.prototype.onSearchItemClick = function( e )
-{
-	var button = e.target;
-	
-	var title = button.dataset.title;
-	var minx = Number.parseFloat( button.dataset.minx );
-	var miny = Number.parseFloat( button.dataset.miny );
-	var maxx = Number.parseFloat( button.dataset.maxx );
-	var maxy = Number.parseFloat( button.dataset.maxy );
-	
-	this.client.invoke( netgis.Events.MAP_SET_EXTENT, { minx: minx, miny: miny, maxx: maxx, maxy: maxy } );
-	
-	//this.searchInput.value = title;
-	this.searchValue = title;
-};
-
-netgis.Toolbar.prototype.updateBuffer = function()
-{
-	var inputs = this.toolbars[ netgis.Modes.BUFFER_FEATURE_EDIT ].getElementsByTagName( "input" );
-	var radius = Number.parseFloat( inputs[ 0 ].value );
-	var segments = Number.parseInt( inputs[ 1 ].value );
-	
-	this.client.invoke( netgis.Events.BUFFER_CHANGE, { radius: radius, segments: segments } );
-};
-
-netgis.Toolbar.prototype.onBufferChange = function( e )
-{
-	this.updateBuffer();
-};
-
-netgis.Toolbar.prototype.onBufferKeyUp = function( e )
-{
-	var key = e.keyCode;
-	
-	// Enter
-	//if ( key === 13 )
-	{
-		this.updateBuffer();
-	}
-};
-
-netgis.Toolbar.prototype.onBufferAccept = function( e )
-{
-	this.client.invoke( netgis.Events.BUFFER_ACCEPT, null );
-	//this.setMode( netgis.Modes.VIEW );
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-};
-
-netgis.Toolbar.prototype.onBufferCancel = function( e )
-{
-	this.client.invoke( netgis.Events.BUFFER_CANCEL, null );
-	//this.setMode( netgis.Modes.VIEW );
-	this.client.invoke( netgis.Events.SET_MODE, netgis.Modes.VIEW );
-};
-
-netgis.Toolbar.prototype.onSnapChange = function( e )
-{
-	var input = e.target;
-	var on = input.checked;
-	
-	this.toolbars[ netgis.Modes.DRAW_POINTS ].getElementsByTagName( "input" )[ 0 ].checked = on;
-	this.toolbars[ netgis.Modes.DRAW_LINES ].getElementsByTagName( "input" )[ 0 ].checked = on;
-	this.toolbars[ netgis.Modes.DRAW_POLYGONS ].getElementsByTagName( "input" )[ 0 ].checked = on;
-	
-	this.client.invoke( on ? netgis.Events.SNAP_ON : netgis.Events.SNAP_OFF, null );
-};
-
-netgis.Toolbar.prototype.onTracingChange = function( e )
-{
-	var input = e.target;
-	var on = input.checked;
-	
-	var snapInput = this.toolbars[ netgis.Modes.DRAW_POLYGONS ].getElementsByTagName( "input" )[ 0 ];
-	var snap = snapInput.checked;
-	
-	if ( on && !snap )
-	{
-		snapInput.checked = on;
-		this.client.invoke( netgis.Events.SNAP_ON, null );
-	}
-	
-	this.client.invoke( on ? netgis.Events.TRACING_ON : netgis.Events.TRACING_OFF, null );
-};
-
-netgis.Toolbar.prototype.onDrawBufferChange = function( e )
-{
-	var input = e.target;
-	var on = input.checked;
-	
-	this.toolbars[ netgis.Modes.DRAW_POINTS ].getElementsByTagName( "input" )[ 1 ].checked = on;
-	this.toolbars[ netgis.Modes.DRAW_LINES ].getElementsByTagName( "input" )[ 1 ].checked = on;
-	
-	this.client.invoke( on ? netgis.Events.DRAW_BUFFER_ON : netgis.Events.DRAW_BUFFER_OFF, null );
-	
-	this.showDrawBufferOptions( on );
-	
-	// Update Buffer Values
-	if ( on )
-	{
-		var points = true;
-		if ( ! this.toolbars[ netgis.Modes.DRAW_LINES ].classList.contains( "netgis-hide" ) ) points = false;
-		
-		var inputs = this.toolbars[ points ? netgis.Modes.DRAW_POINTS : netgis.Modes.DRAW_LINES ].getElementsByTagName( "input" );
-		var radius = Number.parseInt( inputs[ 2 ].value );
-		var segments = Number.parseInt( inputs[ 3 ].value );
-		
-		this.client.invoke( netgis.Events.DRAW_BUFFER_RADIUS_CHANGE, radius );
-		this.client.invoke( netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE, segments );
-	}
-};
-
-netgis.Toolbar.prototype.onDrawBufferRadiusChange = function( e )
-{
-	var input = e.target;
-	var radius = Number.parseFloat( input.value );
-	
-	this.client.invoke( netgis.Events.DRAW_BUFFER_RADIUS_CHANGE, radius );
-	
-	var pointsInput = this.toolbars[ netgis.Modes.DRAW_POINTS ].getElementsByTagName( "input" )[ 2 ];
-	if ( input !== pointsInput ) pointsInput.value = radius;
-	
-	var linesInput = this.toolbars[ netgis.Modes.DRAW_LINES ].getElementsByTagName( "input" )[ 2 ];
-	if ( input !== linesInput ) linesInput.value = radius;
-};
-
-netgis.Toolbar.prototype.onDrawBufferSegmentsChange = function( e )
-{
-	var input = e.target;
-	var segs = Number.parseInt( input.value );
-	
-	this.client.invoke( netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE, segs );
-	
-	var pointsInput = this.toolbars[ netgis.Modes.DRAW_POINTS ].getElementsByTagName( "input" )[ 3 ];
-	if ( input !== pointsInput ) pointsInput.value = segs;
-	
-	var linesInput = this.toolbars[ netgis.Modes.DRAW_LINES ].getElementsByTagName( "input" )[ 3 ];
-	if ( input !== linesInput ) linesInput.value = segs;
-};
-
-netgis.Toolbar.prototype.showDrawBufferOptions = function( on )
-{
-	var pointsItems = this.toolbars[ netgis.Modes.DRAW_POINTS ].children[ 0 ].children;
-	var linesItems = this.toolbars[ netgis.Modes.DRAW_LINES ].children[ 0 ].children;
-	
-	if ( on )
-	{
-		pointsItems[ 3 ].classList.remove( "netgis-hide" );
-		pointsItems[ 4 ].classList.remove( "netgis-hide" );
-		linesItems[ 3 ].classList.remove( "netgis-hide" );
-		linesItems[ 4 ].classList.remove( "netgis-hide" );
-	}
-	else
-	{
-		pointsItems[ 3 ].classList.add( "netgis-hide" );
-		pointsItems[ 4 ].classList.add( "netgis-hide" );
-		linesItems[ 3 ].classList.add( "netgis-hide" );
-		linesItems[ 4 ].classList.add( "netgis-hide" );
-	}
-};
\ No newline at end of file
diff --git a/templates/map/client/libs/netgis/Util.js b/templates/map/client/libs/netgis/Util.js
deleted file mode 100644
index 72003bc7..00000000
--- a/templates/map/client/libs/netgis/Util.js
+++ /dev/null
@@ -1,217 +0,0 @@
-var netgis = netgis || {};
-
-/**
- * General purpose pure static utility functions.
- */
-netgis.util =
-(
-	function ()
-	{
-		"use strict";
-		
-		// Methods
-		var isDefined = function( v )
-		{
-			return ( typeof v !== "undefined" );
-		};
-		
-		var isString = function( v )
-		{
-			return ( typeof v === "string" || v instanceof String );
-		};
-		
-		/**
-		 * Replace all string occurences.
-		 * @param {String} str
-		 * @param {String} find
-		 * @param {String} newstr
-		 * @returns {String}
-		 */
-		var replace = function( str, find, newstr )
-		{
-			return str.replace( new RegExp( find, "g" ), newstr );
-		};
-		
-		var foreach = function( obj, fn )
-		{
-			for ( var k in obj )
-			{
-				if ( obj.hasOwnProperty( k ) )
-				{
-					fn( k, obj[ k ] );
-				}
-			}
-		};
-		
-		/**
-		 * Replace template strings in html string.
-		 * @param {type} html String with "{key}" placeholders.
-		 * @param {type} data Object of key value pairs to insert.
-		 * @returns {String} The modified html string.
-		 */
-		var template = function( html, data )
-		{
-			// Get Template: $( "#template-" + name ).text();
-			
-			foreach
-			(
-				data,
-				function( key, value )
-				{
-					html = html.replace( new RegExp( "{" + key + "}", "g" ), value );
-				}
-			);
-	
-			return html;
-		};
-		
-		/**
-		 * Create HTML element from string.
-		 * @param {String} html
-		 * @returns {Element}
-		 */
-		var create = function( html )
-		{
-			var temp = document.createElement( "tbody" );
-			temp.innerHTML = html;
-			
-			return temp.children[ 0 ];
-		};
-		
-		/**
-		 * Replace new line characters with HTML line breaks.
-		 * @param {String} str
-		 * @returns {String}
-		 */
-		var newlines = function( str )
-		{
-			return str.replace( new RegExp( "\n", "g" ), "<br />" );
-		};
-		
-		/**
-		 * Calculate the byte size of an object.
-		 * @param {Object} json
-		 * @returns {Object} Object with size info ( bytes, kilobytes, megabytes )
-		 */
-		var size = function( json )
-		{
-			var bytes = new TextEncoder().encode( JSON.stringify( json ) ).length;
-			var kilobytes = bytes / 1024;
-			var megabytes = kilobytes / 1024;
-			
-			return { bytes: bytes, kilobytes: kilobytes, megabytes: megabytes };
-		};
-		
-		/**
-		 * Send async GET request.
-		 * @param {String} url
-		 * @param {function} callback
-		 */
-		var request = function( url, callback )
-		{
-			var request = new XMLHttpRequest();
-			request.onload = function() { callback( this.responseText ); };
-			request.open( "GET", url, true );
-			request.send();
-		};
-		
-		/**
-		 * Pad string with leading zeros.
-		 * @param {String} s The string to pad.
-		 * @param {Integer} n Minimum number of digits.
-		 * @returns {String} The padded string.
-		 */
-		var padstr = function( s, n )
-		{
-			var o = s.toString();
-			while ( o.length < n ) o = "0" + o;
-			
-			return o;
-		};
-		
-		/**
-		 * Merge object properties.
-		 * @param {Object} target Merged object properties will be written to this.
-		 * @param {Object} other The object to append to the target object.
-		 * @returns {Object} The modified target object.
-		 */
-		var merge = function( target, other )
-		{
-			return Object.assign( target, other );
-		};
-		
-		/**
-		 * @returns {String} Formatted Date Time String (German Locale)
-		 */
-		var getTimeStamp = function()
-		{
-			var date = new Date();
-			
-			var timestamp = date.getDate() + "." + ( date.getMonth() + 1 ) + "." + date.getFullYear();
-			timestamp += " " + date.getHours() + ":" + date.getMinutes();
-			
-			return timestamp;
-		};
-		
-		/*
-		 * @param {Number} area Raw Area in Square Meters
-		 * @param {Boolean} decimals Output Rounded Decimals
-		 * @returns {String} Formatted Area String (Square Meters/Square Kilometers)
-		 */
-		var formatArea = function( area, decimals )
-		{
-			var output;
-			
-			// Normal / Large Value
-			var large = ( area > 100000 );
-			
-			// Round Value
-			var i = 0;
-			
-			if ( large )
-			{
-				if ( decimals )
-					i = Math.round( area / 1000000 * 1000 ) / 1000;
-				else
-					i = Math.round( area / 1000000 );
-			}
-			else
-			{
-				if ( decimals )
-					i = Math.round( area * 100 ) / 100;
-				else
-					i = Math.round( area );
-			}
-			
-			if ( i === 0 ) large = false;
-			
-			// Build String
-			i = i.toLocaleString("de-DE")
-			output = i + ( large ? " km²" : " m²" );
-			
-			//NOTE: HTML Superscript / Unicode (&sup2; etc.) not supported in OL Labels
-			
-			return output;
-		};
-
-		// Public Interface
-		var iface =
-		{
-			isDefined: isDefined,
-			isString: isString,
-			replace: replace,
-			foreach: foreach,
-			template: template,
-			newlines: newlines,
-			create: create,
-			size: size,
-			request: request,
-			padstr: padstr,
-			merge: merge,
-			getTimeStamp: getTimeStamp,
-			formatArea: formatArea
-		};
-
-		return iface;
-	}
-)();
\ No newline at end of file
diff --git a/templates/map/client/netgis.min.css b/templates/map/client/netgis.min.css
index a7602828..a110aeec 100644
--- a/templates/map/client/netgis.min.css
+++ b/templates/map/client/netgis.min.css
@@ -1 +1 @@
-.netgis-attribution{position:absolute;left:0;bottom:0;padding:1mm;background:rgba(255,255,255,0.5);font-size:.8em!important;z-index:100}.netgis-client{position:absolute;width:100%;height:100%;overflow:hidden;background:#aaa}.netgis-client *{box-sizing:border-box}.netgis-client .netgis-loader{position:absolute;width:100%;height:100%;z-index:9999;text-align:center;font-size:12mm}.netgis-client .netgis-hide{display:none}.netgis-client .netgis-loader i{position:absolute;top:50%;transform:translateY(-50%);animation:netgis-spin 2s linear infinite}@keyframes netgis-spin{0%{transform:rotate(0deg)}to{transform:rotate(360deg)}}.netgis-controls{position:absolute;width:12mm;left:0;bottom:8mm;z-index:100}.netgis-controls button{font-size:6mm!important;width:100%;height:12mm;padding:0;border:none;background:none;cursor:pointer;color:white;text-shadow:-0.5mm 0 .3mm #000,.5mm 0 .3mm #000,0 -0.5mm .3mm #000,0 .5mm .3mm #000,0 1mm 3mm rgba(0,0,0,0.7)}.netgis-controls button:hover{text-shadow:-0.5mm 0 .3mm #a7233f,.5mm 0 .3mm #a7233f,0 -0.5mm .3mm #a7233f,0 .5mm .3mm #a7233f,0 1mm 3mm rgba(0,0,0,0.7)}.netgis-layer-list{position:absolute;right:0;width:100%;max-width:100mm;top:12mm;bottom:0;overflow:auto;z-index:200;-webkit-transform:none;transform:none;transition:transform 150ms ease}.netgis-layer-list.netgis-hide{display:initial;-webkit-transform:translateX(110%);transform:translateX(110%);transition:transform 150ms ease;will-change:transform}.netgis-layer-list ul{list-style-type:none}.netgis-layer-list>ul{display:block;position:relative;width:100%;margin:0;padding:0}.netgis-folder{position:relative;overflow:hidden;list-style:none;padding:0;margin:0;min-height:12mm;width:100%;white-space:nowrap}.netgis-folder label{cursor:pointer}.netgis-folder input[type=checkbox]{cursor:pointer}.netgis-folder>button{display:inline-block;width:100%;padding:0;padding-right:16mm;margin:0;line-height:12mm;text-align:left}.netgis-folder>ul{display:none;padding-left:8mm}.netgis-folder.netgis-active>ul{display:block}.netgis-folder-item{height:12mm;line-height:12mm}.netgis-folder-item>label{display:block;padding-right:4mm}.netgis-layer-list .netgis-icon{display:inline-block;width:12mm;line-height:12mm;text-align:center}.netgis-layer-list i{margin-right:4mm}.netgis-folder i{color:#eab000}.netgis-folder-item i{color:#bbb}.netgis-folder .netgis-partial{opacity:.5}.netgis-layer-tools{padding:4mm;padding-top:0;text-align:center}.netgis-layer-tools hr{margin:4mm 0;color:#eee;border-color:#eee}.netgis-layer-tools button{padding:2mm 4mm}.netgis-layer-tools button i{margin-right:1mm}.netgis-map{position:absolute;left:0;right:0;top:12mm;bottom:0;background:#f2efe9}.netgis-drop-target{position:absolute;left:0;right:0;top:0;bottom:0;line-height:40mm;text-align:center;z-index:1;pointer-events:none;background:rgba(0,0,0,0.5);color:#fff}.netgis-drop-target.netgis-hide{display:none}.netgis-map{cursor:default}.netgis-map .netgis-toolbar,.netgis-map .netgis-dialog{cursor:auto}.netgis-map.netgis-mode-view,.netgis-map.netgis-mode-search-place{cursor:default;cursor:grab;cursor:-moz-grab;cursor:-webkit-grab}.netgis-map.netgis-mode-panning{cursor:move;cursor:all-scroll;cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}.netgis-map.netgis-mode-zooming-in{cursor:zoom-in}.netgis-map.netgis-mode-zooming-out{cursor:zoom-out}.netgis-map.netgis-mode-draw-points,.netgis-map.netgis-mode-draw-lines,.netgis-map.netgis-mode-draw-polygons,.netgis-map.netgis-mode-cut-feature-draw,.netgis-map.netgis-mode-modify-features{cursor:pointer;cursor:crosshair}.netgis-map.netgis-mode-delete-features,.netgis-map.netgis-mode-cut-feature-begin,.netgis-map.netgis-mode-buffer-feature-begin{cursor:pointer}.netgis-map.netgis-mode-buffer-feature-edit{cursor:default}.netgis-menu{position:absolute;left:0;right:0;top:0;height:12mm;line-height:12mm;white-space:nowrap;font-size:0;z-index:1000;background:lightsalmon}.netgis-menu>div{height:12mm;white-space:nowrap}.netgis-menu>div>*{display:inline-block;height:100%;margin:0;font-size:4mm}.netgis-menu .netgis-right{float:right;padding-right:0;padding-left:4mm}.netgis-menu span{padding:0 4mm 0 0}.netgis-menu button i{font-size:5mm;width:12mm;line-height:12mm;text-align:center}.netgis-dropdown{position:relative;padding:0}.netgis-dropdown .netgis-dropdown-content{display:none;position:absolute;min-width:100%;padding:0;margin:0;margin-top:-1px;z-index:1;font-size:4mm;list-style-type:none}.netgis-dropdown:hover .netgis-dropdown-content{display:block}.netgis-dropdown .netgis-dropdown-content i{font-size:4mm;color:#bbb}.netgis-dropdown button{width:100%;padding:0 4mm 0 0;white-space:nowrap;text-align:left}.netgis-modal{display:none;position:absolute;width:100%;height:100%;top:0;left:0;padding:6mm;z-index:5000;background:rgba(0,0,0,0.6)}.netgis-modal.netgis-show{display:block}.netgis-modal .netgis-dialog{display:none;max-width:160mm;max-height:160mm;margin:auto;border-radius:1mm;border:1mm solid #a7233f;overflow:hidden;overflow-y:auto;cursor:default}.netgis-modal .netgis-dialog.netgis-show{display:block}.netgis-modal header{width:100%;height:12mm;line-height:12mm;text-align:center}.netgis-modal header button{position:relative;width:100%;min-height:12mm}.netgis-modal header button span{display:block;position:absolute;right:0;top:0;line-height:12mm;padding:0 4mm;text-align:center}.netgis-modal-content{padding:6mm;overflow:auto}.netgis-modal-content>table{width:100%;border:none;border-spacing:0}.netgis-modal-content>table td,.netgis-modal-content>table th{width:50%;overflow:hidden;vertical-align:top;text-align:left}.netgis-modal-content .netgis-padding{padding:4mm}.netgis-modal-content .netgis-space{height:6mm}.netgis-modal-content button,.netgis-modal-content label{width:100%;min-height:12mm}.netgis-modal-content button i{margin-right:4mm}.netgis-modal-content button[disabled]{opacity:.5;cursor:not-allowed}.netgis-modal-content input,.netgis-modal-content select{width:100%}.netgis-modal-content input[type=file]{cursor:pointer}.netgis-modal-content ul{margin:0;padding:0;padding-left:4mm;list-style-type:square}.netgis-modal-content li:not(:last-child){margin-bottom:4mm}.netgis-modal h3{margin:0}.netgis-search-parcel{position:absolute;right:0;width:100%;max-width:100mm;top:12mm;bottom:0;overflow:auto;z-index:200;padding:4mm;-webkit-transform:none;transform:none;transition:transform 150ms ease}.netgis-search-parcel.netgis-hide{display:initial;-webkit-transform:translateX(110%);transform:translateX(110%);transition:transform 150ms ease;will-change:transform}.netgis-search-parcel h3{margin:0;margin-bottom:4mm}.netgis-search-parcel label{display:block;margin:3mm 0;margin-bottom:0;cursor:pointer}.netgis-search-parcel input{width:100%;height:12mm;margin:3mm 0;padding:0 3mm}.netgis-search-parcel .netgis-loader{width:6mm;height:6mm;top:8mm;right:6mm;font-size:6mm}.netgis-search-parcel ul{margin:0;padding:0;list-style-type:none}.netgis-search-parcel li button{text-align:left}.netgis-search-parcel button{display:block;width:100%;height:12mm;padding:0 3mm;margin:0}.netgis-search-parcel .netgis-table-wrapper{width:100%;max-height:120mm;margin-top:4mm;overflow:auto}.netgis-search-parcel table{border-collapse:collapse;white-space:nowrap}.netgis-search-parcel tr{height:12mm}.netgis-search-parcel th{text-align:left;padding:0 3mm}.netgis-search-parcel td{text-align:left;padding:0 3mm;cursor:pointer}.netgis-search-parcel td:first-child{padding:0}.netgis-search-parcel table button{display:inline-block;width:12mm;height:12mm}.netgis-search-parcel p{margin:4mm 3mm;font-style:italic}.netgis-client,.netgis-client button{font-family:Verdana,sans-serif;font-size:4mm}.netgis-primary{background-color:#a7233f!important;color:white!important}.netgis-hover-primary:hover{background-color:#c82a4b!important;color:white!important}.netgis-light,.netgis-hover-light:hover{background-color:#f4f4f4!important}.netgis-text-primary{color:#a7233f!important}.netgis-hover-text-primary:hover{color:#c82a4b!important}.netgis-dialog{background:#fff;color:#000}.netgis-dropdown:hover>button{background-color:#c82a4b!important}.netgis-shadow{box-shadow:0 .5mm 1mm 0 rgba(0,0,0,0.2),0 1mm 2.5mm 0 rgba(0,0,0,0.1)!important}.netgis-shadow-large{box-shadow:0 1mm 2mm 0 rgba(0,0,0,0.3),0 2mm 5mm 0 rgba(0,0,0,0.15)!important}.netgis-text-shadow{text-shadow:0 0 1mm rgba(0,0,0,1.0)}.netgis-client button{border:none;background:none;cursor:pointer}.netgis-clip-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.netgis-toolbars{position:absolute;left:0;right:0;top:0}.netgis-toolbar{position:absolute;left:0;right:0;top:12mm;min-height:12mm;line-height:12mm;font-size:0;white-space:nowrap;z-index:1;-webkit-transform:none;transform:none;transition:transform 150ms ease}.netgis-toolbar.netgis-hide{-webkit-transform:translateY(-24mm);transform:translateY(-24mm);transition:transform 150ms ease;will-change:transform}.netgis-toolbar>div{height:12mm;white-space:nowrap}.netgis-toolbar>div>*{display:inline-block;font-size:4mm}.netgis-toolbar button{padding:0 4mm 0 0}.netgis-toolbar>div>button{line-height:12mm}.netgis-toolbar button i{width:12mm}.netgis-toolbar button:last-child{padding-right:0}.netgis-toolbar button:last-child span{margin-right:4mm}.netgis-toolbar label{display:inline-block;height:12mm;padding:0 4mm;cursor:pointer}.netgis-toolbar input[type=checkbox]{margin-right:2mm}.netgis-toolbar input[type=number]{margin-left:2mm;width:20mm}.netgis-toolbar input[type=text]{width:60mm}.netgis-toolbar .netgis-search-list{position:absolute;min-width:68mm;padding:0;margin:0;margin-left:-4mm;z-index:1;list-style-type:none;overflow:hidden;box-shadow:0 .5mm .5mm 0 rgba(0,0,0,0.2)!important}.netgis-toolbar .netgis-search-list.netgis-hide{display:none}.netgis-toolbar .netgis-search-list li{width:100%;padding:0;margin:0}.netgis-toolbar .netgis-search-list li button{width:100%;height:12mm;padding:0 4mm;white-space:nowrap;text-align:left}
\ No newline at end of file
+.netgis-attribution{position:absolute;right:0;bottom:0;padding:1mm;background:rgba(255,255,255,0.5);font-size:2.5mm;z-index:100}.netgis-client{position:absolute;width:100%;height:100%;overflow:hidden;background:#aaa}.netgis-client *{box-sizing:border-box}.netgis-client .netgis-loader{position:absolute;width:100%;height:100%;z-index:999999;text-align:center;font-size:12mm}.netgis-client .netgis-hide{display:none}.netgis-client .netgis-loader *{position:absolute;width:100%;left:0;top:50%;transform:translateY(-50%);animation:netgis-spin 2s linear infinite}@keyframes netgis-spin{0%{transform:rotate(0deg)}to{transform:rotate(360deg)}}.netgis-controls{position:absolute;width:12mm;right:4mm;bottom:8mm;overflow:hidden;z-index:100}.netgis-controls button{font-size:5mm!important;color:inherit;width:100%;height:12mm;padding:0;border:none;background-color:inherit;cursor:pointer}.netgis-layer-list{position:absolute;right:0;width:100%;max-width:100mm;top:12mm;bottom:0;overflow:auto;z-index:200;-webkit-transform:none;transform:none;transition:transform 150ms ease}.netgis-layer-list.netgis-hide{display:initial;-webkit-transform:translateX(110%);transform:translateX(110%);transition:transform 150ms ease;will-change:transform}.netgis-layer-list ul{list-style-type:none}.netgis-layer-list>ul{display:block;position:relative;width:100%;margin:0;padding:0}.netgis-folder{position:relative;overflow:hidden;list-style:none;padding:0;margin:0;min-height:12mm;width:100%;white-space:nowrap}.netgis-folder label{cursor:pointer}.netgis-folder input[type=checkbox]{cursor:pointer}.netgis-folder>button{display:inline-block;width:100%;padding:0;padding-right:16mm;margin:0;line-height:12mm;text-align:left}.netgis-folder>ul{display:none;padding-left:8mm}.netgis-folder.netgis-active>ul{display:block}.netgis-folder-item{height:12mm;line-height:12mm}.netgis-folder-item>label{display:block;padding-right:4mm}.netgis-layer-list .netgis-icon{display:inline-block;width:12mm;line-height:12mm;text-align:center}.netgis-layer-list i{margin-right:4mm}.netgis-folder i{color:#eab000}.netgis-folder-item i{color:#bbb}.netgis-folder .netgis-partial{opacity:.5}.netgis-layer-tools{padding:4mm;padding-top:0;text-align:center}.netgis-layer-tools hr{margin:4mm 0;color:#eee;border-color:#eee}.netgis-layer-tools button{padding:2mm 4mm}.netgis-layer-tools button i{margin-right:1mm}.netgis-map{position:absolute;left:0;right:0;top:12mm;bottom:0;background:#f2efe9}.netgis-drop-target{position:absolute;left:0;right:0;top:0;bottom:0;line-height:40mm;text-align:center;z-index:1;pointer-events:none;background:rgba(0,0,0,0.5);color:#fff}.netgis-drop-target.netgis-hide{display:none}.netgis-map{cursor:grab}.netgis-map:active:hover:not(.netgis-clickable){cursor:grabbing}.netgis-map.netgis-cursor-draw,.netgis-map.netgis-cursor-draw:active:hover{cursor:crosshair}.netgis-map .ol-scale-bar{right:24mm;bottom:10mm;left:auto}.netgis-menu{position:absolute;left:0;right:0;top:0;height:12mm;line-height:12mm;white-space:nowrap;font-size:0;z-index:10000;background:lightsalmon}.netgis-menu>div{height:12mm;white-space:nowrap}.netgis-menu>div>*{display:inline-block;height:100%;margin:0;font-size:4mm}.netgis-menu .netgis-right{float:right}.netgis-menu span{padding:0 4mm 0 0}.netgis-menu button{position:relative}.netgis-menu button i{display:inline-block;font-size:5mm;width:12mm;line-height:12mm;text-align:center}.netgis-menu button span{display:inline-block;position:relative;top:-2px;line-height:12mm;padding:0;margin-right:4mm}.netgis-dropdown{position:relative;padding:0}.netgis-dropdown .netgis-dropdown-content{display:none;position:absolute;min-width:100%;padding:0;margin:0;margin-top:-1px;z-index:1;font-size:4mm;list-style-type:none}.netgis-dropdown:hover .netgis-dropdown-content{display:block}.netgis-dropdown .netgis-dropdown-content i{font-size:4mm;color:#bbb}.netgis-dropdown button{width:100%;padding:0 4mm 0 0;white-space:nowrap;text-align:left}.netgis-modal{display:none;position:absolute;width:100%;height:100%;top:0;left:0;padding:6mm;z-index:110000;background:rgba(0,0,0,0.6)}.netgis-modal.netgis-show{display:block}.netgis-modal>*{position:relative;width:100%;height:100%;max-width:150mm;margin:0 auto}.netgis-modal .netgis-button{display:block;width:100%;min-height:12mm;text-align:left}.netgis-panel{position:absolute;left:0;width:80mm;top:12mm;bottom:0;z-index:5000;-webkit-transform:translateX(-110%);transform:translateX(-110%);transition:transform 150ms ease;will-change:transform}.netgis-panel.netgis-show{-webkit-transform:none;transform:none}.netgis-panel h2{margin:0 4mm;font-size:1em}.netgis-panel .netgis-button,.netgis-panel label{display:block;width:100%;min-height:12mm;text-align:left}.netgis-panel input[type=text]{margin-top:3mm}.netgis-panel .netgis-half{display:inline-block;width:50%!important;padding-right:1mm}.netgis-panel .netgis-half+.netgis-half{padding-left:1mm;padding-right:0}.netgis-panel .netgis-anim-bottom{transition:transform 150ms ease;will-change:transform;-webkit-transform:none;transform:none}.netgis-panel .netgis-anim-bottom.netgis-hide{display:initial;-webkit-transform:translateY(110%);transform:translateY(110%)}.netgis-panel .netgis-resize-bottom{max-height:80%}.netgis-search-parcel{position:absolute;top:12mm;bottom:0;width:100%;overflow:hidden;padding:4mm}.netgis-search-parcel section{position:absolute;left:0;right:0;overflow:auto}.netgis-search-parcel section:first-of-type{top:0;bottom:0;padding:6mm}.netgis-search-parcel section:last-of-type{top:50%;bottom:0}.netgis-search-parcel h3{margin:0;margin-bottom:4mm}.netgis-search-parcel label{display:block;margin:3mm 0;margin-bottom:0;cursor:pointer}.netgis-search-parcel label:first-child{margin-top:0}.netgis-search-parcel label span:first-child{display:block}.netgis-search-parcel input{width:100%;height:12mm;margin:3mm 0;padding:0 3mm}.netgis-search-parcel .netgis-loader{width:6mm;height:6mm;top:8mm;right:6mm;font-size:6mm}.netgis-search-parcel ul{margin:0;padding:0;list-style-type:none}.netgis-search-parcel li button{text-align:left}.netgis-search-parcel button{display:block;width:100%;height:12mm;padding:0 3mm;margin:0}.netgis-search-parcel .netgis-table-wrapper{width:100%;margin-top:4mm;overflow:auto}.netgis-search-parcel table{min-width:100%;border-collapse:collapse;white-space:nowrap}.netgis-search-parcel table thead{position:-webkit-sticky;position:sticky;top:0;z-index:10}.netgis-search-parcel tr{height:12mm}.netgis-search-parcel th{text-align:left;padding:0 3mm}.netgis-search-parcel td{text-align:left;padding:0 3mm;cursor:pointer}.netgis-search-parcel td:first-child{padding:0}.netgis-search-parcel table button{display:inline-block;width:12mm;height:12mm;background:none}.netgis-search-parcel p{margin:4mm 3mm;font-style:italic}.netgis-search-place{position:absolute;left:4mm;right:4mm;max-width:90mm;min-height:12mm;top:16mm;margin-left:auto;z-index:4000;-webkit-transform:translateY(-300%);transform:translateY(-300%);transition:transform 150ms ease;will-change:transform}.netgis-search-place.netgis-show{-webkit-transform:none;transform:none}.netgis-search-place>input{position:relative;width:100%;height:12mm!important;padding:0 3mm!important;z-index:1}.netgis-search-place>button{position:absolute;width:12mm;height:12mm;right:0;top:0;background:none;z-index:2}.netgis-search-place>ul{max-height:60mm;overflow-y:auto;margin:0;padding:0;list-style-type:none}.netgis-search-place li .netgis-button{width:100%;height:12mm;padding:0 3mm;text-align:left}.netgis-tabs{position:relative;background:lightblue}.netgis-tabs>.netgis-header{position:absolute;width:100%;height:12mm;left:0;top:0;white-space:nowrap;overflow-x:auto;overflow-y:hidden}.netgis-tabs>.netgis-content{position:absolute;width:100%;left:0;top:12mm;bottom:0}.netgis-tabs.netgis-scroll>.netgis-header{height:17mm}.netgis-tabs.netgis-scroll>.netgis-content{top:17mm}.netgis-tabs>.netgis-header .netgis-button{display:inline-block;width:auto}.netgis-tabs>.netgis-content section{position:absolute;width:100%;height:100%;left:0;top:0;padding:12mm;overflow:auto}.netgis-tabs>.netgis-content section.netgis-hide{display:none}.netgis-import .netgis-tabs{position:absolute;width:100%;left:0;top:12mm;bottom:0}.netgis-import .netgis-tabs .netgis-header .netgis-button{width:50%;text-align:center}.netgis-client,.netgis-client button{font-family:Verdana,sans-serif;font-size:4mm}.netgis-color-a{background-color:#900;color:#fff}.netgis-color-b{background-color:#430433;color:#fff}.netgis-color-c{background-color:#470f1b;color:#fff}.netgis-color-d{background-color:#f6f5f5;color:#000}.netgis-color-e{background-color:#fff;color:#000}.netgis-hover-a:hover{background-color:#900;color:#fff}.netgis-hover-b:hover{background-color:#430433;color:#fff}.netgis-hover-c:hover{background-color:#470f1b;color:#fff}.netgis-hover-d:hover{background-color:#f6f5f5;color:#000}.netgis-hover-e:hover{background-color:#fff;color:#000}.netgis-text-a{color:#900}.netgis-text-b{color:#430433}.netgis-text-c{color:#470f1b}.netgis-text-d{color:#f6f5f5}.netgis-text-e{color:#fff}.netgis-hover-text-a:hover{color:#900}.netgis-hover-text-b:hover{color:#430433}.netgis-hover-text-c:hover{color:#470f1b}.netgis-hover-text-d:hover{color:#f6f5f5}.netgis-hover-text-e:hover{color:#fff}.netgis-bar-a{box-shadow:0 1.5mm 0 0 #900 inset}.netgis-primary{background-color:#a7233f!important;color:white!important}.netgis-hover-primary:hover{background-color:#c82a4b!important;color:white!important}.netgis-light,.netgis-hover-light:hover{background-color:#f4f4f4!important}.netgis-text-primary{color:#a7233f!important}.netgis-hover-text-primary:hover{color:#c82a4b!important}.netgis-dialog{background:#fff;color:#000}.netgis-dropdown:hover>button{background-color:#c82a4b!important}.netgis-shadow{box-shadow:0 .5mm 1mm 0 rgba(0,0,0,0.2),0 1mm 2.5mm 0 rgba(0,0,0,0.1)!important}.netgis-shadow-large{box-shadow:0 1mm 2mm 0 rgba(0,0,0,0.3),0 2mm 5mm 0 rgba(0,0,0,0.15)!important}.netgis-text-shadow{text-shadow:0 0 1mm rgba(0,0,0,1.0)}.netgis-round{border-radius:2mm}.netgis-client a{color:inherit}.netgis-button{position:relative;padding:0 4mm;font:inherit;text-decoration:none;outline:none;border:none;cursor:pointer}.netgis-button .netgis-icon{display:inline-block;position:absolute;width:12mm;left:0;top:0;bottom:0;line-height:12mm;text-align:center;font-size:1.2em}.netgis-button.netgis-center .netgis-icon:first-child{position:static}.netgis-button .netgis-icon:last-child{left:auto;right:0}.netgis-button:not(.netgis-center) .netgis-icon+*:not(.netgis-icon){margin-left:8mm}.netgis-client button{border:none;cursor:pointer}.netgis-resize-right{resize:horizontal;overflow-x:auto;min-width:40mm;max-width:100%}.netgis-resize-bottom{resize:vertical;overflow-y:auto;min-height:24mm;max-height:100%}.netgis-noselect{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.netgis-clickable{cursor:pointer}.netgis-form h3{font-size:1em;margin-top:0;margin-bottom:6mm}.netgis-form ul{padding:0;padding-left:12mm;margin-top:0;margin-bottom:6mm;list-style-type:square}.netgis-form li{padding-left:2mm}.netgis-form label{display:block;margin-bottom:6mm;font-weight:bold;cursor:pointer}.netgis-form input,.netgis-form select{display:block;width:100%;margin-top:6mm;padding:2mm}.netgis-form input[type=file]{padding:6mm;cursor:pointer}.netgis-form input[type=checkbox]{display:inline-block;width:12mm;margin:0}.netgis-form button{display:block;width:100%;height:12mm}.netgis-clip-text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.netgis-bold{font-weight:bold}.netgis-center{text-align:center!important}.netgis-toolbars{position:absolute;left:0;right:0;top:0}.netgis-toolbar{position:absolute;left:0;right:0;top:12mm;min-height:12mm;line-height:12mm;font-size:0;white-space:nowrap;z-index:1;-webkit-transform:none;transform:none;transition:transform 150ms ease}.netgis-toolbar.netgis-hide{-webkit-transform:translateY(-24mm);transform:translateY(-24mm);transition:transform 150ms ease;will-change:transform}.netgis-toolbar>div{height:12mm;white-space:nowrap}.netgis-toolbar>div>*{display:inline-block;font-size:4mm}.netgis-toolbar button{padding:0 4mm 0 0}.netgis-toolbar>div>button{line-height:12mm}.netgis-toolbar button i{width:12mm}.netgis-toolbar button:last-child{padding-right:0}.netgis-toolbar button:last-child span{margin-right:4mm}.netgis-toolbar label{display:inline-block;height:12mm;padding:0 4mm;cursor:pointer}.netgis-toolbar input[type=checkbox]{margin-right:2mm}.netgis-toolbar input[type=number]{margin-left:2mm;width:20mm}.netgis-toolbar input[type=text]{width:60mm}.netgis-toolbar .netgis-search-list{position:absolute;min-width:68mm;padding:0;margin:0;margin-left:-4mm;z-index:1;list-style-type:none;overflow:hidden;box-shadow:0 .5mm .5mm 0 rgba(0,0,0,0.2)!important}.netgis-toolbar .netgis-search-list.netgis-hide{display:none}.netgis-toolbar .netgis-search-list li{width:100%;padding:0;margin:0}.netgis-toolbar .netgis-search-list li button{width:100%;height:12mm;padding:0 4mm;white-space:nowrap;text-align:left}.netgis-toolbox{position:absolute;top:12mm;bottom:0;width:100%;overflow:hidden}.netgis-toolbox section{position:absolute;left:0;right:0;overflow:auto}.netgis-toolbox section:first-of-type{top:0;bottom:0}.netgis-toolbox section:last-of-type{top:50%;bottom:0}.netgis-toolbox section:last-of-type>div{position:absolute;width:100%;top:12mm;bottom:0;overflow:auto}.netgis-toolbox button:hover i{color:inherit!important}.netgis-toolbox label{display:block;width:100%;min-height:12mm;text-align:left;position:relative;padding:4mm;cursor:pointer}.netgis-toolbox input[type=checkbox]{width:4mm;height:4mm;margin:0 4mm 0 0}.netgis-toolbox input[type=checkbox]:last-child{float:right;margin-right:0}.netgis-toolbox input[type=text]{width:100%;height:10mm;padding:0 2mm;margin-top:3mm}.netgis-toolbox input[type=number]{position:absolute;right:2mm;width:24mm;top:2.5mm;height:8mm;padding:0 1mm}.netgis-tree{display:block;line-height:12mm;padding:0;margin:0;list-style-type:none}.netgis-tree ul{padding:0;margin:0;padding-left:9mm;list-style-type:none}.netgis-tree .netgis-folder{position:relative}.netgis-tree summary{display:block}.netgis-tree summary label{text-align:center}.netgis-tree .netgis-folder .netgis-icon{width:6mm;left:12mm;color:#eab000}.netgis-tree .netgis-folder .netgis-partial{opacity:.5}.netgis-tree details[open]>summary>.netgis-hide-open,.netgis-tree details>summary>.netgis-show-open{display:none}.netgis-tree details[open]>summary>.netgis-show-open{display:initial}.netgis-tree .netgis-folder>details>summary>label{position:absolute;width:12mm;top:0;left:0}.netgis-tree .netgis-folder>details>summary>span{margin-left:17mm!important}.netgis-tree .netgis-item label{padding:0 4mm;padding-left:3mm}.netgis-tree .netgis-item label input{margin-right:4mm}
\ No newline at end of file
diff --git a/templates/map/client/netgis.min.js b/templates/map/client/netgis.min.js
index 52f33636..d90779a9 100644
--- a/templates/map/client/netgis.min.js
+++ b/templates/map/client/netgis.min.js
@@ -1,229 +1,271 @@
-var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)};
-$jscomp.getGlobal=function(a){a=["object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global,a];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
-$jscomp.polyfill=function(a,b,c,d){if(b){c=$jscomp.global;a=a.split(".");for(d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})}};$jscomp.polyfill("Number.parseFloat",function(a){return a||parseFloat},"es6","es3");
+var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);
+$jscomp.polyfill=function(a,b,c,d){if(b){c=$jscomp.global;a=a.split(".");for(d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})}};$jscomp.polyfill("Number.parseFloat",function(a){return a||parseFloat},"es6","es3");$jscomp.polyfill("Number.parseInt",function(a){return a||parseInt},"es6","es3");
 $jscomp.polyfill("Array.prototype.fill",function(a){return a?a:function(a,c,d){var b=this.length||0;0>c&&(c=Math.max(0,b+c));if(null==d||d>b)d=b;d=Number(d);0>d&&(d=Math.max(0,b+d));for(c=Number(c||0);c<d;c++)this[c]=a;return this}},"es6","es3");$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}};$jscomp.arrayIterator=function(a){return{next:$jscomp.arrayIteratorImpl(a)}};$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
 $jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.SymbolClass=function(a,b){this.$jscomp$symbol$id_=a;$jscomp.defineProperty(this,"description",{configurable:!0,writable:!0,value:b})};$jscomp.SymbolClass.prototype.toString=function(){return this.$jscomp$symbol$id_};
 $jscomp.Symbol=function(){function a(c){if(this instanceof a)throw new TypeError("Symbol is not a constructor");return new $jscomp.SymbolClass($jscomp.SYMBOL_PREFIX+(c||"")+"_"+b++,c)}var b=0;return a}();
 $jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("Symbol.iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.iteratorPrototype($jscomp.arrayIteratorImpl(this))}});$jscomp.initSymbolIterator=function(){}};
 $jscomp.initSymbolAsyncIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.asyncIterator;a||(a=$jscomp.global.Symbol.asyncIterator=$jscomp.global.Symbol("Symbol.asyncIterator"));$jscomp.initSymbolAsyncIterator=function(){}};$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};
 $jscomp.iteratorFromArray=function(a,b){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var c=0,d={next:function(){if(c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d.next=function(){return{done:!0,value:void 0}};return d.next()}};d[Symbol.iterator]=function(){return d};return d};$jscomp.polyfill("Array.prototype.values",function(a){return a?a:function(){return $jscomp.iteratorFromArray(this,function(a,c){return c})}},"es8","es3");
-$jscomp.polyfill("Number.parseInt",function(a){return a||parseInt},"es6","es3");$jscomp.owns=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};$jscomp.assign="function"==typeof Object.assign?Object.assign:function(a,b){for(var c=1;c<arguments.length;c++){var d=arguments[c];if(d)for(var e in d)$jscomp.owns(d,e)&&(a[e]=d[e])}return a};$jscomp.polyfill("Object.assign",function(a){return a||$jscomp.assign},"es6","es3");var netgis=netgis||{};
+$jscomp.polyfill("Number.isNaN",function(a){return a?a:function(a){return"number"===typeof a&&isNaN(a)}},"es6","es3");$jscomp.owns=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};$jscomp.assign="function"==typeof Object.assign?Object.assign:function(a,b){for(var c=1;c<arguments.length;c++){var d=arguments[c];if(d)for(var e in d)$jscomp.owns(d,e)&&(a[e]=d[e])}return a};$jscomp.polyfill("Object.assign",function(a){return a||$jscomp.assign},"es6","es3");var netgis=netgis||{};
 netgis.Attribution=function(){this.layers=this.client=null;this.items=[]};
 netgis.Attribution.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-attribution netgis-text-primary";netgis.util.isDefined(this.client.config.map)&&netgis.util.isDefined(this.client.config.map.attribution)&&this.items.push(this.client.config.map.attribution);this.update();this.client.root.appendChild(this.root);this.client.on(netgis.Events.CONTEXT_UPDATE,this.onContextUpdate.bind(this));this.client.on(netgis.Events.LAYER_SHOW,this.onLayerShow.bind(this));
-this.client.on(netgis.Events.LAYER_HIDE,this.onLayerHide.bind(this))};netgis.Attribution.prototype.update=function(){this.root.innerHTML="&copy; "+this.items.join(", ")};netgis.Attribution.prototype.onContextUpdate=function(a){this.layers=[];for(var b=0;b<a.layers.length;b++){var c=a.layers[b];c.attribution&&0<c.attribution.length&&(this.layers[b]=c.attribution)}};
-netgis.Attribution.prototype.onLayerShow=function(a){if(a=this.layers[a.id]){for(var b=0;b<this.items.length;b++)if(this.items[b]===a)return;this.items.push(a);this.update()}};netgis.Attribution.prototype.onLayerHide=function(a){if(a=this.layers[a.id]){for(var b=0;b<this.items.length;b++)if(this.items[b]===a){this.items.splice(b,1);break}this.update()}};netgis=netgis||{};
-netgis.Client=function(a,b){this.build="20220826";this.debug=!1;netgis.util.isString(a)&&(a=document.getElementById(a));this.container=a;this.editable=!0;this.root=null;this.modules=[];this.callbacks={};this.config=this.createDefaultConfig();this.create();if(netgis.util.isDefined(b))if(netgis.util.isString(b)){var c=this;netgis.util.request(b,function(a){a=JSON.parse(a);netgis.util.merge(c.config,a);c.createModules();c.load();c.invoke(netgis.Events.CONTEXT_UPDATE,c.config);c.hideLoader()})}else netgis.util.merge(this.config,b),
-this.createModules(),this.load(),this.invoke(netgis.Events.CONTEXT_UPDATE,this.config),this.hideLoader();else this.createModules(),this.load(),this.invoke(netgis.Events.CONTEXT_UPDATE,this.config),this.hideLoader()};
+this.client.on(netgis.Events.LAYER_HIDE,this.onLayerHide.bind(this));this.client.on(netgis.Events.EDIT_FEATURES_CHANGE,this.onEditFeaturesChange.bind(this))};netgis.Attribution.prototype.update=function(){var a="&copy; "+this.items.join(", ");this.appendix&&(a+=", "+this.appendix);this.root.innerHTML=a};
+netgis.Attribution.prototype.onContextUpdate=function(a){this.layers=[];for(var b=0;b<a.layers.length;b++){var c=a.layers[b];c.attribution&&0<c.attribution.length&&(this.layers[c.id]=c.attribution)}for(b=0;b<a.layers.length;b++)if(c=a.layers[b],c.active)this.onLayerShow({id:c.id})};netgis.Attribution.prototype.onLayerShow=function(a){if(a=this.layers[a.id]){for(var b=0;b<this.items.length;b++)if(this.items[b]===a)return;this.items.push(a);this.update()}};
+netgis.Attribution.prototype.onLayerHide=function(a){if(a=this.layers[a.id]){for(var b=0;b<this.items.length;b++)if(this.items[b]===a){this.items.splice(b,1);break}this.update()}};netgis.Attribution.prototype.onEditFeaturesChange=function(a){for(var b=0;b<this.items.length;b++)if(-1<this.items[b].search("Zeichnungsfl\u00e4che: ")){this.items.splice(b,1);break}this.appendix=a.area&&0<a.area?"<b>Zeichnungsfl\u00e4che: "+netgis.util.formatArea(a.area,!0)+"</b>":null;this.update()};netgis=netgis||{};
+netgis.Client=function(a,b){this.build="20220826";this.debug=!1;netgis.util.isString(a)&&(a=document.getElementById(a));this.container=a;this.editable=!0;this.root=null;this.modules=[];this.callbacks={};this.config=this.createDefaultConfig();this.create();if(netgis.util.isDefined(b))if(netgis.util.isString(b)){var c=this;netgis.util.request(b,function(a){a=JSON.parse(a);netgis.util.merge(c.config,a);c.applyConfig(c.config)})}else netgis.util.merge(this.config,b),this.applyConfig(this.config);else this.applyConfig(this.config);
+this.hideLoader()};netgis.Client.Layers=Object.freeze({PARCEL_DISTRICTS:"parcel-districts",PARCEL_FIELDS:"parcel-fields",PARCEL_FEATURES:"parcel-features",EDIT_LAYER:"edit-layer",PREVIEW_LAYER:"preview-layer"});netgis.Client.prototype.applyConfig=function(a){this.createModules();this.load();this.invoke(netgis.Events.CONTEXT_UPDATE,a);this.initModules(a);this.initConfig(a);this.initOutput(a);this.initEvents();this.importLayers={};this.setMode(netgis.Modes.VIEW)};
+netgis.Client.prototype.initElements=function(){};
+netgis.Client.prototype.initModules=function(a){this.map=new netgis.MapOpenLayers(a);this.map.attach(this.root);this.controls=new netgis.Controls;this.controls.attach(this.root);this.layerPanel=new netgis.Panel("Inhalte");this.layerPanel.attach(this.root);this.layerTree=new netgis.Tree;this.layerTree.container.style.position="absolute";this.layerTree.container.style.width="100%";this.layerTree.container.style.top="12mm";this.layerTree.container.style.bottom="6mm";this.layerTree.container.style.overflow=
+"auto";this.layerTree.attach(this.layerPanel.container);this.toolboxPanel=new netgis.Panel("Werkzeuge");this.toolboxPanel.attach(this.root);this.toolbox=new netgis.Toolbox(a);this.toolbox.attach(this.toolboxPanel.container);this.searchPlace=new netgis.SearchPlace(a);this.searchPlace.attach(this.root);this.parcelPanel=new netgis.Panel("Flurst\u00fccks-Suche");this.parcelPanel.container.style.minWidth="92mm";this.parcelPanel.attach(this.root);this.searchParcel=new netgis.SearchParcel(a);this.searchParcel.attach(this.parcelPanel.container);
+this.importModal=new netgis.Modal("Ebene hinzuf\u00fcgen");this.importModal.container.classList.add("netgis-import");this.importModal.attach(this.root);this.importTabs=new netgis.Tabs(["Datei","Dienst"]);this.importTabs.attach(this.importModal.content);a=this.importTabs.getContentSection(0);a.classList.add("netgis-noselect");var b=document.createElement("div");b.innerHTML="<h3>Unterst\u00fctzte Koordinatensysteme:</h3><ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>";
+a.appendChild(b);b=document.createElement("label");b.innerHTML="Datei ausw\u00e4hlen/ablegen:";a.appendChild(b);var c=document.createElement("input");c.className="netgis-color-d";c.setAttribute("type","file");c.setAttribute("accept",".geojson,.gml,.gpkg,.shp.zip,.sqlite");b.appendChild(c);this.importFileInput=c;b=document.createElement("button");b.setAttribute("type","button");b.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";b.innerHTML="<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>";
+b.addEventListener("click",this.onImportFileClick.bind(this));a.appendChild(b);b=this.importTabs.getContentSection(1);b.classList.add("netgis-noselect");a=document.createElement("label");a.innerHTML="WMS/WFS URL:";b.appendChild(a);c=document.createElement("input");c.setAttribute("type","text");a.appendChild(c);this.importServiceInput=c;a=document.createElement("button");a.setAttribute("type","button");a.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";a.innerHTML=
+"<i class='netgis-icon fas fa-cloud-download-alt'></i><span>Dienst laden</span>";a.style.marginBottom="6mm";a.addEventListener("click",this.onImportServiceClick.bind(this));b.appendChild(a);a=document.createElement("div");a.className="netgis-hide";b.appendChild(a);this.importServiceDetails=a;b=document.createElement("label");b.innerHTML="Bezeichnung:";a.appendChild(b);c=document.createElement("input");c.setAttribute("type","text");b.appendChild(c);this.importServiceNameInput=c;b=document.createElement("label");
+b.innerHTML="Kartenebene:";a.appendChild(b);c=document.createElement("select");b.appendChild(c);this.importServiceLayerSelect=c;b=document.createElement("label");b.innerHTML="Format:";a.appendChild(b);c=document.createElement("select");b.appendChild(c);this.importServiceFormatSelect=c;b=document.createElement("button");b.setAttribute("type","button");b.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";b.innerHTML="<i class='netgis-icon fas fa-check'></i><span>Hinzuf\u00fcgen</span>";
+b.addEventListener("click",this.onImportServiceAccept.bind(this));a.appendChild(b);this.exportModal=new netgis.Modal("Exportieren");this.exportModal.container.classList.add("netgis-export");this.exportModal.attach(this.root);a=document.createElement("div");a.className="netgis-form netgis-noselect";a.style.position="absolute";a.style.width="100%";a.style.top="12mm";a.style.bottom="0mm";a.style.overflow="auto";a.style.padding="12mm";this.exportModal.content.appendChild(a);b=document.createElement("label");
+b.innerHTML="Format:";a.appendChild(b);c=document.createElement("select");c.innerHTML="<option value='pdf'>PDF</option><option value='jpeg'>JPEG</option><option value='png'>PNG</option><option value='gif'>GIF</option>";c.addEventListener("change",this.onExportFormatChange.bind(this));b.appendChild(c);this.exportFormatSelect=c;b=document.createElement("label");b.innerHTML="Breite (Pixel):";a.appendChild(b);c=document.createElement("input");c.setAttribute("type","number");c.setAttribute("min",0);b.appendChild(c);
+this.exportWidthInput=c;b=document.createElement("label");b.innerHTML="H\u00f6he (Pixel):";a.appendChild(b);c=document.createElement("input");c.setAttribute("type","number");c.setAttribute("min",0);b.appendChild(c);this.exportHeightInput=c;b=document.createElement("label");b.innerHTML="Seitenr\u00e4nder (Millimeter):";a.appendChild(b);c=document.createElement("input");c.setAttribute("type","number");c.setAttribute("min",0);c.value=10;b.appendChild(c);this.exportPaddingInput=c;b=document.createElement("label");
+b.innerHTML="Querformat:";a.appendChild(b);c=document.createElement("input");c.setAttribute("type","checkbox");b.appendChild(c);this.exportLandscapeInput=c;b=document.createElement("button");b.setAttribute("type","button");b.className="netgis-button netgis-center netgis-color-a netgis-hover-c netgis-shadow";b.innerHTML="<i class='netgis-icon fas fa-check'></i><span>Exportieren</span>";b.addEventListener("click",this.onExportButtonClick.bind(this));a.appendChild(b)};
+netgis.Client.prototype.initConfig=function(a){var b=[],c=a.folders;if(c){for(var d=0;d<c.length;d++){var e=1E3+d,f=this.layerTree.addFolder(null,e,c[d].title);b.push(f)}for(d=0;d<c.length;d++)e=c[d].parent,-1<e&&this.layerTree.setFolderParent(b[d],b[e])}if(c=a.layers)for(d=0;d<c.length;d++){var g=c[d];f=-1<g.folder?b[g.folder]:null;e=g.id;e||(e=1E3+d,g.id=e);this.layerTree.addCheckbox(f,e,g.title);g.active&&(this.map.addLayer(e,this.map.createLayer(g)),this.layerTree.setItemChecked(e,!0))}this.importFolder=
+this.layerTree.addFolder(null,"import","Importierte Ebenen",!0);this.importFolder.classList.add("netgis-hide");this.editFolder=this.layerTree.addFolder(null,"edit-folder","Zeichnung",!0);this.editFolder.classList.add("netgis-hide");this.layerTree.addCheckbox(this.editFolder,"edit-layer","Zeichnung");this.layerTree.setItemChecked("edit-layer",!0);this.importButton=this.layerTree.addButton(null,"<i class='netgis-icon fas fa-plus' style='font-size: 1em;'></i><span>Ebene hinzuf\u00fcgen...</span>",this.onLayerTreeImportClick.bind(this));
+this.attribution.onContextUpdate(a)};
+netgis.Client.prototype.initOutput=function(a){netgis.util.isDefined(a.output)?netgis.util.isDefined(a.output.id)&&(this.output=document.getElementById(a.output.id),this.output.value&&0<this.output.value.length&&(a=JSON.parse(this.output.value),this.map.addEditFeaturesGeoJSON(a,!1),this.map.map.updateSize(),this.map.zoomGeoJSON(a),this.editFolder.classList.remove("netgis-hide"))):(this.output=document.createElement("input"),this.output.setAttribute("type","hidden"),this.output.className="netgis-edit-output",
+this.root.appendChild(this.output))};
+netgis.Client.prototype.initEvents=function(){this.container.addEventListener(netgis.Events.SET_MODE,this.onSetMode.bind(this));this.container.addEventListener(netgis.Events.PANEL_TOGGLE,this.onPanelToggle.bind(this));this.container.addEventListener(netgis.Events.PANEL_RESIZE,this.onPanelResize.bind(this));this.container.addEventListener(netgis.Events.LAYERS_TOGGLE,this.onLayersToggle.bind(this));this.container.addEventListener(netgis.SearchPlace.Events.TOGGLE,this.onSearchPlaceToggle.bind(this));
+this.container.addEventListener(netgis.SearchParcel.Events.TOGGLE,this.onSearchParcelToggle.bind(this));this.container.addEventListener(netgis.Events.CONTROLS_ZOOM,this.onControlsZoom.bind(this));this.container.addEventListener(netgis.Events.CONTROLS_ZOOM_ALL,this.onControlsZoomAll.bind(this));this.container.addEventListener(netgis.Events.TOOLBOX_TOGGLE,this.onToolboxToggle.bind(this));this.parcelPanel.container.addEventListener(netgis.Events.PANEL_TOGGLE,this.onParcelsPanelToggle.bind(this));this.container.addEventListener(netgis.Events.PARCELS_RESET,
+this.onParcelsReset.bind(this));this.container.addEventListener(netgis.Events.PARCELS_FIELDS_RESPONSE,this.onParcelsFieldsResponse.bind(this));this.container.addEventListener(netgis.Events.PARCELS_RESPONSE,this.onParcelsResponse.bind(this));this.container.addEventListener(netgis.Events.PARCELS_ITEM_ENTER,this.onParcelsItemEnter.bind(this));this.container.addEventListener(netgis.Events.PARCELS_ITEM_LEAVE,this.onParcelsItemLeave.bind(this));this.container.addEventListener(netgis.Events.PARCELS_ITEM_CLICK,
+this.onParcelsItemClick.bind(this));this.container.addEventListener(netgis.Events.PARCELS_ITEM_IMPORT_CLICK,this.onParcelsImportClick.bind(this));this.container.addEventListener(netgis.Events.MAP_FEATURE_ENTER,this.onMapFeatureEnter.bind(this));this.container.addEventListener(netgis.Events.MAP_FEATURE_CLICK,this.onMapFeatureClick.bind(this));this.container.addEventListener(netgis.Events.MAP_FEATURE_LEAVE,this.onMapFeatureLeave.bind(this));this.container.addEventListener(netgis.Events.LAYER_CREATED,
+this.onLayerCreated.bind(this));this.layerTree.container.addEventListener(netgis.Tree.Events.ITEM_CHANGE,this.onLayerTreeItemChange.bind(this));this.searchPlace.container.addEventListener(netgis.SearchPlace.Events.SELECT,this.onSearchPlaceSelect.bind(this));this.container.addEventListener(netgis.Events.SNAP_TOGGLE,this.onSnapToggle.bind(this));this.container.addEventListener(netgis.Events.TRACING_TOGGLE,this.onTracingToggle.bind(this));this.container.addEventListener(netgis.Events.BUFFER_TOGGLE,this.onBufferToggle.bind(this));
+this.container.addEventListener(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE,this.onBufferRadiusChange.bind(this));this.container.addEventListener(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,this.onBufferSegmentsChange.bind(this));this.container.addEventListener(netgis.Events.BUFFER_CHANGE,this.onBufferFeatureChange.bind(this));this.container.addEventListener(netgis.Events.BUFFER_ACCEPT,this.onBufferFeatureAccept.bind(this));this.container.addEventListener(netgis.Events.IMPORT_SHAPEFILE_SHOW,this.onImportShapefileShow.bind(this));
+this.container.addEventListener(netgis.Events.IMPORT_GEOJSON_SHOW,this.onImportGeoJSONShow.bind(this));this.container.addEventListener(netgis.Events.IMPORT_GML_SHOW,this.onImportGMLShow.bind(this));this.container.addEventListener(netgis.Events.IMPORT_SPATIALITE_SHOW,this.onImportSpatialiteShow.bind(this));this.container.addEventListener(netgis.Events.IMPORT_GEOPACKAGE_SHOW,this.onImportGeopackageShow.bind(this));this.container.addEventListener(netgis.Events.EXPORT_PDF_SHOW,this.onExportPDFShow.bind(this));
+this.container.addEventListener(netgis.Events.EXPORT_PNG_SHOW,this.onExportPNGShow.bind(this));this.container.addEventListener(netgis.Events.EXPORT_JPEG_SHOW,this.onExportJPEGShow.bind(this));this.container.addEventListener(netgis.Events.EXPORT_GIF_SHOW,this.onExportGIFShow.bind(this));this.container.addEventListener(netgis.Events.EXPORT_PDF,this.onExportPDF.bind(this));this.container.addEventListener(netgis.Events.EXPORT_PNG,this.onExportPNG.bind(this));this.container.addEventListener(netgis.Events.EXPORT_JPEG,
+this.onExportJPEG.bind(this));this.container.addEventListener(netgis.Events.EXPORT_GIF,this.onExportGIF.bind(this));this.container.addEventListener(netgis.Events.EDIT_FEATURES_CHANGE,this.onEditFeaturesChange.bind(this));this.container.addEventListener(netgis.Events.EXPORT_SHOW,this.onExportShow.bind(this))};
 netgis.Client.prototype.createDefaultConfig=function(){return{map:{projection:"EPSG:3857",center:[1113194,6621293],minZoom:0,maxZoom:20,zoom:6,attribution:"NetGIS"},projections:[],layers:[{folder:0,type:netgis.LayerTypes.OSM,title:"Open Street Map",attribution:"OSM Contributors",active:!0}],folders:[{title:"Hintergrund",parent:-1}],styles:{editLayer:{fill:"rgba( 255, 0, 0, 0.5 )",stroke:"#ff0000",strokeWidth:3,pointRadius:6},select:{fill:"rgba( 0, 127, 255, 0.5 )",stroke:"#007fff",strokeWidth:3,pointRadius:6},
 sketch:{fill:"rgba( 0, 127, 0, 0.5 )",stroke:"#007f00",strokeWidth:3,pointRadius:6},modify:{fill:"rgba( 0, 127, 0, 0.5 )",stroke:"#007f00",strokeWidth:3,pointRadius:6},parcel:{fill:"rgba( 127, 255, 255, 0.5 )",stroke:"#7fffff",strokeWidth:3}}}};
 netgis.Client.prototype.create=function(){this.root=document.createElement("section");this.root.className="netgis-client";this.loader=document.createElement("div");this.loader.className="netgis-loader netgis-dialog netgis-text-primary";this.loader.innerHTML="<i class='fas fa-spinner'></i>";this.root.appendChild(this.loader);this.container.appendChild(this.root)};
-netgis.Client.prototype.createModules=function(){this.editable=!0;this.container.hasAttribute("contenteditable")&&"false"===this.container.getAttribute("contenteditable")&&(this.editable=!1);this.container.hasAttribute("data-editable")&&(this.editable="true"===this.container.getAttribute("data-editable")?!0:!1);this.add(this.map=new netgis.MapOpenLayers);this.add(new netgis.Controls);this.add(new netgis.Attribution);this.add(new netgis.LayerTree);this.add(new netgis.Toolbar);this.add(new netgis.Menu);
-this.add(new netgis.SearchPlace);this.add(new netgis.SearchParcel);this.add(new netgis.Modal)};
-netgis.Client.prototype.load=function(){for(var a=0;a<this.modules.length;a++)this.modules[a].load();netgis.util.isDefined(this.config.output)?netgis.util.isDefined(this.config.output.id)&&(this.output=document.getElementById(this.config.output.id),this.output.value&&0<this.output.value.length&&(a=JSON.parse(this.output.value),this.invoke(netgis.Events.EDIT_FEATURES_LOADED,a))):(this.output=document.createElement("input"),this.output.setAttribute("type","hidden"),this.output.className="netgis-edit-output",
-this.root.appendChild(this.output));this.invoke(netgis.Events.SET_MODE,netgis.Modes.VIEW);this.on(netgis.Events.EXPORT_BEGIN,this.onMapExportBegin.bind(this));this.on(netgis.Events.EXPORT_END,this.onMapExportEnd.bind(this));this.on(netgis.Events.EDIT_FEATURES_CHANGE,this.onEditFeaturesChange.bind(this))};netgis.Client.prototype.add=function(a){a.client=this;this.modules.push(a)};netgis.Client.prototype.on=function(a,b){netgis.util.isDefined(this.callbacks[a])||(this.callbacks[a]=[]);this.callbacks[a].push(b)};
-netgis.Client.prototype.off=function(a,b){if(netgis.util.isDefined(this.callbacks[a]))if(netgis.util.isDefined(b)){for(var c=0;c<this.callbacks[a].length;c++)if(this.callbacks[a][c]===b){this.callbacks[a].splice(c,1);break}1>this.callbacks[a].length&&delete this.callbacks[a]}else delete this.callbacks[a]};netgis.Client.prototype.invoke=function(a,b){this.debug&&console.info("EVENT:",a,b);if(netgis.util.isDefined(this.callbacks[a]))for(var c=0;c<this.callbacks[a].length;c++)this.callbacks[a][c](b)};
-netgis.Client.prototype.showLoader=function(){this.loader.classList.remove("netgis-hide")};netgis.Client.prototype.hideLoader=function(){this.loader.classList.add("netgis-hide")};netgis.Client.prototype.onHtmlResponse=function(a){this.root=netgis.util.create(a);this.container.appendChild(this.root)};netgis.Client.prototype.onEditFeaturesChange=function(a){a=JSON.stringify(a);this.output.value=a};netgis.Client.prototype.onMapExportBegin=function(a){this.showLoader()};
-netgis.Client.prototype.onMapExportEnd=function(a){this.hideLoader()};netgis=netgis||{};netgis.Controls=function(){this.client=null};
-netgis.Controls.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-controls";var a=document.createElement("button");a.setAttribute("type","button");a.innerHTML="<i class='fas fa-search-plus'></i>";a.title="Hineinzoomen";a.addEventListener("click",this.onZoomIn.bind(this));this.root.appendChild(a);a=document.createElement("button");a.setAttribute("type","button");a.innerHTML="<i class='fas fa-search-minus'></i>";a.title="Herauszoomen";a.addEventListener("click",
-this.onZoomOut.bind(this));this.root.appendChild(a);this.client.root.appendChild(this.root)};netgis.Controls.prototype.onZoomIn=function(a){this.client.invoke(netgis.Events.MAP_CHANGE_ZOOM,1)};netgis.Controls.prototype.onZoomOut=function(a){this.client.invoke(netgis.Events.MAP_CHANGE_ZOOM,-1)};netgis.Controls.prototype.onSettings=function(a){alert("TODO: settings dialog")};netgis=netgis||{};
-netgis.Events=Object.freeze({CONTEXT_UPDATE:"CONTEXT_UPDATE",SET_MODE:"SET_MODE",LAYER_LIST_TOGGLE:"LAYER_LIST_TOGGLE",PANEL_TOGGLE:"PANEL_TOGGLE",PANEL_SHOW:"PANEL_SHOW",PANEL_HIDE:"PANEL_HIDE",LAYER_SHOW:"LAYER_SHOW",LAYER_HIDE:"LAYER_HIDE",LAYER_CREATED:"LAYER_CREATED",MAP_ZOOM_WKT:"MAP_ZOOM_WKT",MAP_SET_EXTENT:"MAP_SET_EXTENT",MAP_CHANGE_ZOOM:"MAP_CHANGE_ZOOM",MAP_UPDATE_STYLE:"MAP_UPDATE_STYLE",MAP_MODE_POINTS:"MAP_MODE_POINTS",MAP_MODE_LINES:"MAP_MODE_LINES",MAP_MODE_POLYGONS:"MAP_MODE_POLYGONS",EDIT_FEATURES_LOADED:"EDIT_FEATURES_LOADED",
-EDIT_FEATURES_CHANGE:"EDIT_FEATURES_CHANGE",SEARCH_PLACE_REQUEST:"SEARCH_PLACE_REQUEST",SEARCH_PLACE_RESPONSE:"SEARCH_PLACE_RESPONSE",PARCEL_SHOW_PREVIEW:"PARCEL_SHOW_PREVIEW",PARCEL_HIDE_PREVIEW:"PARCEL_HIDE_PREVIEW",BUFFER_CHANGE:"BUFFER_CHANGE",BUFFER_ACCEPT:"BUFFER_ACCEPT",BUFFER_CANCEL:"BUFFER_CANCEL",DRAW_BUFFER_ON:"DRAW_BUFFER_ON",DRAW_BUFFER_OFF:"DRAW_BUFFER_OFF",DRAW_BUFFER_RADIUS_CHANGE:"DRAW_BUFFER_RADIUS_CHANGE",DRAW_BUFFER_SEGMENTS_CHANGE:"DRAW_BUFFER_SEGMENTS_CHANGE",SNAP_ON:"SNAP_ON",
-SNAP_OFF:"SNAP_OFF",TRACING_ON:"TRACING_ON",TRACING_OFF:"TRACING_OFF",IMPORT_SHAPEFILE_SHOW:"IMPORT_SHAPEFILE_SHOW",IMPORT_GEOJSON_SHOW:"IMPORT_GEOJSON_SHOW",IMPORT_GML_SHOW:"IMPORT_GML_SHOW",IMPORT_SPATIALITE_SHOW:"IMPORT_SPATIALITE_SHOW",IMPORT_GEOPACKAGE_SHOW:"IMPORT_GEOPACKAGE_SHOW",IMPORT_SHAPEFILE:"IMPORT_SHAPEFILE",IMPORT_GEOJSON:"IMPORT_GEOJSON",IMPORT_GML:"IMPORT_GML",IMPORT_WKT:"IMPORT_WKT",IMPORT_SPATIALITE:"IMPORT_SPATIALITE",IMPORT_GEOPACKAGE:"IMPORT_GEOPACKAGE",EXPORT_PDF_SHOW:"EXPORT_PDF_SHOW",
-EXPORT_JPEG_SHOW:"EXPORT_JPEG_SHOW",EXPORT_PNG_SHOW:"EXPORT_PNG_SHOW",EXPORT_GIF_SHOW:"EXPORT_GIF_SHOW",EXPORT_PDF:"EXPORT_PDF",EXPORT_JPEG:"EXPORT_JPEG",EXPORT_PNG:"EXPORT_PNG",EXPORT_GIF:"EXPORT_GIF",EXPORT_BEGIN:"EXPORT_BEGIN",EXPORT_END:"EXPORT_END",ADD_SERVICE_SHOW:"ADD_SERVICE_SHOW",ADD_SERVICE_WMS:"ADD_SERVICE_WMS",ADD_SERVICE_WFS:"ADD_SERVICE_WFS"});netgis=netgis||{};netgis.LayerTree=function(){this.folderDraw=this.folderImport=this.list=this.root=this.client=null};
-netgis.LayerTree.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-layer-list netgis-dialog netgis-shadow netgis-hide";this.list=document.createElement("ul");this.list.className="root";this.root.appendChild(this.list);this.initDefaultFolders();this.tools=document.createElement("div");this.tools.className="netgis-layer-tools";this.tools.innerHTML="<hr/>";this.root.appendChild(this.tools);this.buttonAddService=document.createElement("button");this.buttonAddService.className=
-"netgis-text-primary netgis-hover-primary";this.buttonAddService.innerHTML="<i class='fas fa-folder-plus'></i> Dienst hinzuf\u00fcgen";this.buttonAddService.addEventListener("click",this.onAddServiceClick.bind(this));this.tools.appendChild(this.buttonAddService);this.client.root.appendChild(this.root);this.client.on(netgis.Events.CONTEXT_UPDATE,this.onContextUpdate.bind(this));this.client.on(netgis.Events.LAYER_LIST_TOGGLE,this.onLayerListToggle.bind(this));this.client.on(netgis.Events.LAYER_CREATED,
-this.onLayerCreated.bind(this));this.client.on(netgis.Events.EDIT_FEATURES_CHANGE,this.onEditFeaturesChange.bind(this));this.client.on(netgis.Events.ADD_SERVICE_WMS,this.onAddServiceWMS.bind(this));this.client.on(netgis.Events.ADD_SERVICE_WFS,this.onAddServiceWFS.bind(this));this.client.on(netgis.Events.SET_MODE,this.onSetMode.bind(this))};
-netgis.LayerTree.prototype.initDefaultFolders=function(){this.folderDraw=this.createFolder("Zeichnung");this.folderDraw.classList.add("netgis-hide");this.list.appendChild(this.folderDraw);this.folderImport=this.createFolder("Importierte Ebenen");this.folderImport.classList.add("netgis-hide");this.list.appendChild(this.folderImport);this.folderServices=this.createFolder("Eigene Dienste");this.folderServices.classList.add("netgis-hide");this.list.appendChild(this.folderServices)};
-netgis.LayerTree.prototype.clearAll=function(){this.list.innerHTML="";this.initDefaultFolders()};
-netgis.LayerTree.prototype.createFolder=function(a){var b=document.createElement("li");b.className="netgis-folder netgis-hover-light";b.setAttribute("title",a);var c=document.createElement("label");c.className="netgis-icon";b.appendChild(c);var d=document.createElement("input");d.setAttribute("type","checkbox");d.addEventListener("change",this.onFolderChange.bind(this));c.appendChild(d);c=document.createElement("button");c.setAttribute("type","button");c.className="netgis-clip-text netgis-hover-text-primary";
-c.innerHTML='<i class="fas fa-folder-open"></i>'+a;c.addEventListener("click",this.onFolderClick.bind(this));b.appendChild(c);a=document.createElement("ul");b.appendChild(a);return b};
-netgis.LayerTree.prototype.createLayer=function(a,b,c){var d=document.createElement("li");d.setAttribute("title",b);d.className="netgis-folder-item netgis-hover-text-primary";var e=document.createElement("label");e.className="netgis-label netgis-clip-text";d.appendChild(e);var f=document.createElement("span");f.className="netgis-icon";e.appendChild(f);var g=document.createElement("input");g.setAttribute("type","checkbox");g.dataset.id=a;g.checked=c;g.addEventListener("change",this.onItemChange.bind(this));
-f.appendChild(g);a=document.createElement("i");a.className="fas fa-th-large";e.appendChild(a);b=document.createTextNode(b);e.appendChild(b);b=document.createElement("span");e.appendChild(b);return d};netgis.LayerTree.prototype.addToFolder=function(a,b,c){a?(a=a.getElementsByTagName("ul")[0],a.appendChild(b)):a=this.list;c?a.insertBefore(b,a.firstChild):a.appendChild(b)};netgis.LayerTree.prototype.onFolderClick=function(a){a.currentTarget.parentElement.classList.toggle("netgis-active")};
-netgis.LayerTree.prototype.onFolderChange=function(a){var b=a.currentTarget;a=b.checked;b=b.parentElement.parentElement;for(var c=b.getElementsByTagName("input"),d=1;d<c.length;d++){var e=c[d];e.checked=a;e=e.dataset.id;netgis.util.isDefined(e)&&(e=parseInt(e),this.client.invoke(a?netgis.Events.LAYER_SHOW:netgis.Events.LAYER_HIDE,{id:e}))}this.updateFolderChecks(b);a=b.parentElement.parentElement;-1!==a.className.search("netgis-folder")&&this.updateFolderChecks(a)};
-netgis.LayerTree.prototype.updateFolderChecks=function(a){netgis.util.isDefined(a)||(a=this.list);for(var b=a.getElementsByClassName("netgis-folder-item"),c=0,d=0;d<b.length;d++){var e=b[d].getElementsByTagName("input")[0];e.checked&&c++}e=a.getElementsByTagName("input")[0];d=0;0<c&&(d=1);c===b.length&&(d=2);switch(d){case 0:e.checked=!1;e.classList.remove("netgis-partial");break;case 1:e.checked=!0;e.classList.add("netgis-partial");break;case 2:e.checked=!0,e.classList.remove("netgis-partial")}(a=
-a.parentElement)&&a!==this.list&&(a=a.parentElement)&&-1!==a.className.search("netgis-folder")&&this.updateFolderChecks(a)};
-netgis.LayerTree.prototype.onItemChange=function(a){var b=a.currentTarget;a=b.checked;var c=b.parentElement.parentElement.parentElement;b=parseInt(b.dataset.id);c=c.parentElement.parentElement;for(var d=c.getElementsByTagName("input"),e=0,f=1;f<d.length;f++)d[f].checked&&e++;-1!==c.className.search("netgis-folder")&&this.updateFolderChecks(c);this.client.invoke(a?netgis.Events.LAYER_SHOW:netgis.Events.LAYER_HIDE,{id:b})};netgis.LayerTree.prototype.onLayerListToggle=function(a){this.root.classList.toggle("netgis-hide")};
-netgis.LayerTree.prototype.onContextUpdate=function(a){this.clearAll();var b=a.folders;a=a.layers;for(var c=[],d=0;d<b.length;d++){var e=b[d],f=this.createFolder(e.title);c.push(f)}for(d=0;d<a.length;d++)e=a[d],f=this.createLayer(d,e.title,e.active),this.addToFolder(c[e.folder],f);for(d=0;d<b.length;d++)e=b[d],f=c[d],-1===e.parent?this.list.appendChild(f):this.addToFolder(c[e.parent],f);for(d=0;d<a.length;d++)e=a[d],e.active&&this.client.invoke(netgis.Events.LAYER_SHOW,{id:d});for(d=0;d<c.length;d++)this.updateFolderChecks(c[d])};
-netgis.LayerTree.prototype.onLayerCreated=function(a){var b=this.createLayer(a.id,a.title,a.checked);if("import"===a.folder){this.folderImport.classList.remove("netgis-hide");var c=this.folderImport}else"draw"===a.folder&&(this.folderDraw.classList.remove("netgis-hide"),c=this.folderDraw);this.addToFolder(c,b,!0);this.updateFolderChecks(c)};
-netgis.LayerTree.prototype.onEditFeaturesChange=function(a){if(this.folderDraw){var b=this.folderDraw.getElementsByTagName("ul")[0],c=b.getElementsByTagName("input")[0],d=parseInt(c.dataset.id);c.checked||(c.checked=!0,this.updateFolderChecks(this.folderDraw),this.client.invoke(netgis.Events.LAYER_SHOW,{id:d}));b=b.getElementsByTagName("label")[0].getElementsByTagName("span");b[b.length-1].innerText=a.area&&0<a.area?" (Fl\u00e4che: "+netgis.util.formatArea(a.area,!0)+")":""}};
-netgis.LayerTree.prototype.onAddServiceWMS=function(a){var b=this.createLayer(a.id,a.title,!0);this.folderServices.classList.remove("netgis-hide");this.addToFolder(this.folderServices,b,!0);this.updateFolderChecks(this.folderServices);this.client.invoke(netgis.Events.LAYER_SHOW,{id:a.id})};
-netgis.LayerTree.prototype.onAddServiceWFS=function(a){var b=this.createLayer(a.id,a.title,!0);this.folderServices.classList.remove("netgis-hide");this.addToFolder(this.folderServices,b,!0);this.updateFolderChecks(this.folderServices);this.client.invoke(netgis.Events.LAYER_SHOW,{id:a.id})};netgis.LayerTree.prototype.onSetMode=function(a){a===netgis.Modes.SEARCH_PARCEL&&this.root.classList.add("netgis-hide")};
-netgis.LayerTree.prototype.onAddServiceClick=function(a){this.client.invoke(netgis.Events.ADD_SERVICE_SHOW,null)};netgis=netgis||{};netgis.LayerTypes=Object.freeze({XYZ:"XYZ",OSM:"OSM",WMS:"WMS",WFS:"WFS",KML:"KML"});netgis=netgis||{};netgis.Map=function(){this.attribution=this.root=this.client=null};netgis.Map.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-map";this.client.root.appendChild(this.root)};netgis=netgis||{};netgis.MapOpenLayers=function(){netgis.Map.call(this);this.mode=null;this.toolbars={};this.map=this.view=null;this.layers=[];this.interactions={};this.sketch=this.selected=this.hover=this.parcelLayer=this.editLayer=this.snapFeatures=this.snap=null;this.editEventsSilent=!1;this.importLayerID=2E4;this.editLayerID=3E4;this.labelFont="4mm Verdana, sans-serif";this.drawBufferRadius=100;this.drawBufferSegments=3};netgis.MapOpenLayers.prototype=Object.create(netgis.Map.prototype);
-netgis.MapOpenLayers.prototype.constructor=netgis.MapOpenLayers;
-netgis.MapOpenLayers.prototype.load=function(){netgis.Map.prototype.load.call(this);this.dropTarget=document.createElement("div");this.dropTarget.className="netgis-drop-target netgis-hide";this.dropTarget.innerHTML="Datei hier ablegen!";this.root.appendChild(this.dropTarget);this.root.addEventListener("dragenter",this.onDragEnter.bind(this));this.root.addEventListener("dragover",this.onDragEnter.bind(this));this.root.addEventListener("dragend",this.onDragLeave.bind(this));this.root.addEventListener("dragleave",
-this.onDragLeave.bind(this));this.root.addEventListener("drop",this.onDragDrop.bind(this));this.initMap();this.initDefaultLayers();this.initInteractions();this.client.on(netgis.Events.CONTEXT_UPDATE,this.onContextUpdate.bind(this));this.client.on(netgis.Events.MAP_UPDATE_STYLE,this.onUpdateStyle.bind(this));this.client.on(netgis.Events.EDIT_FEATURES_LOADED,this.onEditFeaturesLoaded.bind(this));this.client.on(netgis.Events.SET_MODE,this.onSetMode.bind(this));this.client.on(netgis.Events.SNAP_ON,this.onSnapOn.bind(this));
-this.client.on(netgis.Events.SNAP_OFF,this.onSnapOff.bind(this));this.client.on(netgis.Events.TRACING_ON,this.onTracingOn.bind(this));this.client.on(netgis.Events.TRACING_OFF,this.onTracingOff.bind(this));this.client.on(netgis.Events.LAYER_SHOW,this.onLayerShow.bind(this));this.client.on(netgis.Events.LAYER_HIDE,this.onLayerHide.bind(this));this.client.on(netgis.Events.MAP_ZOOM_WKT,this.onZoomWKT.bind(this));this.client.on(netgis.Events.MAP_SET_EXTENT,this.onSetExtent.bind(this));this.client.on(netgis.Events.MAP_CHANGE_ZOOM,
-this.onChangeZoom.bind(this));this.client.on(netgis.Events.BUFFER_CHANGE,this.onBufferChange.bind(this));this.client.on(netgis.Events.BUFFER_ACCEPT,this.onBufferAccept.bind(this));this.client.on(netgis.Events.BUFFER_CANCEL,this.onBufferCancel.bind(this));this.client.on(netgis.Events.IMPORT_GEOJSON,this.onImportGeoJSON.bind(this));this.client.on(netgis.Events.IMPORT_GML,this.onImportGML.bind(this));this.client.on(netgis.Events.IMPORT_SHAPEFILE,this.onImportShapefile.bind(this));this.client.on(netgis.Events.IMPORT_WKT,
-this.onImportWKT.bind(this));this.client.on(netgis.Events.IMPORT_SPATIALITE,this.onImportSpatialite.bind(this));this.client.on(netgis.Events.IMPORT_GEOPACKAGE,this.onImportGeopackage.bind(this));this.client.on(netgis.Events.EXPORT_PDF,this.onExportPDF.bind(this));this.client.on(netgis.Events.EXPORT_JPEG,this.onExportJPEG.bind(this));this.client.on(netgis.Events.EXPORT_PNG,this.onExportPNG.bind(this));this.client.on(netgis.Events.EXPORT_GIF,this.onExportGIF.bind(this));this.client.on(netgis.Events.PARCEL_SHOW_PREVIEW,
-this.onParcelShowPreview.bind(this));this.client.on(netgis.Events.PARCEL_HIDE_PREVIEW,this.onParcelHidePreview.bind(this));this.client.on(netgis.Events.ADD_SERVICE_WMS,this.onAddServiceWMS.bind(this));this.client.on(netgis.Events.ADD_SERVICE_WFS,this.onAddServiceWFS.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_ON,this.onDrawBufferOn.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_OFF,this.onDrawBufferOff.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE,this.onDrawBufferRadiusChange.bind(this));
-this.client.on(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,this.onDrawBufferSegmentsChange.bind(this))};
-netgis.MapOpenLayers.prototype.initMap=function(){var a=this.client.config;"undefined"!==typeof proj4&&(proj4.defs(a.projections),proj4.defs("urn:ogc:def:crs:OGC:1.3:CRS84",proj4.defs("EPSG:4326")),ol.proj.proj4.register(proj4));this.view=new ol.View({projection:a.map.projection,center:a.map.center,minZoom:a.map.minZoom,maxZoom:a.map.maxZoom,zoom:a.map.zoom});this.map=new ol.Map({target:this.root,view:this.view,pixelRatio:1,moveTolerance:5,controls:[]});this.map.on("pointermove",this.onPointerMove.bind(this));
-this.map.on("click",this.onSingleClick.bind(this));this.map.on("movestart",this.onMoveStart.bind(this));this.map.on("moveend",this.onMoveEnd.bind(this));this.view.on("change:resolution",this.onChangeResolution.bind(this))};
-netgis.MapOpenLayers.prototype.initDefaultLayers=function(){this.editLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleEdit.bind(this),zIndex:this.editLayerID});this.map.addLayer(this.editLayer);this.previewLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleSketch.bind(this),zIndex:this.editLayerID+10});this.map.addLayer(this.previewLayer);this.parcelLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleParcel.bind(this),
-zIndex:this.editLayerID+20});this.map.addLayer(this.parcelLayer);this.editEventsOn()};netgis.MapOpenLayers.prototype.editEventsOn=function(){this.editLayer.getSource().on("addfeature",this.onEditLayerAdd.bind(this));this.editLayer.getSource().on("removefeature",this.onEditLayerRemove.bind(this))};netgis.MapOpenLayers.prototype.editEventsOff=function(){};
+netgis.Client.prototype.createModules=function(){this.editable=!0;this.container.hasAttribute("contenteditable")&&"false"===this.container.getAttribute("contenteditable")&&(this.editable=!1);this.container.hasAttribute("data-editable")&&(this.editable="true"===this.container.getAttribute("data-editable")?!0:!1);this.add(this.attribution=new netgis.Attribution);this.add(new netgis.Toolbar);this.add(new netgis.Menu)};
+netgis.Client.prototype.load=function(){for(var a=0;a<this.modules.length;a++)this.modules[a].load();this.invoke(netgis.Events.SET_MODE,netgis.Modes.VIEW);this.on(netgis.Events.EXPORT_BEGIN,this.onMapExportBegin.bind(this));this.on(netgis.Events.EXPORT_END,this.onMapExportEnd.bind(this));this.on(netgis.Events.EDIT_FEATURES_CHANGE,this.onEditFeaturesChange.bind(this))};netgis.Client.prototype.add=function(a){a.client=this;this.modules.push(a)};
+netgis.Client.prototype.on=function(a,b){netgis.util.isDefined(this.callbacks[a])||(this.callbacks[a]=[]);this.callbacks[a].push(b)};netgis.Client.prototype.off=function(a,b){if(netgis.util.isDefined(this.callbacks[a]))if(netgis.util.isDefined(b)){for(var c=0;c<this.callbacks[a].length;c++)if(this.callbacks[a][c]===b){this.callbacks[a].splice(c,1);break}1>this.callbacks[a].length&&delete this.callbacks[a]}else delete this.callbacks[a]};
+netgis.Client.prototype.invoke=function(a,b){this.debug&&console.info("EVENT:",a,b);if(netgis.util.isDefined(this.callbacks[a]))for(var c=0;c<this.callbacks[a].length;c++)this.callbacks[a][c](b)};netgis.Client.prototype.showLoader=function(){this.loader.classList.remove("netgis-hide")};netgis.Client.prototype.hideLoader=function(){this.loader.classList.add("netgis-hide")};netgis.Client.prototype.onHtmlResponse=function(a){this.root=netgis.util.create(a);this.container.appendChild(this.root)};
+netgis.Client.prototype.onEditFeaturesChange=function(a){var b=JSON.stringify(a.detail);this.output.value=b;this.attribution.onEditFeaturesChange(a.detail)};netgis.Client.prototype.onMapExportBegin=function(a){this.showLoader()};netgis.Client.prototype.onMapExportEnd=function(a){this.hideLoader()};netgis.Client.prototype.setMode=function(a){this.map.setMode(a);this.toolbox.setMode(a)};
+netgis.Client.prototype.onPanelToggle=function(a){a=a.detail;a.visible?this.map.setPadding(0,0,0,a.panel.width()):(a=!1,this.layerPanel.visible()&&(a=!0),this.toolboxPanel.visible()&&(a=!0),this.parcelPanel.visible()&&(a=!0),a||this.map.setPadding(0,0,0,0))};netgis.Client.prototype.onPanelResize=function(a){this.map.setPadding(0,0,0,a.detail.width)};netgis.Client.prototype.onLayerCreated=function(a){a.detail.id===this.map.editLayerID&&this.editFolder.classList.remove("netgis-hide")};
+netgis.Client.prototype.onLayersToggle=function(a){this.layerPanel.toggle();this.layerPanel.visible()&&(this.toolboxPanel.hide(),this.parcelPanel.hide())};
+netgis.Client.prototype.onLayerTreeItemChange=function(a){var b=a.detail.id;a=a.detail.checked;switch(b){default:for(var c=this.config.layers,d=!1,e=null,f=0;f<c.length;f++){var g=c[f],h=g.id;if(h===b){e=this.map.createLayer(g);d=!0;break}}if(!d)for(h in this.importLayers)if(h===b){e=this.importLayers[b];d=!0;break}d&&(a?(this.map.addLayer(b,e),this.attribution.onLayerShow({id:b})):(this.map.removeLayer(b),this.attribution.onLayerHide({id:b})));break;case "edit-layer":a?this.map.addLayer(netgis.Client.Layers.EDIT_LAYER,
+this.map.editLayer):this.map.removeLayer(netgis.Client.Layers.EDIT_LAYER)}};netgis.Client.prototype.onToolboxToggle=function(a){this.toolboxPanel.toggle();this.toolboxPanel.visible()&&(this.layerPanel.hide(),this.parcelPanel.hide())};netgis.Client.prototype.onSearchPlaceToggle=function(a){this.searchPlace.toggle()};netgis.Client.prototype.onSearchPlaceSelect=function(a){a=a.detail;this.map.zoomExtent(a.minx,a.miny,a.maxx,a.maxy)};
+netgis.Client.prototype.onSearchParcelToggle=function(a){this.parcelPanel.toggle();this.parcelPanel.visible()&&(this.layerPanel.hide(),this.toolboxPanel.hide())};netgis.Client.prototype.onControlsZoom=function(a){this.map.zoom(a.detail)};netgis.Client.prototype.onControlsZoomAll=function(a){this.map.zoomAll()};netgis.Client.prototype.onParcelsPanelToggle=function(a){this.searchParcel.reset()};
+netgis.Client.prototype.onParcelsReset=function(a){this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FIELDS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FEATURES);if(this.parcelPanel.visible()){this.parcelsAdded=[];var b=this.config.searchParcel.districts_service;a=this.map.createLayer(b);var c=this.config.styles.parcel;this.map.setLayerStyleSimple(a,c.fill,c.stroke,c.width);this.map.addLayer(netgis.Client.Layers.PARCEL_DISTRICTS,a);
+if(b.minZoom){var d=this;window.setTimeout(function(){d.map.zoomLevel(b.minZoom+1)},50)}this.setMode(netgis.Modes.PARCEL_SELECT)}else this.setMode(netgis.Modes.VIEW)};
+netgis.Client.prototype.onParcelsFieldsResponse=function(a){var b=a.detail;this.map.zoomGeoJSON(b.geojson);this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);a=this.config.styles.parcel;b=this.map.createLayerGeoJSON(b.geojson);this.map.setLayerStyleSimple(b,a.fill,a.stroke,a.width);this.map.setLayerOrder(b,4E4);this.map.addLayer(netgis.Client.Layers.PARCEL_FIELDS,b)};
+netgis.Client.prototype.onParcelsResponse=function(a){a=this.map.createLayerWKT(a.detail.parcels);var b=this.config.styles.parcel;this.map.removeLayer(netgis.Client.Layers.PARCEL_DISTRICTS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FIELDS);this.map.removeLayer(netgis.Client.Layers.PARCEL_FEATURES);this.map.setLayerStyleSimple(a,b.fill,b.stroke,b.width);this.map.addLayer(netgis.Client.Layers.PARCEL_FEATURES,a);this.map.zoomLayer(netgis.Client.Layers.PARCEL_FEATURES)};
+netgis.Client.prototype.onMapFeatureEnter=function(a){a=a.detail;switch(a.layer){case netgis.Client.Layers.PARCEL_DISTRICTS:a=a.properties.gemarkung;this.map.container.setAttribute("title",a);break;case netgis.Client.Layers.PARCEL_FIELDS:a=a.properties.flurname;this.map.container.setAttribute("title",a);break;case netgis.Client.Layers.PARCEL_FEATURES:a="Flur: "+a.properties.fln+" / Z\u00e4hler: "+a.properties.fsn_zae+" / Nenner: "+a.properties.fsn_nen,this.map.container.setAttribute("title",a+" (Klicken zum \u00dcbernehmen der Geometrie)")}};
+netgis.Client.prototype.onMapFeatureClick=function(a){a=a.detail;switch(a.layer){default:console.info("Feature Click:",a);break;case netgis.Client.Layers.PARCEL_DISTRICTS:this.searchParcel.setDistrict(a.properties.gemarkung+" ("+a.properties.ldkreis+")",a.properties.gmkgnr);break;case netgis.Client.Layers.PARCEL_FIELDS:this.searchParcel.setFieldNumber(a.properties.flur);break;case netgis.Client.Layers.PARCEL_FEATURES:var b=a.properties.fsk;-1===this.parcelsAdded.indexOf(b)&&(this.map.addEditFeature(this.map.createFeatureJSON(a.properties)),
+this.map.updateSnapFeatures(),this.parcelsAdded.push(b))}};netgis.Client.prototype.onMapFeatureLeave=function(a){this.map.container.setAttribute("title","")};netgis.Client.prototype.onParcelsItemEnter=function(a){this.map.setFeatureHover(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id),!0)};netgis.Client.prototype.onParcelsItemLeave=function(a){this.map.setFeatureHover(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id),!1)};
+netgis.Client.prototype.onParcelsItemClick=function(a){this.map.zoomFeature(this.map.findFeature(netgis.Client.Layers.PARCEL_FEATURES,"fsk",a.detail.id))};netgis.Client.prototype.onParcelsImportClick=function(a){a=a.detail;this.map.addEditFeature(this.map.createFeatureWKT(a.geom,{id:a.id}));this.map.updateSnapFeatures()};netgis.Client.prototype.onSetMode=function(a){this.setMode(a.detail)};
+netgis.Client.prototype.onSnapToggle=function(a){(a=a.detail.target.checked)?(this.map.updateSnapFeatures(),this.map.setSnapOn()):this.map.setSnapOff();this.toolbox.setSnap(a)};netgis.Client.prototype.onTracingToggle=function(a){a.detail.target.checked?(this.map.updateSnapFeatures(),this.map.setSnapOn(),this.map.setTracingOn(),this.toolbox.setSnap(!0)):this.map.setTracingOff()};
+netgis.Client.prototype.onBufferToggle=function(a){if(a=a.detail.target.checked)this.map.onDrawBufferOn();else this.map.onDrawBufferOff();this.toolbox.setBuffer(a)};netgis.Client.prototype.onBufferRadiusChange=function(a){a=Number.parseFloat(a.detail.target.value);this.map.onDrawBufferRadiusChange(a);this.toolbox.setBufferRadius(a)};netgis.Client.prototype.onBufferSegmentsChange=function(a){a=Number.parseInt(a.detail.target.value);this.map.onDrawBufferSegmentsChange(a);this.toolbox.setBufferSegments(a)};
+netgis.Client.prototype.onBufferFeatureChange=function(a){this.map.onBufferChange(a.detail)};netgis.Client.prototype.onBufferFeatureAccept=function(a){this.map.onBufferAccept()};netgis.Client.prototype.onImportShapefileShow=function(a){this.modal.onImportShapefileShow(a)};netgis.Client.prototype.onImportGeoJSONShow=function(a){this.modal.onImportGeoJSONShow(a)};netgis.Client.prototype.onImportGMLShow=function(a){this.modal.onImportGMLShow(a)};netgis.Client.prototype.onImportSpatialiteShow=function(a){this.modal.onImportSpatialiteShow(a)};
+netgis.Client.prototype.onImportGeopackageShow=function(a){this.modal.onImportGeopackageShow(a)};netgis.Client.prototype.onExportPDFShow=function(a){this.modal.onExportPDFShow(a)};netgis.Client.prototype.onExportPNGShow=function(a){this.modal.onExportPNGShow(a)};netgis.Client.prototype.onExportJPEGShow=function(a){this.modal.onExportJPEGShow(a)};netgis.Client.prototype.onExportGIFShow=function(a){this.modal.onExportGIFShow(a)};netgis.Client.prototype.onExportPDF=function(a){this.map.onExportPDF(a)};
+netgis.Client.prototype.onExportPNG=function(a){this.map.onExportPNG(a)};netgis.Client.prototype.onExportJPEG=function(a){this.map.onExportJPEG(a)};netgis.Client.prototype.onExportGIF=function(a){this.map.onExportGIF(a)};netgis.Client.prototype.onLayerTreeImportClick=function(a){this.importModal.show()};
+netgis.Client.prototype.onImportFileClick=function(a){if(a=this.importFileInput.files[0]){var b=a.name,c=this;switch(netgis.util.getFileExtension(a.name).toLowerCase()){case "geojson":console.info("GeoJSON detected:",a.name);var d=new FileReader;d.onload=function(a){a=JSON.parse(a.target.result);c.addImportLayer(b,c.map.createLayerGeoJSON(a,!0))};d.readAsText(a);break;case "zip":console.info("Shapefile Zip detected:",a.name);d=new FileReader;d.onload=function(a){c.addImportLayer(b,c.map.createLayerShapefile(a.target.result))};
+d.readAsArrayBuffer(a);break;case "gml":console.info("GML detected:",a.name);d=new FileReader;d.onload=function(a){c.addImportLayer(b,c.map.createLayerGML(a.target.result))};d.readAsText(a);break;case "sqlite":console.info("Spatialite detected:",a.name);d=new FileReader;d.onload=function(a){c.addImportLayer(b,c.map.createLayerSpatialite(a.target.result))};d.readAsArrayBuffer(a);break;case "gpkg":console.info("GeoPackage detected:",a.name),d=new FileReader,d.onload=function(a){c.addImportLayer(b,c.map.createLayerGeopackage(a.target.result))},
+d.readAsArrayBuffer(a)}}else alert("No file selected!")};
+netgis.Client.prototype.addImportLayer=function(a,b){this.importCounter||(this.importCounter=0);var c=this.importCounter+1;c="import-"+c;this.importCounter+=1;this.layerTree.addCheckbox(this.importFolder,c,a);this.importFolder.classList.remove("netgis-hide");this.importLayers[c]=b;this.map.setLayerOrder(b,this.map.importLayerID);a=this.config.styles["import"];this.map.setLayerStyleSimple(b,a.fill,a.stroke,a.width);this.map.addLayer(c,b);this.layerTree.setItemChecked(c,!0);this.map.zoomLayer(c);this.importModal.hide()};
+netgis.Client.prototype.onImportServiceClick=function(a){this.importServiceDetails.classList.add("netgis-hide");var b=this.importServiceInput.value;b=b.trim();if(!(1>b.length)){var c=b.indexOf("?");this.importServiceBaseURL=a=-1<c?b.substr(0,c):b;var d=["request=GetCapabilities"];if(-1<c)for(b=b.substr(c+1),b=b.split("&"),c=0;c<b.length;c++){var e=b[c];e=e.toLowerCase();-1<e.search("service")?d.push(e):-1<e.search("version")&&d.push(e)}a=a+"?"+d.join("&");-1===a.search("service=")?(netgis.util.request(a+
+"&service=WMS",this.onImportServiceCapsResponse.bind(this)),netgis.util.request(a+"&service=WFS",this.onImportServiceCapsResponse.bind(this))):netgis.util.request(a,this.onImportServiceCapsResponse.bind(this))}};
+netgis.Client.prototype.onImportServiceCapsResponse=function(a){var b=(new DOMParser).parseFromString(a,"text/xml").documentElement,c=this.importServiceLayerSelect;a=this.importServiceFormatSelect;for(var d=c.options.length-1;0<=d;d--)c.options.remove(d);for(d=a.options.length-1;0<=d;d--)a.options.remove(d);switch(b.nodeName){default:case "HTML":this.importServiceType=null;console.warn("could not detect wms or wfs service",b);break;case "WMS_Capabilities":case "WMT_MS_Capabilities":this.importServiceType=
+"wms";b.getAttribute("version");d=b.getElementsByTagName("Service")[0];d=d.getElementsByTagName("Title")[0].textContent;this.importServiceNameInput.value=d;for(var e=b.getElementsByTagName("Layer"),f=[],g=0;g<e.length;g++){d=e[g];var h=d.getElementsByTagName("Name")[0].textContent,k=d.getElementsByTagName("Title")[0].textContent;f.push({name:h,title:k});d=document.createElement("option");d.text=k;d.value=h;c.options.add(d)}c=b.getElementsByTagName("GetMap")[0].getElementsByTagName("Format");b=[];
+for(g=0;g<c.length;g++)d=c[g],e=d.textContent,b.push(e),d=document.createElement("option"),d.text=e,d.value=e,a.options.add(d);break;case "WFS_Capabilities":case "wfs:WFS_Capabilities":this.importServiceType="wfs";b.getAttribute("version");d=b.getElementsByTagName("ows:ServiceIdentification")[0];d=d.getElementsByTagName("ows:Title")[0].textContent;this.importServiceNameInput.value=d;e=b.getElementsByTagName("FeatureType");f=[];for(g=0;g<e.length;g++)d=e[g],h=d.getElementsByTagName("Name")[0].textContent,
+k=d.getElementsByTagName("Title")[0].textContent,f.push({name:h,title:k}),d=document.createElement("option"),d.text=k,d.value=h,c.options.add(d);b=b.getElementsByTagName("ows:Operation");d=null;for(c=0;c<b.length;c++)if("GetFeature"===b[c].getAttribute("name")){d=b[c];break}b=null;if(d)for(d=d.getElementsByTagName("ows:Parameter"),c=0;c<d.length;c++)if(g=d[c],"outputFormat"===g.getAttribute("name")){c=g.getElementsByTagName("ows:Value");for(g=0;g<c.length;g++)d=c[g],e=d.textContent,d=document.createElement("option"),
+d.text=e,d.value=e,a.options.add(d),-1<e.search("json")&&(b=e);break}b&&(a.value=b)}this.importServiceDetails.classList.remove("netgis-hide")};
+netgis.Client.prototype.onImportServiceAccept=function(a){a=this.importServiceBaseURL;var b=this.importServiceNameInput.value,c=this.importServiceLayerSelect.value,d=this.importServiceFormatSelect.value;switch(this.importServiceType){case "wms":this.addImportLayer(b,this.map.createLayerWMS(a,c,d,!1));break;case "wfs":this.addImportLayer(b,this.map.createLayerWFS(a+"?",c,null,d))}};
+netgis.Client.prototype.onExportShow=function(a){this.exportWidthInput.value=this.map.getWidth();this.exportHeightInput.value=this.map.getHeight();this.exportLandscapeInput.checked=this.exportWidthInput.value>this.exportHeightInput.value;this.toolboxPanel.hide();this.exportModal.show()};
+netgis.Client.prototype.onExportFormatChange=function(a){"pdf"===this.exportFormatSelect.value?(this.exportPaddingInput.parentNode.classList.remove("netgis-hide"),this.exportLandscapeInput.parentNode.classList.remove("netgis-hide")):(this.exportPaddingInput.parentNode.classList.add("netgis-hide"),this.exportLandscapeInput.parentNode.classList.add("netgis-hide"))};
+netgis.Client.prototype.onExportButtonClick=function(a){a=this.exportFormatSelect.value;var b=Number.parseInt(this.exportWidthInput.value),c=Number.parseInt(this.exportHeightInput.value),d=Number.parseInt(this.exportPaddingInput.value);this.map.exportImage(a,b,c,this.exportLandscapeInput.checked,d)};netgis=netgis||{};netgis.Controls=function(){this.initElements()};
+netgis.Controls.prototype.initElements=function(){this.container=document.createElement("section");this.container.className="netgis-controls netgis-color-e netgis-text-a netgis-shadow netgis-round";this.zoomIn=this.createButton("<i class='fas fa-plus'></i>","Zoom +");this.zoomIn.addEventListener("click",this.onZoomInClick.bind(this));this.container.appendChild(this.zoomIn);this.zoomOut=this.createButton("<i class='fas fa-minus'></i>","Zoom -");this.zoomOut.addEventListener("click",this.onZoomOutClick.bind(this));
+this.container.appendChild(this.zoomOut);this.zoomAll=this.createButton("<i class='fas fa-home'></i>","Zoom auf Anfangsausdehung");this.zoomAll.addEventListener("click",this.onZoomAllClick.bind(this));this.container.appendChild(this.zoomAll)};netgis.Controls.prototype.attach=function(a){a.appendChild(this.container)};netgis.Controls.prototype.createButton=function(a,b){var c=document.createElement("button");c.setAttribute("type","button");c.innerHTML=a;c.title=b;c.className="netgis-hover-a";return c};
+netgis.Controls.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-controls netgis-color-e netgis-text-a netgis-hover-a netgis-shadow netgis-round";var a=document.createElement("button");a.setAttribute("type","button");a.innerHTML="<i class='fas fa-search-plus'></i>";a.title="Hineinzoomen";a.addEventListener("click",this.onZoomInClick.bind(this));this.root.appendChild(a);a=document.createElement("button");a.setAttribute("type","button");a.innerHTML="<i class='fas fa-search-minus'></i>";
+a.title="Herauszoomen";a.addEventListener("click",this.onZoomOutClick.bind(this));this.root.appendChild(a);this.client.root.appendChild(this.root)};netgis.Controls.prototype.onZoomInClick=function(a){netgis.util.invoke(this.container,netgis.Events.CONTROLS_ZOOM,1)};netgis.Controls.prototype.onZoomOutClick=function(a){netgis.util.invoke(this.container,netgis.Events.CONTROLS_ZOOM,-1)};
+netgis.Controls.prototype.onZoomAllClick=function(a){netgis.util.invoke(this.container,netgis.Events.CONTROLS_ZOOM_ALL,null)};netgis.Controls.prototype.onSettings=function(a){alert("TODO: settings dialog")};netgis=netgis||{};
+netgis.Events=Object.freeze({PANEL_RESIZE:"panel-resize",PANEL_TOGGLE:"panel-toggle",LAYERS_TOGGLE:"layers-toggle",TOOLBOX_TOGGLE:"toolbox-toggle",CONTROLS_ZOOM:"controls-zoom",CONTROLS_ZOOM_ALL:"controls-zoom-all",MAP_FEATURE_ENTER:"map-feature-enter",MAP_FEATURE_HOVER:"map-feature-hover",MAP_FEATURE_CLICK:"map-feature-click",MAP_FEATURE_LEAVE:"map-feature-leave",PARCELS_RESET:"parcels-reset",PARCELS_FIELDS_RESPONSE:"parcels-fields-response",PARCELS_RESPONSE:"parcels-response",PARCELS_ITEM_ENTER:"parcels-item-enter",
+PARCELS_ITEM_LEAVE:"parcels-item-leave",PARCELS_ITEM_CLICK:"parcels-item-click",PARCELS_ITEM_IMPORT_CLICK:"parcels-item-import-click",SNAP_TOGGLE:"snap-toggle",BUFFER_TOGGLE:"buffer-toggle",TRACING_TOGGLE:"tracing-toggle",EXPORT_SHOW:"export-show",CONTEXT_UPDATE:"CONTEXT_UPDATE",SET_MODE:"SET_MODE",LAYER_LIST_TOGGLE:"LAYER_LIST_TOGGLE",PANEL_SHOW:"PANEL_SHOW",PANEL_HIDE:"PANEL_HIDE",LAYER_SHOW:"LAYER_SHOW",LAYER_HIDE:"LAYER_HIDE",LAYER_CREATED:"LAYER_CREATED",MAP_ZOOM_WKT:"MAP_ZOOM_WKT",MAP_SET_EXTENT:"MAP_SET_EXTENT",
+MAP_CHANGE_ZOOM:"MAP_CHANGE_ZOOM",MAP_UPDATE_STYLE:"MAP_UPDATE_STYLE",MAP_MODE_POINTS:"MAP_MODE_POINTS",MAP_MODE_LINES:"MAP_MODE_LINES",MAP_MODE_POLYGONS:"MAP_MODE_POLYGONS",EDIT_FEATURES_LOADED:"EDIT_FEATURES_LOADED",EDIT_FEATURES_CHANGE:"EDIT_FEATURES_CHANGE",SEARCH_PLACE_REQUEST:"SEARCH_PLACE_REQUEST",SEARCH_PLACE_RESPONSE:"SEARCH_PLACE_RESPONSE",PARCEL_SHOW_PREVIEW:"PARCEL_SHOW_PREVIEW",PARCEL_HIDE_PREVIEW:"PARCEL_HIDE_PREVIEW",BUFFER_CHANGE:"BUFFER_CHANGE",BUFFER_ACCEPT:"BUFFER_ACCEPT",BUFFER_CANCEL:"BUFFER_CANCEL",
+DRAW_BUFFER_ON:"DRAW_BUFFER_ON",DRAW_BUFFER_OFF:"DRAW_BUFFER_OFF",DRAW_BUFFER_RADIUS_CHANGE:"DRAW_BUFFER_RADIUS_CHANGE",DRAW_BUFFER_SEGMENTS_CHANGE:"DRAW_BUFFER_SEGMENTS_CHANGE",SNAP_ON:"SNAP_ON",SNAP_OFF:"SNAP_OFF",TRACING_ON:"TRACING_ON",TRACING_OFF:"TRACING_OFF",IMPORT_SHAPEFILE_SHOW:"IMPORT_SHAPEFILE_SHOW",IMPORT_GEOJSON_SHOW:"IMPORT_GEOJSON_SHOW",IMPORT_GML_SHOW:"IMPORT_GML_SHOW",IMPORT_SPATIALITE_SHOW:"IMPORT_SPATIALITE_SHOW",IMPORT_GEOPACKAGE_SHOW:"IMPORT_GEOPACKAGE_SHOW",IMPORT_SHAPEFILE:"IMPORT_SHAPEFILE",
+IMPORT_GEOJSON:"IMPORT_GEOJSON",IMPORT_GML:"IMPORT_GML",IMPORT_WKT:"IMPORT_WKT",IMPORT_SPATIALITE:"IMPORT_SPATIALITE",IMPORT_GEOPACKAGE:"IMPORT_GEOPACKAGE",EXPORT_PDF_SHOW:"EXPORT_PDF_SHOW",EXPORT_JPEG_SHOW:"EXPORT_JPEG_SHOW",EXPORT_PNG_SHOW:"EXPORT_PNG_SHOW",EXPORT_GIF_SHOW:"EXPORT_GIF_SHOW",EXPORT_PDF:"EXPORT_PDF",EXPORT_JPEG:"EXPORT_JPEG",EXPORT_PNG:"EXPORT_PNG",EXPORT_GIF:"EXPORT_GIF",EXPORT_BEGIN:"EXPORT_BEGIN",EXPORT_END:"EXPORT_END",ADD_SERVICE_SHOW:"ADD_SERVICE_SHOW",ADD_SERVICE_WMS:"ADD_SERVICE_WMS",
+ADD_SERVICE_WFS:"ADD_SERVICE_WFS"});netgis=netgis||{};netgis.LayerTypes=Object.freeze({XYZ:"XYZ",OSM:"OSM",WMS:"WMS",WFS:"WFS",KML:"KML"});netgis=netgis||{};netgis.Map=function(){this.attribution=this.root=this.client=null};netgis.Map.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-map";this.client.root.appendChild(this.root)};netgis=netgis||{};
+netgis.MapOpenLayers=function(a){this.activeLayers={};this.projection=a.map.projection;this.geopackageLibURL=a["import"].geopackageLibURL;this.config=a;this.mode=null;this.toolbars={};this.map=this.view=null;this.layers=[];this.interactions={};this.sketch=this.selected=this.hoverLayer=this.hoverFeature=this.parcelLayer=this.editLayer=this.snapFeatures=this.snap=null;this.editEventsSilent=!1;this.importLayerID=2E4;this.editLayerID=3E4;this.labelFont="4mm Verdana, sans-serif";this.drawBufferRadius=100;
+this.drawBufferSegments=3;this.initElements();this.initMap(a);this.initStyles(a);this.initDefaultLayers();this.initInteractions();this.initEvents()};netgis.MapOpenLayers.prototype.initElements=function(){this.container=document.createElement("section");this.container.className="netgis-map"};netgis.MapOpenLayers.prototype.attach=function(a){a.appendChild(this.container)};netgis.MapOpenLayers.prototype.initEvents=function(){this.container.addEventListener("pointerleave",this.onPointerLeave.bind(this))};
+netgis.MapOpenLayers.prototype.load=function(){netgis.Map.prototype.load.call(this);this.dropTarget=document.createElement("div");this.dropTarget.className="netgis-drop-target netgis-hide";this.dropTarget.innerHTML="Datei hier ablegen!";this.container.appendChild(this.dropTarget);this.container.addEventListener("dragenter",this.onDragEnter.bind(this));this.container.addEventListener("dragover",this.onDragEnter.bind(this));this.container.addEventListener("dragend",this.onDragLeave.bind(this));this.container.addEventListener("dragleave",
+this.onDragLeave.bind(this));this.container.addEventListener("drop",this.onDragDrop.bind(this));this.initMap();this.initDefaultLayers();this.initInteractions();this.client.on(netgis.Events.CONTEXT_UPDATE,this.onContextUpdate.bind(this));this.client.on(netgis.Events.MAP_UPDATE_STYLE,this.onUpdateStyle.bind(this));this.client.on(netgis.Events.EDIT_FEATURES_LOADED,this.onEditFeaturesLoaded.bind(this));this.client.on(netgis.Events.SET_MODE,this.onSetMode.bind(this));this.client.on(netgis.Events.SNAP_ON,
+this.onSnapOn.bind(this));this.client.on(netgis.Events.SNAP_OFF,this.onSnapOff.bind(this));this.client.on(netgis.Events.TRACING_ON,this.onTracingOn.bind(this));this.client.on(netgis.Events.TRACING_OFF,this.onTracingOff.bind(this));this.client.on(netgis.Events.LAYER_SHOW,this.onLayerShow.bind(this));this.client.on(netgis.Events.LAYER_HIDE,this.onLayerHide.bind(this));this.client.on(netgis.Events.MAP_ZOOM_WKT,this.onZoomWKT.bind(this));this.client.on(netgis.Events.MAP_SET_EXTENT,this.onSetExtent.bind(this));
+this.client.on(netgis.Events.MAP_CHANGE_ZOOM,this.onChangeZoom.bind(this));this.client.on(netgis.Events.BUFFER_CHANGE,this.onBufferChange.bind(this));this.client.on(netgis.Events.BUFFER_ACCEPT,this.onBufferAccept.bind(this));this.client.on(netgis.Events.BUFFER_CANCEL,this.onBufferCancel.bind(this));this.client.on(netgis.Events.IMPORT_GEOJSON,this.onImportGeoJSON.bind(this));this.client.on(netgis.Events.IMPORT_GML,this.onImportGML.bind(this));this.client.on(netgis.Events.IMPORT_SHAPEFILE,this.onImportShapefile.bind(this));
+this.client.on(netgis.Events.IMPORT_WKT,this.onImportWKT.bind(this));this.client.on(netgis.Events.IMPORT_SPATIALITE,this.onImportSpatialite.bind(this));this.client.on(netgis.Events.IMPORT_GEOPACKAGE,this.onImportGeopackage.bind(this));this.client.on(netgis.Events.EXPORT_PDF,this.onExportPDF.bind(this));this.client.on(netgis.Events.EXPORT_JPEG,this.onExportJPEG.bind(this));this.client.on(netgis.Events.EXPORT_PNG,this.onExportPNG.bind(this));this.client.on(netgis.Events.EXPORT_GIF,this.onExportGIF.bind(this));
+this.client.on(netgis.Events.PARCEL_SHOW_PREVIEW,this.onParcelShowPreview.bind(this));this.client.on(netgis.Events.PARCEL_HIDE_PREVIEW,this.onParcelHidePreview.bind(this));this.client.on(netgis.Events.ADD_SERVICE_WMS,this.onAddServiceWMS.bind(this));this.client.on(netgis.Events.ADD_SERVICE_WFS,this.onAddServiceWFS.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_ON,this.onDrawBufferOn.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_OFF,this.onDrawBufferOff.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE,
+this.onDrawBufferRadiusChange.bind(this));this.client.on(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,this.onDrawBufferSegmentsChange.bind(this))};
+netgis.MapOpenLayers.prototype.initMap=function(a){"undefined"!==typeof proj4&&(proj4.defs(a.projections),proj4.defs("urn:ogc:def:crs:OGC:1.3:CRS84",proj4.defs("EPSG:4326")),ol.proj.proj4.register(proj4));this.view=new ol.View({projection:a.map.projection,center:a.map.center,minZoom:a.map.minZoom,maxZoom:a.map.maxZoom,zoom:a.map.zoom});this.setPadding(0,0,0,0);this.map=new ol.Map({target:this.container,view:this.view,pixelRatio:1,moveTolerance:5,controls:[]});a.map.scalebar&&(this.scalebar=new ol.control.ScaleLine({bar:!0}),
+this.map.addControl(this.scalebar));this.map.on("pointermove",this.onPointerMove.bind(this));this.map.on("click",this.onSingleClick.bind(this));this.map.on("movestart",this.onMoveStart.bind(this));this.map.on("moveend",this.onMoveEnd.bind(this));this.view.on("change:resolution",this.onChangeResolution.bind(this))};netgis.MapOpenLayers.prototype.initStyles=function(a){a=a.styles.select;this.hoverStyle=this.createStyle(a.fill,a.stroke,a.width);this.hoverStyle.setZIndex(1)};
+netgis.MapOpenLayers.prototype.initDefaultLayers=function(){this.editLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleEdit.bind(this),zIndex:this.editLayerID});this.addLayer(netgis.Client.Layers.EDIT_LAYER,this.editLayer);this.previewLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),style:this.styleSketch.bind(this),zIndex:this.editLayerID+10});this.addLayer(netgis.Client.Layers.PREVIEW_LAYER,this.previewLayer);this.parcelLayer=new ol.layer.Vector({source:new ol.source.Vector({features:[]}),
+style:this.styleParcel.bind(this),zIndex:this.editLayerID+20});this.map.addLayer(this.parcelLayer);this.editEventsOn()};netgis.MapOpenLayers.prototype.editEventsOn=function(){this.editLayer.getSource().on("addfeature",this.onEditLayerAdd.bind(this));this.editLayer.getSource().on("changefeature",this.onEditLayerChange.bind(this));this.editLayer.getSource().on("removefeature",this.onEditLayerRemove.bind(this))};netgis.MapOpenLayers.prototype.editEventsOff=function(){};
 netgis.MapOpenLayers.prototype.initInteractions=function(){this.interactions[netgis.Modes.VIEW]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.PANNING]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.ZOOMING_IN]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.ZOOMING_OUT]=this.interactions[netgis.Modes.VIEW];this.interactions[netgis.Modes.DRAW_POINTS]=[new ol.interaction.Draw({type:"Point",source:this.editLayer.getSource(),
 style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_POINTS][0].on("drawend",this.onDrawPointsEnd.bind(this));this.interactions[netgis.Modes.DRAW_LINES]=[new ol.interaction.Draw({type:"LineString",source:this.editLayer.getSource(),style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.DRAW_LINES][0].on("drawend",this.onDrawLinesEnd.bind(this));
 this.interactions[netgis.Modes.DRAW_POLYGONS]=[new ol.interaction.Draw({type:"Polygon",source:this.editLayer.getSource(),style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURE_BEGIN]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.CUT_FEATURE_DRAW]=[new ol.interaction.Draw({type:"Polygon",style:this.styleSketch.bind(this)}),new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];
-this.interactions[netgis.Modes.CUT_FEATURE_DRAW][0].on("drawend",this.onCutFeatureDrawEnd.bind(this));this.interactions[netgis.Modes.MODIFY_FEATURES]=[new ol.interaction.Modify({source:this.editLayer.getSource(),deleteCondition:ol.events.condition.doubleClick,style:this.styleModify.bind(this)}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.MODIFY_FEATURES][0].on("modifyend",this.onModifyFeaturesEnd.bind(this));this.interactions[netgis.Modes.DELETE_FEATURES]=[new ol.interaction.DragPan,
-new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.BUFFER_FEATURE_BEGIN]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.BUFFER_FEATURE_EDIT]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.snapFeatures=new ol.Collection;this.interactions[netgis.Modes.SEARCH_PLACE]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.SEARCH_PARCEL]=this.interactions[netgis.Modes.VIEW]};
-netgis.MapOpenLayers.prototype.createLayer=function(a){var b=null;switch(a.type){case netgis.LayerTypes.XYZ:b=this.createLayerXYZ(a.url);break;case netgis.LayerTypes.OSM:b=this.createLayerOSM();break;case netgis.LayerTypes.WMS:b=this.createLayerWMS(a.url,a.name,a.format,a.username,a.password);break;case netgis.LayerTypes.WFS:b=this.createLayerWFS(a.url,a.name,this.client.config.map.projection,a.outputFormat)}b&&(a.minZoom&&b.setMinZoom(Number.parseFloat(a.minZoom)-1),a.maxZoom&&b.setMaxZoom(Number.parseFloat(a.maxZoom)));
-return b};netgis.MapOpenLayers.prototype.createLayerXYZ=function(a){return new ol.layer.Tile({source:new ol.source.XYZ({url:a,crossOrigin:"anonymous"})})};netgis.MapOpenLayers.prototype.createLayerOSM=function(){return new ol.layer.Tile({source:new ol.source.XYZ({url:"https://{a-c}.tile.openstreetmap.de/{z}/{x}/{y}.png",crossOrigin:"anonymous"})})};
-netgis.MapOpenLayers.prototype.createLayerWMS=function(a,b,c,d,e){a={url:a,params:{LAYERS:b,FORMAT:c?c:"image/png",TRANSPARENT:"true",VERSION:"1.1.1"},serverType:"mapserver",crossOrigin:"anonymous",hidpi:!1};d&&e&&(a.imageLoadFunction=function(a,b){var c=new XMLHttpRequest;c.open("GET",b);c.setRequestHeader("Authorization","Basic "+window.btoa(d+":"+e));c.onload=function(){a.getImage().src=b};c.send()});a=new ol.source.ImageWMS(a);return new ol.layer.Image({source:a,opacity:1})};
-netgis.MapOpenLayers.prototype.createLayerWFS=function(a,b,c,d){a+="service=WFS&version=1.1.0&request=GetFeature";d=d?netgis.util.replace(d," ","+"):"application/json";var e=new ol.source.Vector({format:new ol.format.GeoJSON,strategy:ol.loadingstrategy.bbox,url:function(e){return a+"&typename="+b+"&srsname="+c+"&bbox="+e.join(",")+","+c+"&outputFormat="+d}}),f=new ol.layer.Vector({source:e}),g=this;e.on("featuresloadstart",function(a){g.removeSnapLayer(f)});e.on("featuresloadend",function(a){window.setTimeout(function(){g.addSnapLayer(f)},
-10)});return f};netgis.MapOpenLayers.prototype.clearAll=function(){for(var a=0;a<this.layers.length;a++)this.map.removeLayer(this.layers[a]);this.layers=[];this.snapFeatures.clear()};netgis.MapOpenLayers.prototype.onUpdateStyle=function(a){a=new ol.style.Style({fill:new ol.style.Fill({color:a.polygon.fill}),stroke:new ol.style.Stroke({color:a.polygon.stroke,width:a.polygon.strokeWidth})});this.editLayer.setStyle(a)};
-netgis.MapOpenLayers.prototype.styleEdit=function(a){var b=this.client.config.styles.editLayer.pointRadius;a=a.getGeometry();b=new ol.style.Style({image:new ol.style.Circle({radius:b,fill:new ol.style.Fill({color:this.client.config.styles.editLayer.stroke})}),fill:new ol.style.Fill({color:this.client.config.styles.editLayer.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.editLayer.stroke,width:this.client.config.styles.editLayer.strokeWidth})});a instanceof ol.geom.Polygon&&(a=
-a.getArea(),b.setText(new ol.style.Text({text:[netgis.util.formatArea(a,!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.client.config.styles.editLayer.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return b};
+this.interactions[netgis.Modes.CUT_FEATURE_DRAW][0].on("drawend",this.onCutFeatureDrawEnd.bind(this));this.interactions[netgis.Modes.MODIFY_FEATURES]=[new ol.interaction.DragPan,new ol.interaction.Modify({source:this.editLayer.getSource(),deleteCondition:ol.events.condition.doubleClick,style:this.styleModify.bind(this)}),new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.MODIFY_FEATURES][0].on("modifyend",this.onModifyFeaturesEnd.bind(this));this.interactions[netgis.Modes.DELETE_FEATURES]=
+[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.BUFFER_FEATURE_BEGIN]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.BUFFER_FEATURE_EDIT]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.snapFeatures=new ol.Collection;this.interactions[netgis.Modes.SEARCH_PLACE]=[new ol.interaction.DragPan,new ol.interaction.MouseWheelZoom];this.interactions[netgis.Modes.SEARCH_PARCEL]=this.interactions[netgis.Modes.VIEW]};
+netgis.MapOpenLayers.prototype.addLayer=function(a,b){b&&(b.set("id",a),this.map.addLayer(b),this.activeLayers[a]=b)};netgis.MapOpenLayers.prototype.removeLayer=function(a){var b=this.activeLayers[a];b&&(this.map.removeLayer(b),delete this.activeLayers[a])};netgis.MapOpenLayers.prototype.createStyle=function(a,b,c){var d={};a&&(d.fill=new ol.style.Fill({color:a}));b&&(d.stroke=new ol.style.Stroke({color:b,width:c?c:3}));return new ol.style.Style(d)};
+netgis.MapOpenLayers.prototype.setLayerStyle=function(a,b){a.setStyle(b)};netgis.MapOpenLayers.prototype.setLayerStyleSimple=function(a,b,c,d){this.setLayerStyle(a,this.createStyle(b,c,d))};netgis.MapOpenLayers.prototype.setLayerStyleEdit=function(a){a.setStyle(this.styleEdit.bind(this))};netgis.MapOpenLayers.prototype.setLayerOrder=function(a,b){a.setZIndex(Number.parseInt(b))};
+netgis.MapOpenLayers.prototype.createLayer=function(a){var b=null;switch(a.type){case netgis.LayerTypes.XYZ:b=this.createLayerXYZ(a.url);break;case netgis.LayerTypes.OSM:b=this.createLayerOSM();break;case netgis.LayerTypes.WMS:b=this.createLayerWMS(a.url,a.name,a.format,a.tiled,a.username,a.password);break;case netgis.LayerTypes.WFS:b=this.createLayerWFS(a.url,a.name,this.projection,a.format,a.username,a.password),(a.fill||a.stroke||a.width)&&b.setStyle(this.createStyle(a.fill,a.stroke,a.width))}b&&
+(a.minZoom&&b.setMinZoom(Number.parseFloat(a.minZoom)),a.maxZoom&&b.setMaxZoom(Number.parseFloat(a.maxZoom)),a.order&&b.setZIndex(Number.parseInt(a.order)));return b};netgis.MapOpenLayers.prototype.createLayerXYZ=function(a){return new ol.layer.Tile({source:new ol.source.XYZ({url:a,crossOrigin:"anonymous"})})};netgis.MapOpenLayers.prototype.createLayerOSM=function(){return new ol.layer.Tile({source:new ol.source.OSM})};
+netgis.MapOpenLayers.prototype.createLayerWMS=function(a,b,c,d,e,f){a={url:a,params:{LAYERS:b,FORMAT:c?c:"image/png",TRANSPARENT:"true",VERSION:"1.1.1"},serverType:"mapserver",crossOrigin:"anonymous",hidpi:!1};e&&f&&(a.imageLoadFunction=function(a,b){var c=new XMLHttpRequest;c.open("GET",b);c.setRequestHeader("Authorization","Basic "+window.btoa(e+":"+f));c.onload=function(){a.getImage().src=b};c.send()});d?(d=new ol.source.TileWMS(a),d=new ol.layer.Tile({source:d})):(d=new ol.source.ImageWMS(a),
+d=new ol.layer.Image({source:d}));return d};
+netgis.MapOpenLayers.prototype.createLayerWFS=function(a,b,c,d,e,f){a+="service=WFS&version=1.1.0&request=GetFeature";c||(c=this.projection);d=d?netgis.util.replace(d," ","+"):"application/json; subtype=geojson";var g=new ol.source.Vector({format:new ol.format.GeoJSON,strategy:ol.loadingstrategy.bbox,loader:function(h,k,n,q,p){h=a+"&typename="+b+"&srsname="+c+"&bbox="+h.join(",")+","+c+"&outputFormat="+d;var l=new XMLHttpRequest;l.open("GET",h);e&&f&&l.setRequestHeader("Authorization","Basic "+window.btoa(e+
+":"+f));l.onerror=function(){console.error("WFS Request Error");p()};l.onload=function(){if(200===l.status){var a=g.getFormat().readFeatures(l.responseText);g.clear();g.addFeatures(a);q(a)}else console.error("WFS Request Status",l.status),p()};l.send()}}),h=new ol.layer.Vector({source:g}),k=this;g.on("featuresloadstart",function(a){k.removeSnapLayer(h)});g.on("featuresloadend",function(a){window.setTimeout(function(){k.addSnapLayer(h)},10)});return h};
+netgis.MapOpenLayers.prototype.clearAll=function(){for(var a=0;a<this.layers.length;a++)this.map.removeLayer(this.layers[a]);this.layers=[];this.snapFeatures.clear()};netgis.MapOpenLayers.prototype.addFeature=function(a,b){a.getSource().addFeature(b)};netgis.MapOpenLayers.prototype.addEditFeature=function(a){this.editLayer.getSource().addFeature(a)};
+netgis.MapOpenLayers.prototype.addEditFeaturesGeoJSON=function(a,b){var c=new ol.format.GeoJSON;c.readProjection(a);a=b?c.readFeatures(a,{featureProjection:this.projection}):c.readFeatures(a);this.editLayer.getSource().addFeatures(a);this.updateSnapFeatures()};netgis.MapOpenLayers.prototype.createFeatureWKT=function(a,b){a=(new ol.format.WKT).readGeometry(a);b.geometry=a;return new ol.Feature(b)};netgis.MapOpenLayers.prototype.createFeatureJSON=function(a){return new ol.Feature(a)};
+netgis.MapOpenLayers.prototype.onUpdateStyle=function(a){a=new ol.style.Style({fill:new ol.style.Fill({color:a.polygon.fill}),stroke:new ol.style.Stroke({color:a.polygon.stroke,width:a.polygon.strokeWidth})});this.editLayer.setStyle(a)};
+netgis.MapOpenLayers.prototype.styleEdit=function(a){var b=a.getGeometry(),c=this.hoverFeature===a,d=c?this.config.styles.select.fill:this.config.styles.editLayer.fill;a=c?this.config.styles.select.stroke:this.config.styles.editLayer.stroke;d=new ol.style.Style({image:new ol.style.Circle({radius:c?this.config.styles.select.pointRadius:this.config.styles.editLayer.pointRadius,fill:new ol.style.Fill({color:a})}),fill:new ol.style.Fill({color:d}),stroke:new ol.style.Stroke({color:a,width:this.config.styles.editLayer.strokeWidth})});
+c&&d.setZIndex(1);b instanceof ol.geom.Polygon&&(b=b.getArea(),d.setText(new ol.style.Text({text:[netgis.util.formatArea(b,!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:a}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return d};
 netgis.MapOpenLayers.prototype.styleSelect=function(a){var b=a.getGeometry();a=new ol.style.Style({image:new ol.style.Circle({radius:this.client.config.styles.select.pointRadius,fill:new ol.style.Fill({color:this.client.config.styles.select.stroke})}),fill:new ol.style.Fill({color:this.client.config.styles.select.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.select.stroke,width:this.client.config.styles.select.strokeWidth})});b instanceof ol.geom.Polygon&&(b=b.getArea(),a.setText(new ol.style.Text({text:[netgis.util.formatArea(b,
 !0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.client.config.styles.select.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return a};
-netgis.MapOpenLayers.prototype.styleModify=function(a){var b=new ol.style.Style({image:new ol.style.Circle({radius:this.client.config.styles.modify.pointRadius,fill:new ol.style.Fill({color:this.client.config.styles.modify.stroke})}),fill:new ol.style.Fill({color:this.client.config.styles.modify.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.modify.stroke,width:this.client.config.styles.modify.strokeWidth})});a=new ol.style.Style({image:new ol.style.Circle({radius:this.client.config.styles.modify.pointRadius,
-fill:new ol.style.Fill({color:this.client.config.styles.modify.stroke})}),geometry:this.getGeometryPoints(a)});return[b,a]};
-netgis.MapOpenLayers.prototype.styleSketch=function(a){var b=a.getGeometry(),c=new ol.style.Style({image:new ol.style.Circle({radius:this.client.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.client.config.styles.sketch.stroke})}),fill:new ol.style.Fill({color:this.client.config.styles.sketch.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.sketch.stroke,width:this.client.config.styles.sketch.strokeWidth})});b instanceof ol.geom.Polygon&&(b=b.getArea(),c.setText(new ol.style.Text({text:[netgis.util.formatArea(b,
-!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.client.config.styles.sketch.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));a=new ol.style.Style({image:new ol.style.Circle({radius:this.client.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.client.config.styles.sketch.stroke})}),geometry:this.getGeometryPoints(a)});return[c,a]};
-netgis.MapOpenLayers.prototype.styleParcel=function(){return new ol.style.Style({fill:new ol.style.Fill({color:this.client.config.styles.parcel.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.parcel.stroke,width:this.client.config.styles.parcel.strokeWidth})})};
+netgis.MapOpenLayers.prototype.styleModify=function(a){var b=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.modify.pointRadius,fill:new ol.style.Fill({color:this.config.styles.modify.stroke})}),fill:new ol.style.Fill({color:this.config.styles.modify.fill}),stroke:new ol.style.Stroke({color:this.config.styles.modify.stroke,width:this.config.styles.modify.strokeWidth})}),c=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.modify.pointRadius,fill:new ol.style.Fill({color:this.config.styles.modify.stroke})}),
+geometry:this.getGeometryPoints(a)});a=a.getGeometry();a instanceof ol.geom.Polygon&&(a=a.getArea(),b.setText(new ol.style.Text({text:[netgis.util.formatArea(a,!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.config.styles.modify.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));return[b,c]};
+netgis.MapOpenLayers.prototype.styleSketch=function(a){var b=a.getGeometry(),c=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke})}),fill:new ol.style.Fill({color:this.config.styles.sketch.fill}),stroke:new ol.style.Stroke({color:this.config.styles.sketch.stroke,width:this.config.styles.sketch.strokeWidth})});b instanceof ol.geom.Polygon&&(b=b.getArea(),c.setText(new ol.style.Text({text:[netgis.util.formatArea(b,
+!0),"4mm sans-serif"],font:this.labelFont,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke}),backgroundFill:new ol.style.Fill({color:"rgba( 255, 255, 255, 0.5 )"}),padding:[2,4,2,4]})));a=new ol.style.Style({image:new ol.style.Circle({radius:this.config.styles.sketch.pointRadius,fill:new ol.style.Fill({color:this.config.styles.sketch.stroke})}),geometry:this.getGeometryPoints(a)});return[c,a]};
+netgis.MapOpenLayers.prototype.styleParcel=function(){return new ol.style.Style({fill:new ol.style.Fill({color:this.client.config.styles.parcel.fill}),stroke:new ol.style.Stroke({color:this.client.config.styles.parcel.stroke,width:this.client.config.styles.parcel.strokeWidth})})};netgis.MapOpenLayers.prototype.redrawVectorLayers=function(){this.map.getLayers().forEach(function(a,b,c){a instanceof ol.layer.Vector&&a.setStyle(a.getStyle())})};
 netgis.MapOpenLayers.prototype.getGeometryPoints=function(a){var b=a.getGeometry();if(b instanceof ol.geom.LineString)return new ol.geom.MultiPoint(b.getCoordinates());if(b instanceof ol.geom.Polygon){a=[];b=b.getCoordinates();for(var c=0;c<b.length;c++)for(var d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiPolygon){a=[];for(var f=b.getPolygons(),g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);
 return new ol.geom.MultiPoint(a)}if(b instanceof ol.geom.MultiLineString){a=[];f=b.getPolygons();for(g=0;g<f.length;g++)for(b=f[g].getCoordinates(),c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++)a.push(d[e]);return new ol.geom.MultiPoint(a)}return b};netgis.MapOpenLayers.prototype.getActiveVectorLayers=function(){for(var a=[],b=this.map.getLayers().getArray(),c=this.layers,d=0;d<c.length;d++){var e=c[d];e instanceof ol.layer.Vector&&-1<b.indexOf(e)&&a.push(e)}return a};
-netgis.MapOpenLayers.prototype.setMode=function(a){switch(this.mode){case netgis.Modes.BUFFER_FEATURE_EDIT:this.onBufferCancel(null);break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.onDrawBufferOff(null)}this.map.getInteractions().clear();var b=this.interactions[a];if(b)for(var c=0;c<b.length;c++)this.map.addInteraction(b[c]);this.snap&&(a===netgis.Modes.DRAW_POINTS||a===netgis.Modes.DRAW_LINES||a===netgis.Modes.DRAW_POLYGONS)&&this.map.addInteraction(this.snap);switch(a){default:this.editLayer.setStyle(this.styleEdit.bind(this));
-break;case netgis.Modes.MODIFY_FEATURES:this.editLayer.setStyle(this.styleModify.bind(this))}this.mode&&this.root.classList.remove(this.getModeClassName(this.mode));a&&this.root.classList.add(this.getModeClassName(a));this.mode=a};netgis.MapOpenLayers.prototype.getModeClassName=function(a){a=a.toLowerCase();a=netgis.util.replace(a,"_","-");return"netgis-mode-"+a};
-netgis.MapOpenLayers.prototype.setSnapOn=function(){this.snap=new ol.interaction.Snap({features:this.snapFeatures});this.map.addInteraction(this.snap);this.snapFeatures.changed()};netgis.MapOpenLayers.prototype.setSnapOff=function(){this.snap&&(this.map.removeInteraction(this.snap),this.snap=null)};
-netgis.MapOpenLayers.prototype.setTracingOn=function(){var a=new ol.source.Vector({features:this.snapFeatures});this.tracing=new ol.interaction.Draw({type:"Polygon",source:this.editLayer.getSource(),style:this.styleSketch.bind(this),trace:!0,traceSource:a});a=this.interactions[netgis.Modes.DRAW_POLYGONS];a[0].setActive(!1);a.push(this.tracing);this.setMode(this.mode)};
+netgis.MapOpenLayers.prototype.setMode=function(a){switch(this.mode){case netgis.Modes.BUFFER_FEATURE_EDIT:this.onBufferCancel(null);break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:var b=this.drawBufferOn;this.onDrawBufferOff(null);this.drawBufferOn=b;break;case netgis.Modes.MODIFY_FEATURES:this.editLayer.setStyle(this.styleEdit.bind(this))}this.container.classList.remove("netgis-cursor-draw");this.container.classList.remove("netgis-clickable");switch(a){case netgis.Modes.DRAW_POINTS:this.container.classList.add("netgis-cursor-draw");
+this.updateSnapFeatures();if(this.drawBufferOn)this.onDrawBufferOn();break;case netgis.Modes.DRAW_LINES:this.container.classList.add("netgis-cursor-draw");this.updateSnapFeatures();if(this.drawBufferOn)this.onDrawBufferOn();break;case netgis.Modes.DRAW_POLYGONS:this.container.classList.add("netgis-cursor-draw");this.updateSnapFeatures();break;case netgis.Modes.MODIFY_FEATURES:this.editLayer.setStyle(this.styleModify.bind(this))}this.map.getInteractions().clear();(b=this.interactions[a])||(b=this.interactions[netgis.Modes.VIEW]);
+for(var c=0;c<b.length;c++)this.map.addInteraction(b[c]);this.snap&&(a===netgis.Modes.DRAW_POINTS||a===netgis.Modes.DRAW_LINES||a===netgis.Modes.DRAW_POLYGONS)&&this.map.addInteraction(this.snap);this.mode=a};netgis.MapOpenLayers.prototype.getModeClassName=function(a){a=a.toLowerCase();a=netgis.util.replace(a,"_","-");return"netgis-mode-"+a};netgis.MapOpenLayers.prototype.setSnapOn=function(){this.snap=new ol.interaction.Snap({features:this.snapFeatures});this.map.addInteraction(this.snap);this.snapFeatures.changed()};
+netgis.MapOpenLayers.prototype.setSnapOff=function(){this.snap&&(this.map.removeInteraction(this.snap),this.snap=null)};netgis.MapOpenLayers.prototype.setTracingOn=function(){var a=new ol.source.Vector({features:this.snapFeatures});this.tracing=new ol.interaction.Draw({type:"Polygon",source:this.editLayer.getSource(),style:this.styleSketch.bind(this),trace:!0,traceSource:a});a=this.interactions[netgis.Modes.DRAW_POLYGONS];a[0].setActive(!1);a.push(this.tracing);this.setMode(this.mode)};
 netgis.MapOpenLayers.prototype.setTracingOff=function(){var a=this.interactions[netgis.Modes.DRAW_POLYGONS];a[0].setActive(!0);a.splice(a.indexOf(this.tracing),1);this.setMode(this.mode)};netgis.MapOpenLayers.prototype.addSnapLayer=function(a){a=a.getSource().getFeatures();for(var b=0;b<a.length;b++)this.snapFeatures.push(a[b])};netgis.MapOpenLayers.prototype.removeSnapLayer=function(a){a=a.getSource().getFeatures();for(var b=0;b<a.length;b++)this.snapFeatures.remove(a[b])};
+netgis.MapOpenLayers.prototype.updateSnapFeatures=function(){this.snapFeatures.clear();var a=this;this.map.getLayers().forEach(function(b,c,d){c=b.get("id");c!==netgis.Client.Layers.PARCEL_DISTRICTS&&c!==netgis.Client.Layers.PARCEL_FIELDS&&c!==netgis.Client.Layers.PARCEL_FEATURES&&b instanceof ol.layer.Vector&&a.addSnapLayer(b)})};
+netgis.MapOpenLayers.prototype.zoomExtent=function(a,b,c,d){a=ol.proj.fromLonLat([a,b],this.projection);c=ol.proj.fromLonLat([c,d],this.projection);this.view.fit([a[0],a[1],c[0],c[1]])};netgis.MapOpenLayers.prototype.zoomWKT=function(a){a=(new ol.format.WKT).readGeometry(a);this.view.fit(a,{duration:300})};
+netgis.MapOpenLayers.prototype.zoomGeoJSON=function(a){a=(new ol.format.GeoJSON).readFeatures(a);for(var b=a[0].getGeometry().getExtent(),c=1;c<a.length;c++)ol.extent.extend(b,a[c].getGeometry().getExtent());this.view.fit(b,{duration:300})};netgis.MapOpenLayers.prototype.zoomLayer=function(a){a=this.activeLayers[a].getSource().getExtent();this.view.fit(a,{duration:300})};netgis.MapOpenLayers.prototype.zoomFeature=function(a){this.view.fit(a.getGeometry(),{duration:300})};
+netgis.MapOpenLayers.prototype.zoom=function(a){this.view.animate({zoom:this.view.getZoom()+a,duration:200})};netgis.MapOpenLayers.prototype.zoomLevel=function(a){this.view.animate({zoom:a,center:this.view.getCenter(),duration:300})};netgis.MapOpenLayers.prototype.zoomAll=function(){var a=this.config.map;this.view.animate({zoom:a.zoom,center:a.center,duration:500})};netgis.MapOpenLayers.prototype.setPadding=function(a,b,c,d){this.view.padding=[a+40,b+40,c+40,d+40]};
 netgis.MapOpenLayers.prototype.onSnapOn=function(a){this.setSnapOn()};netgis.MapOpenLayers.prototype.onSnapOff=function(a){this.setSnapOff()};netgis.MapOpenLayers.prototype.onTracingOn=function(a){this.setTracingOn()};netgis.MapOpenLayers.prototype.onTracingOff=function(a){this.setTracingOff()};netgis.MapOpenLayers.prototype.onLayerShow=function(a){if(a=this.layers[a.id])this.map.addLayer(a),a instanceof ol.layer.Vector&&this.addSnapLayer(a)};
 netgis.MapOpenLayers.prototype.onLayerHide=function(a){if(a=this.layers[a.id])this.map.removeLayer(a),a instanceof ol.layer.Vector&&this.removeSnapLayer(a)};
-netgis.MapOpenLayers.prototype.onContextUpdate=function(a){this.clearAll();var b=a.bbox;if(b){if(netgis.util.isDefined(this.client.config.map)&&netgis.util.isDefined(this.client.config.map.projection)){var c=ol.proj.fromLonLat([b[0],b[1]],this.client.config.map.projection);var d=ol.proj.fromLonLat([b[2],b[3]],this.client.config.map.projection)}else c=ol.proj.fromLonLat([b[0],b[1]]),d=ol.proj.fromLonLat([b[2],b[3]]);b[0]=c[0];b[1]=c[1];b[2]=d[0];b[3]=d[1];this.view.fit(b)}for(b=0;b<a.layers.length;b++)if(c=
-this.createLayer(a.layers[b]))c.setZIndex(a.layers.length-b),this.layers[b]=c};netgis.MapOpenLayers.prototype.onAddServiceWMS=function(a){var b=this.createLayerWMS(a.url,a.name,a.format);b.setZIndex(a.id);this.layers[a.id]=b};netgis.MapOpenLayers.prototype.onAddServiceWFS=function(a){var b=this.createLayerWFS(a.url,a.name,this.client.config.map.projection,a.format);b.setZIndex(a.id);this.layers[a.id]=b};netgis.MapOpenLayers.prototype.onSetMode=function(a){this.setMode(a)};
+netgis.MapOpenLayers.prototype.onContextUpdate=function(a){this.clearAll();if(a=a.bbox){if(netgis.util.isDefined(this.client.config.map)&&netgis.util.isDefined(this.client.config.map.projection)){var b=ol.proj.fromLonLat([a[0],a[1]],this.client.config.map.projection);var c=ol.proj.fromLonLat([a[2],a[3]],this.client.config.map.projection)}else b=ol.proj.fromLonLat([a[0],a[1]]),c=ol.proj.fromLonLat([a[2],a[3]]);a[0]=b[0];a[1]=b[1];a[2]=c[0];a[3]=c[1];this.view.fit(a)}};
+netgis.MapOpenLayers.prototype.onAddServiceWMS=function(a){var b=this.createLayerWMS(a.url,a.name,a.format);b.setZIndex(a.id);this.layers[a.id]=b};netgis.MapOpenLayers.prototype.onAddServiceWFS=function(a){var b=this.createLayerWFS(a.url,a.name,this.client.config.map.projection,a.format);b.setZIndex(a.id);this.layers[a.id]=b};netgis.MapOpenLayers.prototype.onSetMode=function(a){this.setMode(a)};
 netgis.MapOpenLayers.prototype.onSetExtent=function(a){var b=ol.proj.fromLonLat([a.minx,a.miny],this.client.config.map.projection);a=ol.proj.fromLonLat([a.maxx,a.maxy],this.client.config.map.projection);this.view.fit([b[0],b[1],a[0],a[1]])};netgis.MapOpenLayers.prototype.onChangeZoom=function(a){this.view.animate({zoom:this.view.getZoom()+a,duration:200})};netgis.MapOpenLayers.prototype.onZoomWKT=function(a){a=(new ol.format.WKT).readGeometry(a);this.view.fit(a,{duration:300,padding:[40,40,40,40]})};
-netgis.MapOpenLayers.prototype.onPointerMove=function(a){a=a.pixel;var b=this.hover,c=this.styleSelect.bind(this);b&&(b.setStyle(this.styleEdit.bind(this)),b=null);var d=this;switch(this.mode){case netgis.Modes.DELETE_FEATURES:this.map.forEachFeatureAtPixel(a,function(a,f){f===d.editLayer&&(b=a,a.setStyle(c));return!0});break;case netgis.Modes.CUT_FEATURE_BEGIN:this.map.forEachFeatureAtPixel(a,function(a,f){f===d.editLayer&&(b=a,a.setStyle(c));return!0});break;case netgis.Modes.BUFFER_FEATURE_BEGIN:this.map.forEachFeatureAtPixel(a,
-function(a,f){f===d.editLayer&&(b=a,a.setStyle(c));return!0});break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.updateDrawBufferPreview()}this.hover=b};
-netgis.MapOpenLayers.prototype.onSingleClick=function(a){switch(this.mode){case netgis.Modes.DELETE_FEATURES:this.hover&&(this.editLayer.getSource().removeFeature(this.hover),this.hover=null);break;case netgis.Modes.CUT_FEATURE_BEGIN:this.hover&&(this.selected=this.hover,this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.CUT_FEATURE_DRAW));break;case netgis.Modes.BUFFER_FEATURE_BEGIN:this.hover&&(this.selected=this.hover,this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_EDIT))}};
+netgis.MapOpenLayers.prototype.onPointerMove=function(a){var b=a.pixel;a=a.coordinate;var c=null,d=null;this.map.forEachFeatureAtPixel(b,function(a,b){if(b){if(-1!==b.get("id").search("import-"))return!1;c=a;d=b;return!0}});switch(this.mode){default:return!0;case netgis.Modes.PARCEL_SELECT:case netgis.Modes.DELETE_FEATURES:case netgis.Modes.CUT_FEATURE_BEGIN:case netgis.Modes.BUFFER_FEATURE_BEGIN:break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:return this.updateDrawBufferPreview(),
+!0}c!==this.hoverFeature&&(this.hoverFeature&&this.featureLeave(this.hoverFeature,this.hoverLayer,b,a),c&&this.featureEnter(c,d,b,a),this.redrawVectorLayers(),this.hoverFeature=c,this.hoverLayer=d);c&&this.featureHover(c,d,b,a)};netgis.MapOpenLayers.prototype.onPointerLeave=function(a){this.hoverFeature&&(this.featureLeave(this.hoverFeature,this.hoverLayer,[a.offsetX,a.offsetY],null),this.hoverLayer=this.hoverFeature=null)};
+netgis.MapOpenLayers.prototype.featureEnter=function(a,b,c,d){b&&(this.container.classList.add("netgis-clickable"),b.get("id")!==netgis.Client.Layers.EDIT_LAYER&&-1===b.get("id").search("import-")&&a.setStyle(this.hoverStyle),netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_ENTER,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()}))};netgis.MapOpenLayers.prototype.featureHover=function(a,b,c,d){};
+netgis.MapOpenLayers.prototype.featureLeave=function(a,b,c,d){b&&(this.container.classList.remove("netgis-clickable"),b.get("id")!==netgis.Client.Layers.EDIT_LAYER&&a.setStyle(null),netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_LEAVE,{pixel:c,coords:d,layer:b.get("id"),properties:a.getProperties()}))};netgis.MapOpenLayers.prototype.findFeature=function(a,b,c){if(a=this.activeLayers[a]){a=a.getSource().getFeatures();for(var d=null,e=0;e<a.length;e++){var f=a[e];if(f.get(b)===c){d=f;break}}return d}};
+netgis.MapOpenLayers.prototype.setFeatureHover=function(a,b){a.setStyle(b?this.hoverStyle:null)};netgis.MapOpenLayers.prototype.onPointerMove_01=function(a){a=a.pixel;var b=this.hoverFeature,c=this;switch(this.mode){case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.updateDrawBufferPreview()}b=null;this.map.forEachFeatureAtPixel(a,function(a,e){e===c.editLayer&&(b=a);return!0});b!==this.hoverFeature&&this.redrawVectorLayers();this.hoverFeature=b};
+netgis.MapOpenLayers.prototype.onSingleClick=function(a){switch(this.mode){default:this.hoverFeature&&this.hoverLayer&&(a={pixel:a.pixel,coords:a.coordinate,layer:this.hoverLayer.get("id"),id:this.hoverFeature.getId(),properties:this.hoverFeature.getProperties()},netgis.util.invoke(this.container,netgis.Events.MAP_FEATURE_CLICK,a));break;case netgis.Modes.DELETE_FEATURES:this.hoverFeature&&(this.editLayer.getSource().removeFeature(this.hoverFeature),this.featureLeave(this.hoverFeature,this.editLayer),
+this.hoverFeature=null,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.VIEW));break;case netgis.Modes.CUT_FEATURE_BEGIN:this.hoverFeature&&(this.selected=this.hoverFeature,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.CUT_FEATURE_DRAW));break;case netgis.Modes.BUFFER_FEATURE_BEGIN:this.hoverFeature&&(this.selected=this.hoverFeature,netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_EDIT))}};
 netgis.MapOpenLayers.prototype.onMoveStart=function(a){};netgis.MapOpenLayers.prototype.onMoveEnd=function(a){};netgis.MapOpenLayers.prototype.onChangeResolution=function(a){};
-netgis.MapOpenLayers.prototype.onCutFeatureDrawEnd=function(a){var b=a.feature;if(a=this.selected){var c=new jsts.io.OL3Parser,d=c.read(a.getGeometry());b=c.read(b.getGeometry());d=d.difference(b);c=c.write(d);c=new ol.Feature({geometry:c});d=this.editLayer.getSource();d.removeFeature(a);d.addFeature(c);this.selected=c}this.editEventsSilent=!0;this.splitMultiPolygons(this.editLayer);this.editEventsSilent=!1;this.updateEditOutput()};
+netgis.MapOpenLayers.prototype.onCutFeatureDrawEnd=function(a){var b=a.feature;if(a=this.selected){var c=new jsts.io.OL3Parser,d=c.read(a.getGeometry());b=c.read(b.getGeometry());d=d.difference(b);c=c.write(d);c=new ol.Feature({geometry:c});d=this.editLayer.getSource();d.removeFeature(a);d.addFeature(c);this.selected=c}this.editEventsSilent=!0;this.splitMultiPolygons(this.editLayer);this.editEventsSilent=!1;this.updateEditOutput();netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.VIEW)};
 netgis.MapOpenLayers.prototype.onModifyFeaturesEnd=function(a){this.updateEditOutput();this.updateEditArea()};netgis.MapOpenLayers.prototype.createBufferFeature=function(a,b,c){a=this.createBufferGeometry(a,b,c);return new ol.Feature({geometry:a})};netgis.MapOpenLayers.prototype.createBufferGeometry=function(a,b,c){var d=new jsts.io.OL3Parser;a=d.read(a).buffer(b,c);return d.write(a)};
 netgis.MapOpenLayers.prototype.onBufferChange=function(a){var b=this.editLayer.getSource(),c=this.selected;this.sketch&&b.removeFeature(this.sketch);c&&(a=this.createBufferFeature(c.getGeometry(),a.radius,a.segments),b.addFeature(a),this.sketch=a)};netgis.MapOpenLayers.prototype.onBufferAccept=function(a){this.selected&&this.sketch&&this.editLayer.getSource().removeFeature(this.selected);this.selected=this.sketch=null};
-netgis.MapOpenLayers.prototype.onBufferCancel=function(a){this.sketch&&(this.editLayer.getSource().removeFeature(this.sketch),this.sketch=null);this.selected=null};netgis.MapOpenLayers.prototype.onDrawPointsEnd=function(a){(a=this.previewLayer.getSource().getFeatures()[0])&&this.editLayer.getSource().addFeature(a.clone())};netgis.MapOpenLayers.prototype.onDrawLinesEnd=function(a){(a=this.previewLayer.getSource().getFeatures()[0])&&this.editLayer.getSource().addFeature(a.clone())};
-netgis.MapOpenLayers.prototype.onDrawBufferOn=function(a){a=this.createBufferFeature(new ol.geom.Point(this.client.config.map.center),this.drawBufferRadius,this.drawBufferSegments);this.previewLayer.getSource().addFeature(a)};netgis.MapOpenLayers.prototype.onDrawBufferOff=function(a){this.previewLayer.getSource().clear()};netgis.MapOpenLayers.prototype.onDrawBufferRadiusChange=function(a){this.drawBufferRadius=a;this.updateDrawBufferPreview()};
-netgis.MapOpenLayers.prototype.onDrawBufferSegmentsChange=function(a){this.drawBufferSegments=a;this.updateDrawBufferPreview()};netgis.MapOpenLayers.prototype.updateDrawBufferPreview=function(){var a=this.interactions[this.mode][0].getOverlay().getSource().getFeatures();if(!(1>a.length)){var b=this.previewLayer.getSource().getFeatures()[0];b&&(a=a[0].getGeometry(),a=this.createBufferGeometry(a,this.drawBufferRadius,this.drawBufferSegments),b.setGeometry(a))}};
-netgis.MapOpenLayers.prototype.onEditLayerAdd=function(a){this.updateEditLayerItem();this.updateEditOutput();this.snapFeatures.push(a.feature)};netgis.MapOpenLayers.prototype.onEditLayerRemove=function(a){this.updateEditOutput();this.snapFeatures.remove(a.feature)};netgis.MapOpenLayers.prototype.onEditLayerChange=function(a){this.updateEditOutput()};
-netgis.MapOpenLayers.prototype.updateEditOutput=function(){var a=this.editLayer.getSource().getFeatures(),b=this.client.config.map.projection,c=(new ol.format.GeoJSON).writeFeaturesObject(a,{dataProjection:b,featureProjection:b});c.crs={type:"name",properties:{name:"urn:ogc:def:crs:"+b.replace(":","::")}};for(var d=b=0;d<a.length;d++){var e=a[d].getGeometry();e instanceof ol.geom.Polygon&&(b+=e.getArea())}c.area=b;this.editEventsSilent||this.client.invoke(netgis.Events.EDIT_FEATURES_CHANGE,c)};
-netgis.MapOpenLayers.prototype.updateEditLayerItem=function(){var a=this.editLayerID;this.layers[a]||(this.layers[a]=this.editLayer,this.client.invoke(netgis.Events.LAYER_CREATED,{id:a,title:"Zeichnung",checked:!0,folder:"draw"}))};netgis.MapOpenLayers.prototype.updateEditArea=function(){};netgis.MapOpenLayers.prototype.onEditFeaturesLoaded=function(a){var b=this;window.setTimeout(function(){b.createLayerGeoJSON("Import",a)},10)};
-netgis.MapOpenLayers.prototype.onDragEnter=function(a){a.preventDefault();this.dropTarget.classList.remove("netgis-hide");return!1};netgis.MapOpenLayers.prototype.onDragLeave=function(a){this.dropTarget.classList.add("netgis-hide");return!1};
+netgis.MapOpenLayers.prototype.onBufferCancel=function(a){this.sketch&&(this.editLayer.getSource().removeFeature(this.sketch),this.sketch=null);this.selected=null};netgis.MapOpenLayers.prototype.onDrawPointsEnd=function(a){var b=this.previewLayer.getSource().getFeatures()[0];if(b){var c=this.editLayer.getSource();c.addFeature(b.clone());window.setTimeout(function(){c.removeFeature(a.feature)},10)}};
+netgis.MapOpenLayers.prototype.onDrawLinesEnd=function(a){var b=this.previewLayer.getSource().getFeatures()[0];if(b){var c=this.editLayer.getSource();c.addFeature(b.clone());window.setTimeout(function(){c.removeFeature(a.feature)},10)}};netgis.MapOpenLayers.prototype.onDrawBufferOn=function(a){a=this.createBufferFeature(new ol.geom.Point(this.config.map.center),this.drawBufferRadius,this.drawBufferSegments);this.previewLayer.getSource().addFeature(a);this.drawBufferOn=!0};
+netgis.MapOpenLayers.prototype.onDrawBufferOff=function(a){this.previewLayer.getSource().clear();this.drawBufferOn=!1};netgis.MapOpenLayers.prototype.onDrawBufferRadiusChange=function(a){this.drawBufferRadius=a;this.updateDrawBufferPreview()};netgis.MapOpenLayers.prototype.onDrawBufferSegmentsChange=function(a){this.drawBufferSegments=a;this.updateDrawBufferPreview()};
+netgis.MapOpenLayers.prototype.updateDrawBufferPreview=function(){var a=this.interactions[this.mode][0].getOverlay().getSource().getFeatures();if(!(1>a.length)){var b=this.previewLayer.getSource().getFeatures()[0];b&&(a=a[0].getGeometry(),a=this.createBufferGeometry(a,this.drawBufferRadius,this.drawBufferSegments),b.setGeometry(a))}};netgis.MapOpenLayers.prototype.onEditLayerAdd=function(a){this.updateEditLayerItem();this.updateEditOutput();this.snapFeatures.push(a.feature)};
+netgis.MapOpenLayers.prototype.onEditLayerRemove=function(a){this.updateEditOutput();this.snapFeatures.remove(a.feature)};netgis.MapOpenLayers.prototype.onEditLayerChange=function(a){this.updateEditOutput()};
+netgis.MapOpenLayers.prototype.updateEditOutput=function(){var a=this.editLayer.getSource().getFeatures(),b=this.projection,c=(new ol.format.GeoJSON).writeFeaturesObject(a,{dataProjection:b,featureProjection:b});c.crs={type:"name",properties:{name:"urn:ogc:def:crs:"+b.replace(":","::")}};for(var d=b=0;d<a.length;d++){var e=a[d].getGeometry();e instanceof ol.geom.Polygon&&(b+=e.getArea())}c.area=b;this.editEventsSilent||netgis.util.invoke(this.container,netgis.Events.EDIT_FEATURES_CHANGE,c)};
+netgis.MapOpenLayers.prototype.updateEditLayerItem=function(){var a=this.editLayerID;this.activeLayers[a]||(this.activeLayers[a]=this.editLayer,netgis.util.invoke(this.container,netgis.Events.LAYER_CREATED,{id:a,title:"Zeichnung",checked:!0,folder:"draw"}))};netgis.MapOpenLayers.prototype.updateEditArea=function(){};
+netgis.MapOpenLayers.prototype.onEditFeaturesLoaded=function(a){var b=this;console.info("Edit Features Loaded:",a);window.setTimeout(function(){b.addLayer("import",b.createLayerGeoJSON(a,!0))},10)};netgis.MapOpenLayers.prototype.onDragEnter=function(a){a.preventDefault();this.dropTarget.classList.remove("netgis-hide");return!1};netgis.MapOpenLayers.prototype.onDragLeave=function(a){this.dropTarget.classList.add("netgis-hide");return!1};
 netgis.MapOpenLayers.prototype.onDragDrop=function(a){console.info("Drag Drop");this.dropTarget.classList.add("netgis-hide");a.preventDefault();a=a.dataTransfer.files[0];var b=new FileReader;b.onload=this.onDragLoad.bind(this);console.log("File:",a);b.readAsArrayBuffer(a);return!1};netgis.MapOpenLayers.prototype.onDragLoad=function(a){console.log("On Load:",a.target);this.loadShape(a.target.result)};netgis.MapOpenLayers.prototype.loadShape=function(a){var b=this;shp(a).then(function(a){b.onShapeLoad(a)})};
 netgis.MapOpenLayers.prototype.onShapeLoad=function(a){console.info("Shapefile To Geojson:",a);a=(new ol.format.GeoJSON({dataProjection:"EPSG:4326",featureProjection:"EPSG:3857"})).readFeatures(a);this.importLayer.getSource().addFeatures(a);this.view.fit(this.importLayer.getSource().getExtent(),{})};netgis.MapOpenLayers.prototype.onImportGeoJSON=function(a){var b=a.name,c=this,d=new FileReader;d.onload=function(a){c.createLayerGeoJSON(b,a.target.result)};d.readAsText(a)};
 netgis.MapOpenLayers.prototype.onImportGML=function(a){var b=a.name,c=this,d=new FileReader;d.onload=function(a){c.createLayerGML(b,a.target.result)};d.readAsText(a)};netgis.MapOpenLayers.prototype.onImportShapefile=function(a){var b=a.name,c=this,d=new FileReader;d.onload=function(a){c.createLayerShapefile(b,a.target.result)};d.readAsArrayBuffer(a)};
 netgis.MapOpenLayers.prototype.onImportSpatialite=function(a){var b=a.name,c=this,d=new FileReader;d.onload=function(a){c.createLayerSpatialite(b,a.target.result)};d.readAsArrayBuffer(a)};netgis.MapOpenLayers.prototype.onImportGeopackage=function(a){var b=a.name,c=this,d=new FileReader;d.onload=function(a){c.createLayerGeopackage(b,a.target.result)};d.readAsArrayBuffer(a)};
-netgis.MapOpenLayers.prototype.createLayerGeoJSON=function(a,b){var c=new ol.format.GeoJSON;a=c.readProjection(b);b=c.readFeatures(b,{featureProjection:this.client.config.map.projection});a=a.getCode();switch(a){case "EPSG:3857":case "EPSG:4326":case this.client.config.map.projection:break;default:console.warn("Unsupported Import Projection:",a)}this.addImportedFeatures(b)};
-netgis.MapOpenLayers.prototype.createLayerGML=function(a,b){console.warn("GML support is experimental!");a=[];b=(new DOMParser).parseFromString(b,"text/xml").getElementsByTagName("gml:featureMember");for(var c=0;c<b.length;c++){for(var d={},e=b[c].children[0],f=0;f<e.attributes.length;f++){var g=e.attributes[f];d[g.nodeName]=g.nodeValue}for(f=0;f<e.children.length;f++)if(g=e.children[f],"ogr:geometryProperty"!==g.nodeName){var h=g.nodeName.split(":");d[h[h.length-1]]=g.innerHTML}e=e.getElementsByTagName("ogr:geometryProperty")[0].children[0];
-(f=e.getAttribute("srsName"))&&"EPSG:4326"!==f&&f!==this.client.config.map.projection&&console.warn("Unsupported Import Projection:",f);switch(e.nodeName){case "gml:Polygon":d.geometry=this.gmlParsePolygon(e,f);break;case "gml:MultiPolygon":d.geometry=this.gmlParseMultiPolygon(e,f)}d=new ol.Feature(d);a.push(d)}this.addImportedFeatures(a)};
+netgis.MapOpenLayers.prototype.createLayerGeoJSON=function(a,b){var c=new ol.format.GeoJSON,d=c.readProjection(a);a=b?c.readFeatures(a,{featureProjection:this.projection}):c.readFeatures(a);d=d.getCode();switch(d){case "EPSG:3857":case "EPSG:4326":case this.projection:break;default:console.warn("Unsupported Import Projection:",d)}return new ol.layer.Vector({source:new ol.source.Vector({features:a})})};
+netgis.MapOpenLayers.prototype.createLayerWKT=function(a){for(var b=new ol.format.WKT,c=[],d=0;d<a.length;d++){var e=a[d],f=b.readGeometry(e.geometry);e.geometry=f;f=new ol.Feature(e);c.push(f)}return new ol.layer.Vector({source:new ol.source.Vector({features:c})})};netgis.MapOpenLayers.prototype.createLayerVector=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})});a&&b.setZIndex(a);return b};
+netgis.MapOpenLayers.prototype.createLayerGML=function(a){console.warn("GML support is experimental!");var b=[];a=(new DOMParser).parseFromString(a,"text/xml").getElementsByTagName("gml:featureMember");for(var c=0;c<a.length;c++){for(var d={},e=a[c].children[0],f=0;f<e.attributes.length;f++){var g=e.attributes[f];d[g.nodeName]=g.nodeValue}for(f=0;f<e.children.length;f++)if(g=e.children[f],"ogr:geometryProperty"!==g.nodeName){var h=g.nodeName.split(":");d[h[h.length-1]]=g.innerHTML}e=e.getElementsByTagName("ogr:geometryProperty")[0].children[0];
+(f=e.getAttribute("srsName"))&&"EPSG:4326"!==f&&f!==this.projection&&console.warn("Unsupported Import Projection:",f);switch(e.nodeName){case "gml:Polygon":d.geometry=this.gmlParsePolygon(e,f);break;case "gml:MultiPolygon":d.geometry=this.gmlParseMultiPolygon(e,f)}d=new ol.Feature(d);b.push(d)}return new ol.layer.Vector({source:new ol.source.Vector({features:b})})};
 netgis.MapOpenLayers.prototype.gmlParsePolygon=function(a,b){var c=[];a=a.getElementsByTagName("gml:LinearRing");for(var d=0;d<a.length;d++){var e=a[d].getElementsByTagName("gml:coordinates")[0].innerHTML;c.push(this.gmlParseCoordinates(e,b))}return new ol.geom.Polygon(c)};
-netgis.MapOpenLayers.prototype.gmlParseMultiPolygon=function(a,b){var c=[];a=a.getElementsByTagName("gml:polygonMember");for(var d=0;d<a.length;d++){var e=a[d].getElementsByTagName("gml:Polygon")[0];c.push(this.gmlParsePolygon(e,b))}return new ol.geom.MultiPolygon(c)};netgis.MapOpenLayers.prototype.gmlParseCoordinates=function(a,b){a=a.split(" ");for(var c=0;c<a.length;c++){a[c]=a[c].split(",");for(var d=0;d<a[c].length;d++)a[c][d]=Number.parseFloat(a[c][d]);b&&(a[c]=ol.proj.transform(a[c],b,this.client.config.map.projection))}return a};
-netgis.MapOpenLayers.prototype.createLayerShapefile=function(a,b){var c=this;shp(b).then(function(a){var b=new ol.format.GeoJSON;b.readProjection(a);a=b.readFeatures(a,{featureProjection:c.client.config.map.projection});c.addImportedFeatures(a)})};
-netgis.MapOpenLayers.prototype.createLayerSpatialite=function(a,b){var c=this;window.initSqlJs().then(function(a){var d=[],f=new Uint8Array(b);a=new a.Database(f);var g=a.exec("SELECT name FROM sqlite_schema WHERE type = 'table' \n\t\t\t\t\tAND name NOT LIKE 'sqlite_%' \n\t\t\t\t\tAND name NOT LIKE 'sql_%' \n\t\t\t\t\tAND name NOT LIKE 'idx_%' \n\t\t\t\t\tAND name NOT LIKE 'spatial_ref_sys%' \n\t\t\t\t\tAND name NOT LIKE 'spatialite_%' \n\t\t\t\t\tAND name NOT LIKE 'geometry_columns%' \n\t\t\t\t\tAND name NOT LIKE 'views_%' \n\t\t\t\t\tAND name NOT LIKE 'virts_%' \n\t\t\t\t\tAND name NOT LIKE 'SpatialIndex' \n\t\t\t\t\tAND name NOT LIKE 'ElementaryGeometries' \n\t\t\t\t;");f=
-g[0].values;for(var h=0;h<f.length;h++){g=a.exec("SELECT * FROM "+f[h][0]);var k=g[0];g=null;for(var l=0;l<k.columns.length;l++){if("geometry"===k.columns[l].toLowerCase()){g=l;break}if("geom"===k.columns[l].toLowerCase()){g=l;break}}k=k.values;for(l=0;l<k.length;l++){var m=k[l][g],n=new Uint8Array(m.length-43-1+5);n[0]=m[1];n[1]=m[39];n[2]=m[40];n[3]=m[41];n[4]=m[42];for(var p=m.length-43-1,q=0;q<p;q++)n[5+q]=m[43+q];m=(new ol.format.WKB).readGeometry(n,{featureProjection:c.client.config.map.projection});
-d.push(new ol.Feature({geometry:m}))}}c.addImportedFeatures(d)})};
-netgis.MapOpenLayers.prototype.createLayerGeopackage=function(a,b){var c=this;a=new Uint8Array(b);window.GeoPackage.setSqljsWasmLocateFile(function(a){return c.client.config.import.geopackageLibURL+a});window.GeoPackage.GeoPackageAPI.open(a).then(function(a){for(var b=[],d=new ol.format.GeoJSON,g=a.getFeatureTables(),h=0;h<g.length;h++)for(var k=a.queryForGeoJSONFeaturesInTable(g[h]),l=0;l<k.length;l++){var m=d.readGeometry(k[l].geometry,{featureProjection:c.client.config.map.projection});m=new ol.Feature({geometry:m});
-b.push(m)}c.addImportedFeatures(b)})};netgis.MapOpenLayers.prototype.addImportedFeatures=function(a){this.editEventsSilent=!0;this.editLayer.getSource().addFeatures(a);this.editEventsSilent=!1;this.updateEditOutput();if(0<a.length){for(var b=a[0].getGeometry().getExtent(),c=1;c<a.length;c++)ol.extent.extend(b,a[c].getGeometry().getExtent());this.view.fit(b,{duration:300,padding:[40,40,40,40]})}};
-netgis.MapOpenLayers.prototype.onImportWKT=function(a){a=(new ol.format.WKT).readGeometry(a);a=new ol.Feature({geometry:a});this.addImportedFeatures([a])};netgis.MapOpenLayers.prototype.onExportPDF=function(a){this.exportImage("pdf",a.resx,a.resy,a.mode,a.margin)};netgis.MapOpenLayers.prototype.onExportJPEG=function(a){this.exportImage("jpeg",a.resx,a.resy)};netgis.MapOpenLayers.prototype.onExportPNG=function(a){this.exportImage("png",a.resx,a.resy)};
-netgis.MapOpenLayers.prototype.onExportGIF=function(a){this.exportImage("gif",a.resx,a.resy)};netgis.MapOpenLayers.prototype.onParcelShowPreview=function(a){a=(new ol.format.WKT).readGeometry(a.geom);a=new ol.Feature({geometry:a});this.parcelLayer.getSource().clear();this.parcelLayer.getSource().addFeature(a)};netgis.MapOpenLayers.prototype.onParcelHidePreview=function(a){this.parcelLayer.getSource().clear()};netgis.MapOpenLayers.prototype.getWidth=function(){return this.map.getSize()[0]};
-netgis.MapOpenLayers.prototype.getHeight=function(){return this.map.getSize()[1]};
-netgis.MapOpenLayers.prototype.exportImage=function(a,b,c,d,e){this.client.invoke(netgis.Events.EXPORT_BEGIN,null);var f=this,g=this.root,h=this.map,k=this.client.config,l=new Image;l.onload=function(){var m=document.createElement("div");m.style.position="fixed";m.style.top="0px";m.style.left="0px";m.style.width=b+"px";m.style.height=c+"px";m.style.background="white";m.style.zIndex=-1;m.style.opacity=0;m.style.pointerEvents="none";g.appendChild(m);h.setTarget(m);h.once("rendercomplete",function(){var n=
-document.createElement("canvas");n.width=b;n.height=c;var p=n.getContext("2d");p.webkitImageSmoothingEnabled=!1;p.mozImageSmoothingEnabled=!1;p.imageSmoothingEnabled=!1;Array.prototype.forEach.call(document.querySelectorAll(".ol-layer canvas"),function(a){if(0<a.width){var b=a.parentNode.style.opacity;p.globalAlpha=""===b?1:Number(b);b=a.style.transform.match(/^matrix\(([^\(]*)\)$/)[1].split(",").map(Number);CanvasRenderingContext2D.prototype.setTransform.apply(p,b);p.drawImage(a,0,0)}});p.drawImage(l,
-0,0);p.fillStyle="#fff";p.fillRect(0,n.height-30,140,30);p.fillStyle="#000";p.font="4mm sans-serif";p.fillText(netgis.util.getTimeStamp(),10,n.height-10);var q=document.createElement("a");switch(a){case "pdf":e=e?e:0;var r=297-e-e,v=210-e-e,t=n.width/n.height;if(!d){var w=r;r=v;v=w}if(n.height>n.width){var u=v;w=u*t;w>r&&(w=r,u=w/t)}else w=r,u=w/t,u>v&&(u=v,w=u*t);t=new jsPDF(d?"l":"p");var x=e;x+=(r-w)/2;r=e;r+=(v-u)/2;t.addImage(n.toDataURL("image/png,1.0",1),"PNG",x,r,w,u);t.setFillColor(255,255,
-255);t.rect(x,r+u-11,80,11,"F");t.setFontSize(8);t.text("Datum: "+netgis.util.getTimeStamp(),x+2,r+u-2-4);t.text("Quelle: "+window.location.href,x+2,r+u-2);n=t.output("bloburl",{filename:k.export.defaultFilename+".pdf"});window.open(n,"_blank");break;case "jpeg":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".jpg"):(q.setAttribute("download",k.export.defaultFilename+".jpg"),q.setAttribute("href",n.toDataURL("image/jpeg",1)),q.click());break;case "png":window.navigator.msSaveBlob?
-window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".png"):(q.setAttribute("download",k.export.defaultFilename+".png"),q.setAttribute("href",n.toDataURL("image/png",1)),q.click());break;case "gif":q.setAttribute("download",k.export.defaultFilename+".gif"),v=new GIF({workerScript:k.export.gifWebWorker,quality:1}),v.addFrame(n),v.on("finished",function(a){q.setAttribute("href",window.URL.createObjectURL(a));q.click()}),v.render()}h.setTarget(g);g.removeChild(m);f.client.invoke(netgis.Events.EXPORT_END,
-null)});h.renderSync()};l.src=k.export.logo};netgis.MapOpenLayers.prototype.splitMultiPolygons=function(a){a=a.getSource();for(var b=a.getFeatures(),c=[],d=[],e=0;e<b.length;e++){var f=b[e],g=f.getGeometry();if(g instanceof ol.geom.MultiPolygon){g=g.getPolygons();for(var h=0;h<g.length;h++){var k=new ol.Feature({geometry:g[h]});d.push(k)}c.push(f)}}for(e=0;e<c.length;e++)a.removeFeature(c[e]);a.addFeatures(d)};netgis=netgis||{};netgis.Menu=function(){this.root=this.client=null;this.sections=[]};
-netgis.Menu.prototype.load=function(){this.root=document.createElement("header");this.root.className="netgis-menu netgis-primary netgis-shadow";var a=document.createElement("div");this.root.appendChild(a);var b=this.createButton('Ebenen<i class="fab fa-buffer"></i>',!0);b.addEventListener("click",this.onToggleClick.bind(this));a.appendChild(b);b=this.createButton('Suche<i class="fas fa-search" style="position: relative; top: 0.3mm;"></i>',!0);b.addEventListener("click",this.onSearchPlaceClick.bind(this));
-a.appendChild(b);b=this.createButton('Flurst\u00fccke<i class="fas fa-vector-square" style="position: relative; top: 0.3mm;"></i>',!0);b.addEventListener("click",this.onSearchParcelClick.bind(this));a.appendChild(b);if(this.client.editable){b=this.createMenu('<i class="fas fa-caret-down"></i>Zeichnen');var c=b.getElementsByTagName("ul")[0];a.appendChild(b);c.appendChild(this.createMenuItem('<i class="fas fa-map-marker-alt"></i>Punkte',this.onDrawPointClick.bind(this)));c.appendChild(this.createMenuItem('<i class="fas fa-minus"></i>Linien',
-this.onDrawLineClick.bind(this)));c.appendChild(this.createMenuItem('<i class="fas fa-vector-square"></i>Polygone',this.onDrawPolygonClick.bind(this)));b=this.createMenu('<i class="fas fa-caret-down"></i>Bearbeiten');c=b.getElementsByTagName("ul")[0];a.appendChild(b);c.appendChild(this.createMenuItem('<i class="fas fa-cut"></i>Ausschneiden',this.onCutFeatureClick.bind(this)));c.appendChild(this.createMenuItem('<i class="fas fa-arrows-alt"></i>Verschieben',this.onModifyFeaturesClick.bind(this)));c.appendChild(this.createMenuItem('<i class="fas fa-eraser"></i>L\u00f6schen',
-this.onDeleteFeaturesClick.bind(this)));c.appendChild(this.createMenuItem('<i class="far fa-dot-circle"></i>Puffern',this.onBufferFeatureClick.bind(this)));b=this.createMenu('<i class="fas fa-caret-down"></i>Import');a.appendChild(b);b=b.getElementsByTagName("ul")[0];b.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoJSON',this.onImportGeoJSONClick.bind(this)));b.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GML',this.onImportGMLClick.bind(this)));b.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Shapefile',
-this.onImportShapefileClick.bind(this)));b.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Spatialite',this.onImportSpatialiteClick.bind(this)));b.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoPackage',this.onImportGeopackageClick.bind(this)));b=this.createMenu('<i class="fas fa-caret-down"></i>Export');a.appendChild(b);a=b.getElementsByTagName("ul")[0];a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>PDF',this.onExportPDFClick.bind(this)));a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>JPEG',
-this.onExportJPEGClick.bind(this)));a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>PNG',this.onExportPNGClick.bind(this)));a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GIF',this.onExportGIFClick.bind(this)))}this.client.root.appendChild(this.root)};netgis.Menu.prototype.createButton=function(a,b){var c=document.createElement("button");c.setAttribute("type","button");c.className="netgis-primary netgis-hover-primary";b&&(c.className+=" netgis-right");c.innerHTML=a;return c};
+netgis.MapOpenLayers.prototype.gmlParseMultiPolygon=function(a,b){var c=[];a=a.getElementsByTagName("gml:polygonMember");for(var d=0;d<a.length;d++){var e=a[d].getElementsByTagName("gml:Polygon")[0];c.push(this.gmlParsePolygon(e,b))}return new ol.geom.MultiPolygon(c)};netgis.MapOpenLayers.prototype.gmlParseCoordinates=function(a,b){a=a.split(" ");for(var c=0;c<a.length;c++){a[c]=a[c].split(",");for(var d=0;d<a[c].length;d++)a[c][d]=Number.parseFloat(a[c][d]);b&&(a[c]=ol.proj.transform(a[c],b,this.projection))}return a};
+netgis.MapOpenLayers.prototype.createLayerShapefile=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;shp(a).then(function(a){var d=new ol.format.GeoJSON;d.readProjection(a);a=d.readFeatures(a,{featureProjection:c.projection});b.getSource().addFeatures(a)});return b};
+netgis.MapOpenLayers.prototype.createLayerSpatialite=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;window.initSqlJs().then(function(d){var e=[],f=new Uint8Array(a);d=new d.Database(f);var g=d.exec("SELECT name FROM sqlite_schema WHERE type = 'table' \n\t\t\t\t\tAND name NOT LIKE 'sqlite_%' \n\t\t\t\t\tAND name NOT LIKE 'sql_%' \n\t\t\t\t\tAND name NOT LIKE 'idx_%' \n\t\t\t\t\tAND name NOT LIKE 'spatial_ref_sys%' \n\t\t\t\t\tAND name NOT LIKE 'spatialite_%' \n\t\t\t\t\tAND name NOT LIKE 'geometry_columns%' \n\t\t\t\t\tAND name NOT LIKE 'views_%' \n\t\t\t\t\tAND name NOT LIKE 'virts_%' \n\t\t\t\t\tAND name NOT LIKE 'SpatialIndex' \n\t\t\t\t\tAND name NOT LIKE 'ElementaryGeometries' \n\t\t\t\t;");
+f=g[0].values;for(var h=0;h<f.length;h++){g=d.exec("SELECT * FROM "+f[h][0]);var k=g[0];g=null;for(var l=0;l<k.columns.length;l++){if("geometry"===k.columns[l].toLowerCase()){g=l;break}if("geom"===k.columns[l].toLowerCase()){g=l;break}}k=k.values;for(l=0;l<k.length;l++){var m=k[l][g],n=new Uint8Array(m.length-43-1+5);n[0]=m[1];n[1]=m[39];n[2]=m[40];n[3]=m[41];n[4]=m[42];for(var q=m.length-43-1,p=0;p<q;p++)n[5+p]=m[43+p];m=(new ol.format.WKB).readGeometry(n,{featureProjection:c.projection});e.push(new ol.Feature({geometry:m}))}}b.getSource().addFeatures(e)});
+return b};
+netgis.MapOpenLayers.prototype.createLayerGeopackage=function(a){var b=new ol.layer.Vector({source:new ol.source.Vector({features:[]})}),c=this;a=new Uint8Array(a);window.GeoPackage.setSqljsWasmLocateFile(function(a){return c.geopackageLibURL+a});window.GeoPackage.GeoPackageAPI.open(a).then(function(a){for(var d=[],f=new ol.format.GeoJSON,g=a.getFeatureTables(),h=0;h<g.length;h++)for(var k=a.queryForGeoJSONFeaturesInTable(g[h]),l=0;l<k.length;l++){var m=f.readGeometry(k[l].geometry,{featureProjection:c.projection});m=
+new ol.Feature({geometry:m});d.push(m)}b.getSource().addFeatures(d)});return b};netgis.MapOpenLayers.prototype.addImportedFeatures=function(a){this.editEventsSilent=!0;this.editLayer.getSource().addFeatures(a);this.editEventsSilent=!1;this.updateEditOutput()};netgis.MapOpenLayers.prototype.onImportWKT=function(a){a=(new ol.format.WKT).readGeometry(a);a=new ol.Feature({geometry:a});this.addImportedFeatures([a])};
+netgis.MapOpenLayers.prototype.onExportPDF=function(a){this.exportImage("pdf",a.resx,a.resy,a.mode,a.margin)};netgis.MapOpenLayers.prototype.onExportJPEG=function(a){this.exportImage("jpeg",a.resx,a.resy)};netgis.MapOpenLayers.prototype.onExportPNG=function(a){this.exportImage("png",a.resx,a.resy)};netgis.MapOpenLayers.prototype.onExportGIF=function(a){this.exportImage("gif",a.resx,a.resy)};
+netgis.MapOpenLayers.prototype.onParcelShowPreview=function(a){a=(new ol.format.WKT).readGeometry(a.geom);a=new ol.Feature({geometry:a});this.parcelLayer.getSource().clear();this.parcelLayer.getSource().addFeature(a)};netgis.MapOpenLayers.prototype.onParcelHidePreview=function(a){this.parcelLayer.getSource().clear()};netgis.MapOpenLayers.prototype.getWidth=function(){return this.map.getSize()[0]};netgis.MapOpenLayers.prototype.getHeight=function(){return this.map.getSize()[1]};
+netgis.MapOpenLayers.prototype.exportImage=function(a,b,c,d,e){netgis.util.invoke(this.container,netgis.Events.EXPORT_BEGIN,null);var f=this,g=this.container,h=this.map,k=this.config,l=new Image;l.onload=function(){var m=document.createElement("div");m.style.position="fixed";m.style.top="0px";m.style.left="0px";m.style.width=b+"px";m.style.height=c+"px";m.style.background="white";m.style.zIndex=-1;m.style.opacity=0;m.style.pointerEvents="none";g.appendChild(m);h.setTarget(m);h.once("rendercomplete",
+function(){var n=document.createElement("canvas");n.width=b;n.height=c;var q=n.getContext("2d");q.webkitImageSmoothingEnabled=!1;q.mozImageSmoothingEnabled=!1;q.imageSmoothingEnabled=!1;Array.prototype.forEach.call(document.querySelectorAll(".ol-layer canvas"),function(a){if(0<a.width){var b=a.parentNode.style.opacity;q.globalAlpha=""===b?1:Number(b);b=a.style.transform.match(/^matrix\(([^\(]*)\)$/)[1].split(",").map(Number);CanvasRenderingContext2D.prototype.setTransform.apply(q,b);q.drawImage(a,
+0,0)}});q.drawImage(l,0,0);q.fillStyle="#fff";q.fillRect(0,n.height-30,140,30);q.fillStyle="#000";q.font="4mm sans-serif";q.fillText(netgis.util.getTimeStamp(),10,n.height-10);var p=document.createElement("a");switch(a){case "pdf":e=e?e:0;var r=297-e-e,v=210-e-e,t=n.width/n.height;if(!d){var w=r;r=v;v=w}if(n.height>n.width){var u=v;w=u*t;w>r&&(w=r,u=w/t)}else w=r,u=w/t,u>v&&(u=v,w=u*t);t=new jsPDF(d?"l":"p");var x=e;x+=(r-w)/2;r=e;r+=(v-u)/2;t.addImage(n.toDataURL("image/png,1.0",1),"PNG",x,r,w,u);
+t.setFillColor(255,255,255);t.rect(x,r+u-11,80,11,"F");t.setFontSize(8);t.text("Datum: "+netgis.util.getTimeStamp(),x+2,r+u-2-4);t.text("Quelle: "+window.location.href,x+2,r+u-2);n=t.output("bloburl",{filename:k.export.defaultFilename+".pdf"});window.open(n,"_blank");break;case "jpeg":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".jpg"):(p.setAttribute("download",k.export.defaultFilename+".jpg"),p.setAttribute("href",n.toDataURL("image/jpeg",1)),p.click());
+break;case "png":window.navigator.msSaveBlob?window.navigator.msSaveBlob(n.msToBlob(),k.export.defaultFilename+".png"):(p.setAttribute("download",k.export.defaultFilename+".png"),p.setAttribute("href",n.toDataURL("image/png",1)),p.click());break;case "gif":p.setAttribute("download",k.export.defaultFilename+".gif"),v=new GIF({workerScript:k.export.gifWebWorker,quality:1}),v.addFrame(n),v.on("finished",function(a){p.setAttribute("href",window.URL.createObjectURL(a));p.click()}),v.render()}h.setTarget(g);
+g.removeChild(m);netgis.util.invoke(f.container,netgis.Events.EXPORT_END,null)});h.renderSync()};l.src=k.export.logo};netgis.MapOpenLayers.prototype.splitMultiPolygons=function(a){a=a.getSource();for(var b=a.getFeatures(),c=[],d=[],e=0;e<b.length;e++){var f=b[e],g=f.getGeometry();if(g instanceof ol.geom.MultiPolygon){g=g.getPolygons();for(var h=0;h<g.length;h++){var k=new ol.Feature({geometry:g[h]});d.push(k)}c.push(f)}}for(e=0;e<c.length;e++)a.removeFeature(c[e]);a.addFeatures(d)};netgis=netgis||{};netgis.Menu=function(){this.root=this.client=null;this.sections=[]};
+netgis.Menu.prototype.load=function(){this.root=document.createElement("header");this.root.className="netgis-menu netgis-color-a netgis-shadow";var a=document.createElement("div");this.root.appendChild(a);var b=this.createButton('<i class="fab fa-buffer"></i><span>Inhalte</span>',!0);b.addEventListener("click",this.onToggleClick.bind(this));a.appendChild(b);b=this.createButton('<i class="fas fa-tools"></i><span>Werkzeuge</span>',!0);b.addEventListener("click",this.onToolboxClick.bind(this));a.appendChild(b);
+b=this.createButton('<i class="fas fa-vector-square"></i><span>Flurst\u00fccke</span>',!0);b.addEventListener("click",this.onSearchParcelClick.bind(this));a.appendChild(b);b=this.createButton('<i class="fas fa-search"></i><span>Suche</span>',!0);b.addEventListener("click",this.onSearchPlaceClick.bind(this));a.appendChild(b);this.client.editable&&(a=this.createMenu('<i class="fas fa-caret-down"></i>Zeichnen').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-map-marker-alt"></i>Punkte',
+this.onDrawPointClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-minus"></i>Linien',this.onDrawLineClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-vector-square"></i>Polygone',this.onDrawPolygonClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Bearbeiten').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-cut"></i>Ausschneiden',this.onCutFeatureClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-arrows-alt"></i>Verschieben',
+this.onModifyFeaturesClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-eraser"></i>L\u00f6schen',this.onDeleteFeaturesClick.bind(this))),a.appendChild(this.createMenuItem('<i class="far fa-dot-circle"></i>Puffern',this.onBufferFeatureClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Import').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoJSON',this.onImportGeoJSONClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GML',
+this.onImportGMLClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Shapefile',this.onImportShapefileClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>Spatialite',this.onImportSpatialiteClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GeoPackage',this.onImportGeopackageClick.bind(this))),a=this.createMenu('<i class="fas fa-caret-down"></i>Export').getElementsByTagName("ul")[0],a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>PDF',
+this.onExportPDFClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>JPEG',this.onExportJPEGClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>PNG',this.onExportPNGClick.bind(this))),a.appendChild(this.createMenuItem('<i class="fas fa-file"></i>GIF',this.onExportGIFClick.bind(this))));this.client.root.appendChild(this.root)};
+netgis.Menu.prototype.createButton=function(a,b){var c=document.createElement("button");c.setAttribute("type","button");c.className="netgis-color-a netgis-hover-c";b&&(c.className+=" netgis-right");c.innerHTML=a;return c};
 netgis.Menu.prototype.createMenu=function(a){var b=document.createElement("div");b.className="netgis-dropdown";var c=document.createElement("button");c.setAttribute("type","button");c.className="netgis-primary netgis-hover-primary";c.innerHTML=a;b.appendChild(c);a=document.createElement("ul");a.className="netgis-dropdown-content netgis-dialog netgis-shadow";b.appendChild(a);return b};
-netgis.Menu.prototype.createMenuItem=function(a,b){var c=document.createElement("li");c.className="netgis-hover-light";var d=document.createElement("button");d.setAttribute("type","button");d.innerHTML=a;d.addEventListener("click",b);c.appendChild(d);return c};netgis.Menu.prototype.onToggleClick=function(a){this.client.invoke(netgis.Events.LAYER_LIST_TOGGLE,null)};netgis.Menu.prototype.onDrawPointClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.DRAW_POINTS)};
+netgis.Menu.prototype.createMenuItem=function(a,b){var c=document.createElement("li");c.className="netgis-hover-light";var d=document.createElement("button");d.setAttribute("type","button");d.innerHTML=a;d.addEventListener("click",b);c.appendChild(d);return c};netgis.Menu.prototype.onToggleClick=function(a){netgis.util.invoke(this.root,netgis.Events.LAYERS_TOGGLE)};netgis.Menu.prototype.onDrawPointClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.DRAW_POINTS)};
 netgis.Menu.prototype.onDrawLineClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.DRAW_LINES)};netgis.Menu.prototype.onDrawPolygonClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.DRAW_POLYGONS)};netgis.Menu.prototype.onCutFeatureClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.CUT_FEATURE_BEGIN)};netgis.Menu.prototype.onModifyFeaturesClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.MODIFY_FEATURES)};
-netgis.Menu.prototype.onDeleteFeaturesClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.DELETE_FEATURES)};netgis.Menu.prototype.onBufferFeatureClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_BEGIN)};netgis.Menu.prototype.onSearchPlaceClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.SEARCH_PLACE)};netgis.Menu.prototype.onSearchParcelClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.SEARCH_PARCEL)};
-netgis.Menu.prototype.onSearchDataClick=function(a){alert("TODO: data search interface")};netgis.Menu.prototype.onImportOWSClick=function(a){alert("TODO: ows import interface, try setting url parameter '?ows=<url>'")};netgis.Menu.prototype.onImportShapefileClick=function(a){this.client.invoke(netgis.Events.IMPORT_SHAPEFILE_SHOW,null)};netgis.Menu.prototype.onImportGeoJSONClick=function(a){this.client.invoke(netgis.Events.IMPORT_GEOJSON_SHOW,null)};netgis.Menu.prototype.onImportKMLClick=function(a){alert("TODO: kml import interface")};
-netgis.Menu.prototype.onImportGMLClick=function(a){this.client.invoke(netgis.Events.IMPORT_GML_SHOW,null)};netgis.Menu.prototype.onImportSpatialiteClick=function(a){this.client.invoke(netgis.Events.IMPORT_SPATIALITE_SHOW,null)};netgis.Menu.prototype.onImportGeopackageClick=function(a){this.client.invoke(netgis.Events.IMPORT_GEOPACKAGE_SHOW,null)};netgis.Menu.prototype.onExportPDFClick=function(a){this.client.invoke(netgis.Events.EXPORT_PDF_SHOW,null)};
-netgis.Menu.prototype.onExportJPEGClick=function(a){this.client.invoke(netgis.Events.EXPORT_JPEG_SHOW,null)};netgis.Menu.prototype.onExportPNGClick=function(a){this.client.invoke(netgis.Events.EXPORT_PNG_SHOW,null)};netgis.Menu.prototype.onExportGIFClick=function(a){this.client.invoke(netgis.Events.EXPORT_GIF_SHOW,null)};netgis=netgis||{};netgis.Modal=function(){this.addService=this.exportGIF=this.exportPNG=this.exportJPEG=this.exportPDF=this.importShapefile=this.importGML=this.importGeoJSON=this.client=null;this.addServiceID=1E4};
-netgis.Modal.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-modal";this.root.addEventListener("click",this.onRootClick.bind(this));this.importGeoJSON=this.createImportGeoJSON();this.root.appendChild(this.importGeoJSON);this.importGML=this.createImportGML();this.root.appendChild(this.importGML);this.importShapefile=this.createImportShapefile();this.root.appendChild(this.importShapefile);this.importSpatialite=this.createImportSpatialite();this.root.appendChild(this.importSpatialite);
-this.importGeopackage=this.createImportGeopackage();this.root.appendChild(this.importGeopackage);this.exportPDF=this.createExportPDF();this.root.appendChild(this.exportPDF);this.exportJPEG=this.createExportJPEG();this.root.appendChild(this.exportJPEG);this.exportPNG=this.createExportPNG();this.root.appendChild(this.exportPNG);this.exportGIF=this.createExportGIF();this.root.appendChild(this.exportGIF);this.addService=this.createAddService();this.root.appendChild(this.addService);this.client.root.appendChild(this.root);
-this.client.on(netgis.Events.IMPORT_GEOJSON_SHOW,this.onImportGeoJSONShow.bind(this));this.client.on(netgis.Events.IMPORT_GML_SHOW,this.onImportGMLShow.bind(this));this.client.on(netgis.Events.IMPORT_SHAPEFILE_SHOW,this.onImportShapefileShow.bind(this));this.client.on(netgis.Events.IMPORT_SPATIALITE_SHOW,this.onImportSpatialiteShow.bind(this));this.client.on(netgis.Events.IMPORT_GEOPACKAGE_SHOW,this.onImportGeopackageShow.bind(this));this.client.on(netgis.Events.EXPORT_PDF_SHOW,this.onExportPDFShow.bind(this));
-this.client.on(netgis.Events.EXPORT_JPEG_SHOW,this.onExportJPEGShow.bind(this));this.client.on(netgis.Events.EXPORT_PNG_SHOW,this.onExportPNGShow.bind(this));this.client.on(netgis.Events.EXPORT_GIF_SHOW,this.onExportGIFShow.bind(this));this.client.on(netgis.Events.ADD_SERVICE_SHOW,this.onAddServiceShow.bind(this))};
-netgis.Modal.prototype.createImportGeoJSON=function(){var a=this.createContainer("Import GeoJSON");this.createText(a,"Unterst\u00fctzte Koordinatensysteme:","<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>");this.createInputFile(a,"Datei ausw\u00e4hlen / ablegen:",".geojson,.json",this.onImportGeoJSONChange.bind(this));this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Importieren",this.onImportGeoJSONAccept.bind(this));return a};
-netgis.Modal.prototype.createImportGML=function(){var a=this.createContainer("Import GML");this.createText(a,"Unterst\u00fctzte Koordinatensysteme:","<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>");this.createInputFile(a,"Datei ausw\u00e4hlen / ablegen:",".gml,.xml",this.onImportGMLChange.bind(this));this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Importieren",this.onImportGMLAccept.bind(this));return a};
-netgis.Modal.prototype.createImportShapefile=function(){var a=this.createContainer("Import Shapefile");this.createText(a,"Unterst\u00fctzte Koordinatensysteme:","<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>");this.createInputFile(a,"Datei ausw\u00e4hlen / ablegen:","application/zip",this.onImportShapefileChange.bind(this));this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Importieren",this.onImportShapefileAccept.bind(this));
-return a};
-netgis.Modal.prototype.createImportSpatialite=function(){var a=this.createContainer("Import Spatialite");this.createText(a,"Unterst\u00fctzte Koordinatensysteme:","<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>");this.createInputFile(a,"Datei ausw\u00e4hlen / ablegen:",".sqlite",this.onImportSpatialiteChange.bind(this));this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Importieren",this.onImportSpatialiteAccept.bind(this));return a};
-netgis.Modal.prototype.createImportGeopackage=function(){var a=this.createContainer("Import GeoPackage");this.createText(a,"Unterst\u00fctzte Koordinatensysteme:","<ul><li>World Geodetic System 1984 (EPSG:4326)</li><li>ETRS89 / UTM zone 32N (EPSG:25832)</li></ul>");this.createInputFile(a,"Datei ausw\u00e4hlen / ablegen:",".gpkg",this.onImportGeopackageChange.bind(this));this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Importieren",this.onImportGeopackageAccept.bind(this));return a};
-netgis.Modal.prototype.createExportPDF=function(){var a=this.createContainer("Export PDF");this.createInputInteger(a,"Breite (Pixel):",800,0,4096);this.createInputInteger(a,"H\u00f6he (Pixel):",600,0,4096);this.createInputInteger(a,"Seitenr\u00e4nder (Millimeter):",10,0,100);this.createInputCheckbox(a,"Querformat:",!0);this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Exportieren",this.onExportPDFAccept.bind(this));return a};
-netgis.Modal.prototype.createExportJPEG=function(){var a=this.createContainer("Export JPEG");this.createInputInteger(a,"Breite (Pixel):",800,0,4096);this.createInputInteger(a,"H\u00f6he (Pixel):",600,0,4096);this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Exportieren",this.onExportJPEGAccept.bind(this));return a};
-netgis.Modal.prototype.createExportPNG=function(){var a=this.createContainer("Export PNG");this.createInputInteger(a,"Breite (Pixel):",800,0,4096);this.createInputInteger(a,"H\u00f6he (Pixel):",600,0,4096);this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Exportieren",this.onExportPNGAccept.bind(this));return a};
-netgis.Modal.prototype.createExportGIF=function(){var a=this.createContainer("Export GIF");this.createInputInteger(a,"Breite (Pixel):",800,0,4096);this.createInputInteger(a,"H\u00f6he (Pixel):",600,0,4096);this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Exportieren",this.onExportGIFAccept.bind(this));return a};
-netgis.Modal.prototype.createAddService=function(){var a=this.createContainer("Dienst hinzuf\u00fcgen");this.createInputText(a,"WMS/WFS URL:");this.createSpace(a);this.createButton(a,"<i class='fas fa-cloud-download-alt'></i>Dienst laden",this.onAddServiceLoad.bind(this));this.createSpace(a);this.createInputHidden(a);this.createText(a,"Bezeichnung:","");this.createInputSelect(a,"Kartenebene:",[]);this.createInputSelect(a,"Format:",[]);this.createSpace(a);this.createButton(a,"<i class='fas fa-check'></i>Dienst hinzuf\u00fcgen",
-this.onAddServiceAccept.bind(this));return a};netgis.Modal.prototype.show=function(a){this.root.classList.add("netgis-show");for(var b=this.root.getElementsByClassName("netgis-dialog"),c=0;c<b.length;c++)b[c].classList.remove("netgis-show");a.classList.add("netgis-show")};netgis.Modal.prototype.hide=function(){this.root.classList.remove("netgis-show")};
-netgis.Modal.prototype.createContainer=function(a){var b=document.createElement("section");b.className="netgis-dialog netgis-shadow";var c=document.createElement("header"),d=document.createElement("button");d.setAttribute("type","button");d.className="netgis-primary netgis-hover-primary";d.innerHTML="<h3>"+a+"</h3>";d.addEventListener("click",this.onHeaderClick.bind(this));c.appendChild(d);a=document.createElement("span");a.innerHTML="<i class='fas fa-times'></i>";d.appendChild(a);b.appendChild(c);
-c=document.createElement("div");c.className="netgis-modal-content";b.appendChild(c);d=document.createElement("table");c.appendChild(d);return b};netgis.Modal.prototype.createSpace=function(a){var b=document.createElement("tr");b.className="netgis-space";var c=document.createElement("td");c.setAttribute("colspan",100);b.appendChild(c);a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(b);return c};
-netgis.Modal.prototype.createButton=function(a,b,c){var d=document.createElement("tr"),e=document.createElement("td");e.setAttribute("colspan",100);d.appendChild(e);var f=document.createElement("button");f.setAttribute("type","button");f.className="netgis-primary netgis-hover-primary";f.innerHTML=b;c&&f.addEventListener("click",c);e.appendChild(f);a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(d);return f};
-netgis.Modal.prototype.createInputHidden=function(a){var b=document.createElement("tr");b.className="netgis-hidden";var c=document.createElement("td");b.appendChild(c);var d=document.createElement("input");d.setAttribute("type","hidden");c.appendChild(d);a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(b);return d};
-netgis.Modal.prototype.createInputText=function(a,b){var c=document.createElement("tr"),d=document.createElement("th");d.className="netgis-padding";var e=document.createElement("label");e.innerHTML=b;d.appendChild(e);c.appendChild(d);b=document.createElement("td");b.className="netgis-padding";c.appendChild(b);d=document.createElement("input");d.setAttribute("type","text");b.appendChild(d);e.htmlFor=d;a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(c);
-return d};netgis.Modal.prototype.createInputSelect=function(a,b,c){c=document.createElement("tr");var d=document.createElement("th");d.className="netgis-padding";var e=document.createElement("label");e.innerHTML=b;d.appendChild(e);c.appendChild(d);b=document.createElement("td");b.className="netgis-padding";c.appendChild(b);d=document.createElement("select");b.appendChild(d);e.htmlFor=d;a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(c);return d};
-netgis.Modal.prototype.createInputInteger=function(a,b,c,d,e){var f=document.createElement("tr"),g=document.createElement("th");g.className="netgis-padding";var h=document.createElement("label");h.innerHTML=b;g.appendChild(h);f.appendChild(g);b=document.createElement("td");b.className="netgis-padding";g=document.createElement("input");g.setAttribute("type","number");g.setAttribute("min",d);g.setAttribute("max",e);g.value=Number.parseInt(c);b.appendChild(g);f.appendChild(b);h.htmlFor=g;a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(f);
-return g};
-netgis.Modal.prototype.createInputCheckbox=function(a,b,c){var d=document.createElement("tr"),e=document.createElement("th");e.className="netgis-padding";var f=document.createElement("label");f.innerHTML=b;e.appendChild(f);d.appendChild(e);b=document.createElement("td");b.className="netgis-padding";e=document.createElement("input");e.setAttribute("type","checkbox");e.checked=c;b.appendChild(e);d.appendChild(b);f.htmlFor=e;a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(d);return e};
-netgis.Modal.prototype.createInputFile=function(a,b,c,d){var e=document.createElement("tr"),f=document.createElement("th");f.className="netgis-padding";var g=document.createElement("label");g.innerHTML=b;f.appendChild(g);e.appendChild(f);b=document.createElement("td");b.className="netgis-padding";f=document.createElement("input");f.setAttribute("type","file");f.setAttribute("accept",c);d&&f.addEventListener("change",d);b.appendChild(f);e.appendChild(b);a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(e);
-return f};netgis.Modal.prototype.createText=function(a,b,c){var d=document.createElement("tr"),e=document.createElement("th");e.className="netgis-padding";e.innerHTML=b;d.appendChild(e);b=document.createElement("td");b.className="netgis-padding";b.innerHTML=c;d.appendChild(b);a.getElementsByClassName("netgis-modal-content")[0].getElementsByTagName("table")[0].appendChild(d);return b};netgis.Modal.prototype.onRootClick=function(a){a.target===this.root&&this.hide()};
-netgis.Modal.prototype.onHeaderClick=function(a){this.hide()};netgis.Modal.prototype.onImportGeoJSONShow=function(a){a=this.importGeoJSON.getElementsByTagName("input")[0];var b=this.importGeoJSON.getElementsByTagName("button")[1];a.value="";b.disabled=!0;this.show(this.importGeoJSON)};netgis.Modal.prototype.onImportGeoJSONChange=function(a){a=this.importGeoJSON.getElementsByTagName("input")[0];this.importGeoJSON.getElementsByTagName("button")[1].disabled=a.value&&0<a.value.length?!1:!0};
-netgis.Modal.prototype.onImportGeoJSONAccept=function(a){a=this.importGeoJSON.getElementsByTagName("input")[0].files[0];this.client.invoke(netgis.Events.IMPORT_GEOJSON,a);this.hide()};netgis.Modal.prototype.onImportGMLShow=function(a){a=this.importGML.getElementsByTagName("input")[0];var b=this.importGML.getElementsByTagName("button")[1];a.value="";b.disabled=!0;this.show(this.importGML)};
-netgis.Modal.prototype.onImportGMLChange=function(a){a=this.importGML.getElementsByTagName("input")[0];this.importGML.getElementsByTagName("button")[1].disabled=a.value&&0<a.value.length?!1:!0};netgis.Modal.prototype.onImportGMLAccept=function(a){a=this.importGML.getElementsByTagName("input")[0].files[0];this.client.invoke(netgis.Events.IMPORT_GML,a);this.hide()};
-netgis.Modal.prototype.onImportShapefileShow=function(a){a=this.importShapefile.getElementsByTagName("input")[0];var b=this.importShapefile.getElementsByTagName("button")[1];a.value="";b.disabled=!0;this.show(this.importShapefile)};netgis.Modal.prototype.onImportShapefileChange=function(a){a=this.importShapefile.getElementsByTagName("input")[0];this.importShapefile.getElementsByTagName("button")[1].disabled=a.value&&0<a.value.length?!1:!0};
-netgis.Modal.prototype.onImportShapefileAccept=function(a){a=this.importShapefile.getElementsByTagName("input")[0].files[0];this.client.invoke(netgis.Events.IMPORT_SHAPEFILE,a);this.hide()};netgis.Modal.prototype.onImportSpatialiteShow=function(a){a=this.importShapefile.getElementsByTagName("input")[0];var b=this.importShapefile.getElementsByTagName("button")[1];a.value="";b.disabled=!0;this.show(this.importSpatialite)};
-netgis.Modal.prototype.onImportSpatialiteChange=function(a){a=this.importSpatialite.getElementsByTagName("input")[0];this.importSpatialite.getElementsByTagName("button")[1].disabled=a.value&&0<a.value.length?!1:!0};netgis.Modal.prototype.onImportSpatialiteAccept=function(a){a=this.importSpatialite.getElementsByTagName("input")[0].files[0];this.client.invoke(netgis.Events.IMPORT_SPATIALITE,a);this.hide()};
-netgis.Modal.prototype.onImportGeopackageShow=function(a){a=this.importGeopackage.getElementsByTagName("input")[0];var b=this.importGeopackage.getElementsByTagName("button")[1];a.value="";b.disabled=!0;this.show(this.importGeopackage)};netgis.Modal.prototype.onImportGeopackageChange=function(a){a=this.importGeopackage.getElementsByTagName("input")[0];this.importGeopackage.getElementsByTagName("button")[1].disabled=a.value&&0<a.value.length?!1:!0};
-netgis.Modal.prototype.onImportGeopackageAccept=function(a){a=this.importGeopackage.getElementsByTagName("input")[0].files[0];this.client.invoke(netgis.Events.IMPORT_GEOPACKAGE,a);this.hide()};netgis.Modal.prototype.onExportPDFShow=function(a){a=this.exportPDF.getElementsByTagName("input");a[0].value=this.client.map.getWidth();a[1].value=this.client.map.getHeight();a[2].value=this.client.config.export.defaultMargin;a[3].checked=!0;this.show(this.exportPDF)};
-netgis.Modal.prototype.onExportJPEGShow=function(a){a=this.exportJPEG.getElementsByTagName("input");a[0].value=this.client.map.getWidth();a[1].value=this.client.map.getHeight();this.show(this.exportJPEG)};netgis.Modal.prototype.onExportPNGShow=function(a){a=this.exportPNG.getElementsByTagName("input");a[0].value=this.client.map.getWidth();a[1].value=this.client.map.getHeight();this.show(this.exportPNG)};
-netgis.Modal.prototype.onExportGIFShow=function(a){a=this.exportGIF.getElementsByTagName("input");a[0].value=this.client.map.getWidth();a[1].value=this.client.map.getHeight();this.show(this.exportGIF)};netgis.Modal.prototype.onExportPDFAccept=function(a){a=this.exportPDF.getElementsByTagName("input");var b=Number.parseInt(a[0].value),c=Number.parseInt(a[1].value),d=Number.parseInt(a[2].value);this.client.invoke(netgis.Events.EXPORT_PDF,{resx:b,resy:c,mode:a[3].checked,margin:d});this.hide()};
-netgis.Modal.prototype.onExportJPEGAccept=function(a){var b=this.exportJPEG.getElementsByTagName("input");a=Number.parseInt(b[0].value);b=Number.parseInt(b[1].value);this.client.invoke(netgis.Events.EXPORT_JPEG,{resx:a,resy:b});this.hide()};netgis.Modal.prototype.onExportPNGAccept=function(a){var b=this.exportPNG.getElementsByTagName("input");a=Number.parseInt(b[0].value);b=Number.parseInt(b[1].value);this.client.invoke(netgis.Events.EXPORT_PNG,{resx:a,resy:b});this.hide()};
-netgis.Modal.prototype.onExportGIFAccept=function(a){var b=this.exportGIF.getElementsByTagName("input");a=Number.parseInt(b[0].value);b=Number.parseInt(b[1].value);this.client.invoke(netgis.Events.EXPORT_GIF,{resx:a,resy:b});this.hide()};netgis.Modal.prototype.onAddServiceShow=function(a){this.show(this.addService);a=this.addService.getElementsByTagName("tr");for(var b=3;b<a.length;b++)a[b].classList.add("netgis-hide")};
-netgis.Modal.prototype.onAddServiceLoad=function(a){a=this.addService.getElementsByTagName("input")[0].value;var b=a.indexOf("?");-1<b&&(a=a.substr(0,b));netgis.util.request(a+"?request=GetCapabilities",this.onAddServiceCapsResponse.bind(this));console.info("Add Service Load:",a)};
-netgis.Modal.prototype.onAddServiceCapsResponse=function(a){var b=(new DOMParser).parseFromString(a,"text/xml").documentElement;a=this.addService.getElementsByTagName("tr");var c=a[5],d=this.addService.getElementsByTagName("input")[1];a=this.addService.getElementsByTagName("select");var e=a[0];a=a[1];for(var f=e.options.length-1;0<=f;f--)e.options.remove(f);for(f=a.options.length-1;0<=f;f--)a.options.remove(f);switch(b.nodeName){case "WMS_Capabilities":d.value="wms";b.getAttribute("version");d=b.getElementsByTagName("Service")[0];
-d=d.getElementsByTagName("Title")[0].textContent;c.children[1].innerHTML=d;f=b.getElementsByTagName("Layer");var g=[];for(d=0;d<f.length;d++){c=f[d];var h=c.getElementsByTagName("Name")[0].textContent,k=c.getElementsByTagName("Title")[0].textContent;g.push({name:h,title:k});c=document.createElement("option");c.text=k;c.value=h;e.options.add(c)}b=b.getElementsByTagName("GetMap")[0].getElementsByTagName("Format");e=[];for(d=0;d<b.length;d++)c=b[d],f=c.textContent,e.push(f),c=document.createElement("option"),
-c.text=f,c.value=f,a.options.add(c);break;case "WFS_Capabilities":case "wfs:WFS_Capabilities":d.value="wfs";b.getAttribute("version");d=b.getElementsByTagName("ows:ServiceIdentification")[0];d=d.getElementsByTagName("ows:Title")[0].textContent;c.children[1].innerHTML=d;f=b.getElementsByTagName("FeatureType");g=[];for(d=0;d<f.length;d++)c=f[d],h=c.getElementsByTagName("Name")[0].textContent,k=c.getElementsByTagName("Title")[0].textContent,g.push({name:h,title:k}),c=document.createElement("option"),
-c.text=k,c.value=h,e.options.add(c);b=b.getElementsByTagName("ows:Operation");e=null;for(c=0;c<b.length;c++)if("GetFeature"===b[c].getAttribute("name")){e=b[c];break}if(e)for(b=e.getElementsByTagName("ows:Parameter"),e=0;e<b.length;e++)if(c=b[e],"outputFormat"===c.getAttribute("name")){b=c.getElementsByTagName("ows:Value");for(d=0;d<b.length;d++)c=b[d],f=c.textContent,c=document.createElement("option"),c.text=f,c.value=f,a.options.add(c);break}a.value="application/json"}a=this.addService.getElementsByTagName("tr");
-for(b=3;b<a.length;b++)a[b].classList.remove("netgis-hide")};
-netgis.Modal.prototype.onAddServiceAccept=function(a){var b=this.addService.getElementsByTagName("input"),c=this.addService.getElementsByTagName("select");a=b[0].value;b=b[1].value;var d=c[0];c=c[1];d=d.options.item(d.options.selectedIndex);c=c.options.item(c.options.selectedIndex);a={id:this.addServiceID++,url:a,title:d.text,name:d.value,format:c.value};switch(b){case "wms":this.client.invoke(netgis.Events.ADD_SERVICE_WMS,a);break;case "wfs":this.client.invoke(netgis.Events.ADD_SERVICE_WFS,a)}this.hide()};netgis=netgis||{};netgis.Modes=Object.freeze({VIEW:"VIEW",PANNING:"PANNING",ZOOMING_IN:"ZOOMING_IN",ZOOMING_OUT:"ZOOMING_OUT",DRAW_POINTS:"DRAW_POINTS",DRAW_LINES:"DRAW_LINES",DRAW_POLYGONS:"DRAW_POLYGONS",CUT_FEATURE_BEGIN:"CUT_FEATURE_BEGIN",CUT_FEATURE_DRAW:"CUT_FEATURE_DRAW",MODIFY_FEATURES:"MODIFY_FEATURES",DELETE_FEATURES:"DELETE_FEATURES",BUFFER_FEATURE_BEGIN:"BUFFER_FEATURE_BEGIN",BUFFER_FEATURE_EDIT:"BUFFER_FEATURE_EDIT",SEARCH_PLACE:"SEARCH_PLACE",SEARCH_PARCEL:"SEARCH_PARCEL"});netgis=netgis||{};
+netgis.Menu.prototype.onDeleteFeaturesClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.DELETE_FEATURES)};netgis.Menu.prototype.onBufferFeatureClick=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_BEGIN)};netgis.Menu.prototype.onSearchPlaceClick=function(a){netgis.util.invoke(this.root,netgis.SearchPlace.Events.TOGGLE)};netgis.Menu.prototype.onSearchParcelClick=function(a){netgis.util.invoke(this.root,netgis.SearchParcel.Events.TOGGLE)};
+netgis.Menu.prototype.onToolboxClick=function(a){netgis.util.invoke(this.root,netgis.Events.TOOLBOX_TOGGLE)};netgis.Menu.prototype.onSearchDataClick=function(a){alert("TODO: data search interface")};netgis.Menu.prototype.onImportOWSClick=function(a){alert("TODO: ows import interface, try setting url parameter '?ows=<url>'")};netgis.Menu.prototype.onImportShapefileClick=function(a){this.client.invoke(netgis.Events.IMPORT_SHAPEFILE_SHOW,null)};
+netgis.Menu.prototype.onImportGeoJSONClick=function(a){this.client.invoke(netgis.Events.IMPORT_GEOJSON_SHOW,null)};netgis.Menu.prototype.onImportKMLClick=function(a){alert("TODO: kml import interface")};netgis.Menu.prototype.onImportGMLClick=function(a){this.client.invoke(netgis.Events.IMPORT_GML_SHOW,null)};netgis.Menu.prototype.onImportSpatialiteClick=function(a){this.client.invoke(netgis.Events.IMPORT_SPATIALITE_SHOW,null)};
+netgis.Menu.prototype.onImportGeopackageClick=function(a){this.client.invoke(netgis.Events.IMPORT_GEOPACKAGE_SHOW,null)};netgis.Menu.prototype.onExportPDFClick=function(a){this.client.invoke(netgis.Events.EXPORT_PDF_SHOW,null)};netgis.Menu.prototype.onExportJPEGClick=function(a){this.client.invoke(netgis.Events.EXPORT_JPEG_SHOW,null)};netgis.Menu.prototype.onExportPNGClick=function(a){this.client.invoke(netgis.Events.EXPORT_PNG_SHOW,null)};
+netgis.Menu.prototype.onExportGIFClick=function(a){this.client.invoke(netgis.Events.EXPORT_GIF_SHOW,null)};netgis=netgis||{};netgis.Modal=function(a){this.initElements(a);this.initEvents()};netgis.Modal.prototype.initElements=function(a){this.container=document.createElement("div");this.container.className="netgis-modal";this.container.addEventListener("click",this.onContainerClick.bind(this));this.content=document.createElement("div");this.content.className="netgis-color-e netgis-shadow";this.container.appendChild(this.content);this.header=this.addHeader(this.content,a,this.onHeaderClick.bind(this))};
+netgis.Modal.prototype.initEvents=function(){};netgis.Modal.prototype.attach=function(a){a.appendChild(this.container)};netgis.Modal.prototype.show=function(){this.container.classList.add("netgis-show")};netgis.Modal.prototype.hide=function(){this.container.classList.remove("netgis-show")};
+netgis.Modal.prototype.addHeader=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-c";d.innerHTML="<span>"+b+"</span><i class='netgis-icon fas fa-times'></i>";d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};netgis.Modal.prototype.onHeaderClick=function(a){this.hide()};netgis.Modal.prototype.onContainerClick=function(a){a.target===this.container&&this.hide()};netgis=netgis||{};
+netgis.Modes=Object.freeze({VIEW:"VIEW",PANNING:"PANNING",ZOOMING_IN:"ZOOMING_IN",ZOOMING_OUT:"ZOOMING_OUT",DRAW_POINTS:"DRAW_POINTS",DRAW_LINES:"DRAW_LINES",DRAW_POLYGONS:"DRAW_POLYGONS",CUT_FEATURE_BEGIN:"CUT_FEATURE_BEGIN",CUT_FEATURE_DRAW:"CUT_FEATURE_DRAW",MODIFY_FEATURES:"MODIFY_FEATURES",DELETE_FEATURES:"DELETE_FEATURES",BUFFER_FEATURE_BEGIN:"BUFFER_FEATURE_BEGIN",BUFFER_FEATURE_EDIT:"BUFFER_FEATURE_EDIT",SEARCH_PLACE:"SEARCH_PLACE",SEARCH_PARCEL:"SEARCH_PARCEL",PARCEL_SELECT:"PARCEL_SELECT",IMPORT:"IMPORT",
+EXPORT:"EXPORT"});netgis=netgis||{};
 netgis.OWS=function(){return{read:function(a,b){var c={layers:[],folders:[]};netgis.util.isDefined(a.properties)&&(c.bbox=a.properties.bbox);a=a.features;for(var d=0;d<a.length;d++){var e=a[d];if("Feature"===e.type){var f=e.properties;f=f.folder;var g=!1;for(e=0;e<c.folders.length;e++)if(c.folders[e].id===f){g=!0;break}if(!g){e=f.split("/");f=[];for(g=0;g<e.length;g++){var h=e[g];0<h.length&&f.push(h)}var k=-1;for(g=0;g<f.length;g++){h=f[g];var l="/"+f.slice(0,g+1).join("/"),m=!1;for(e=0;e<c.folders.length;e++)if(c.folders[e].path===
 l){k=e;m=!0;break}m||(e=c.folders.length,c.folders.push({title:h,parent:k,path:l}),k=e)}}}}for(d=0;d<a.length;d++)if(e=a[d],"Feature"===e.type){f=e.properties;g=-1;for(e=0;e<c.folders.length;e++)if(c.folders[e].path===f.folder){g=e;break}e=f.offerings;for(h=0;h<e.length;h++)switch(k=e[h],l=k.operations,k.code){case "http://www.opengis.net/spec/owc-geojson/1.0/req/wms":c.layers.push({folder:g,type:netgis.LayerTypes.WMS,url:l[0].href,title:f.title,attribution:f.rights,active:f.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/xyz":k=
-l[0];c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/osm":k=l[0],c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active})}}b.invoke(netgis.Events.CONTEXT_UPDATE,c)}}}();netgis=netgis||{};netgis.SearchParcel=function(){this.client=null};
-netgis.SearchParcel.prototype.load=function(){this.root=document.createElement("section");this.root.className="netgis-search-parcel netgis-dialog netgis-shadow netgis-hide";var a=document.createElement("h3");a.innerHTML="Flurst\u00fccks-Suche:";this.root.appendChild(a);a=document.createElement("div");this.root.appendChild(a);var b=this.createInput("Gemarkungsname:");b.style.position="relative";a.appendChild(b);this.nameInput=b.children[0];this.nameInput.setAttribute("title","ENTER: Ausw\u00e4hlen, ESCAPE: Zur\u00fccksetzen");
-this.nameInput.addEventListener("keyup",this.onInputNameKey.bind(this));this.nameLoader=document.createElement("div");this.nameLoader.className="netgis-loader netgis-text-primary netgis-hide";this.nameLoader.innerHTML="<i class='fas fa-spinner'></i>";b.appendChild(this.nameLoader);this.nameList=document.createElement("ul");a.appendChild(this.nameList);b=this.createInput("Gemarkungsnummer:");this.districtInput=b.children[0];a.appendChild(b);b=this.createInput("Flurnummer:");this.fieldInput=b.children[0];
-a.appendChild(b);b=this.createInput("Flurst\u00fccksnummer (Z\u00e4hler/Nenner):");this.parcelInputA=b.children[0];this.parcelInputA.style.width="48%";this.parcelInputB=this.parcelInputA.cloneNode(!0);this.parcelInputB.style.marginLeft="4%";b.appendChild(this.parcelInputB);a.appendChild(b);b=document.createElement("button");b.setAttribute("type","button");b.addEventListener("click",this.onParcelSearchClick.bind(this));b.className="netgis-primary netgis-hover-primary";b.innerHTML="Flurst\u00fccke suchen";
-b.style.marginTop="4mm";a.appendChild(b);this.parcelInfo=document.createElement("p");a.appendChild(this.parcelInfo);this.parcelTable=this.createTable(";Flur;FS Z\u00e4hler;FS Nenner;FKZ;Fl\u00e4che (qm)".split(";"));this.parcelTable.classList.add("netgis-hide");a.appendChild(this.parcelTable);this.parcelList=this.parcelTable.getElementsByTagName("tbody")[0];this.parcelReset=document.createElement("button");this.parcelReset.setAttribute("type","button");this.parcelReset.addEventListener("click",this.onParcelResetClick.bind(this));
-this.parcelReset.className="netgis-primary netgis-hover-primary";this.parcelReset.innerHTML="Zur\u00fccksetzen";this.parcelReset.style.marginTop="4mm";a.appendChild(this.parcelReset);this.reset();this.client.root.appendChild(this.root);this.client.on(netgis.Events.SET_MODE,this.onSetMode.bind(this));this.client.on(netgis.Events.LAYER_LIST_TOGGLE,this.onLayerListToggle.bind(this))};
-netgis.SearchParcel.prototype.createInput=function(a){var b=document.createElement("label");b.className="netgis-hover-text-primary";b.innerHTML=a;a=document.createElement("input");a.setAttribute("type","text");b.appendChild(a);return b};
-netgis.SearchParcel.prototype.createNameItem=function(a){var b=document.createElement("li"),c=document.createElement("button");c.setAttribute("type","button");c.addEventListener("click",this.onNameItemClick.bind(this));c.className="netgis-text-primary netgis-hover-light";c.innerHTML=a;b.appendChild(c);return b};
-netgis.SearchParcel.prototype.createTable=function(a){var b=document.createElement("div");b.className="netgis-table-wrapper";var c=document.createElement("table");b.appendChild(c);var d=document.createElement("thead");c.appendChild(d);var e=document.createElement("tr");e.className="netgis-light";e.style.position="sticky";d.appendChild(e);for(d=0;d<a.length;d++){var f=document.createElement("th");f.innerHTML=a[d];e.appendChild(f)}a=document.createElement("tbody");c.appendChild(a);return b};
-netgis.SearchParcel.prototype.createParcelItem=function(a,b,c,d,e,f,g){var h=document.createElement("tr");h.className="netgis-hover-light netgis-hover-text-primary";h.setAttribute("title","Klicken zum zoomen");h.setAttribute("data-bbox",f);h.setAttribute("data-geom",g);h.addEventListener("mouseenter",this.onParcelEnter.bind(this));h.addEventListener("mouseleave",this.onParcelLeave.bind(this));h.addEventListener("click",this.onParcelClick.bind(this));f=document.createElement("td");h.appendChild(f);
-g=document.createElement("button");g.setAttribute("type","button");g.setAttribute("title","Geometrie \u00fcbernehmen");g.addEventListener("click",this.onParcelImportClick.bind(this));g.className="netgis-text-primary netgis-hover-primary";g.innerHTML="<i class='fas fa-paste'></i>";f.appendChild(g);f=document.createElement("td");f.innerHTML=a;h.appendChild(f);a=document.createElement("td");a.innerHTML=b;h.appendChild(a);b=document.createElement("td");b.innerHTML=c;h.appendChild(b);c=document.createElement("td");
-c.innerHTML=d;h.appendChild(c);d=document.createElement("td");d.innerHTML=e;h.appendChild(d);return h};
-netgis.SearchParcel.prototype.reset=function(){this.nameLoader.classList.add("netgis-hide");this.nameInput.value="";this.districtInput.value="";this.fieldInput.value="";this.parcelInputA.value="";this.parcelInputB.value="";this.nameList.innerHTML="";this.parcelInfo.innerHTML="";this.parcelList.innerHTML="";this.parcelTable.classList.add("netgis-hide");this.parcelReset.classList.add("netgis-hide");this.root.scrollTop=0};
-netgis.SearchParcel.prototype.onInputNameKey=function(a){switch(a.keyCode){case 13:this.selectFirstName();break;case 27:this.reset();break;default:this.requestName(this.nameInput.value.trim())}};
-netgis.SearchParcel.prototype.requestName=function(a){this.nameDebounce&&window.clearTimeout(this.nameDebounce);if(0!==a.length){var b=this.client.config.searchParcel.nameURL;b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));this.nameDebounce=window.setTimeout(this.onInputNameDebounce.bind(this,b),200);this.nameLoader.classList.remove("netgis-hide")}};netgis.SearchParcel.prototype.onInputNameDebounce=function(a){netgis.util.request(a,this.onInputNameResponse.bind(this))};
+l[0];c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active});break;case "http://www.opengis.net/spec/owc-geojson/1.0/req/osm":k=l[0],c.layers.push({folder:g,type:netgis.LayerTypes.XYZ,url:k.href,title:f.title,attribution:f.rights,active:f.active})}}b.invoke(netgis.Events.CONTEXT_UPDATE,c)}}}();netgis=netgis||{};netgis.Panel=function(a){this.initElements(a);this.initEvents()};netgis.Panel.prototype.initElements=function(a){var b=document.createElement("section");b.className="netgis-panel netgis-resize-right netgis-color-e netgis-shadow";this.addHeader(b,a,this.onHeaderClick.bind(this));this.container=b};netgis.Panel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onResize.bind(this))).observe(this.container)};netgis.Panel.prototype.attach=function(a){a.appendChild(this.container)};
+netgis.Panel.prototype.addHeader=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-c";d.innerHTML="<span>"+b+"</span><i class='netgis-icon fas fa-times'></i>";d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};netgis.Panel.prototype.show=function(){this.container.classList.add("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:!0})};
+netgis.Panel.prototype.hide=function(){this.container.classList.remove("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:!1})};netgis.Panel.prototype.toggle=function(){this.container.classList.toggle("netgis-show");netgis.util.invoke(this.container,netgis.Events.PANEL_TOGGLE,{panel:this,visible:this.container.classList.contains("netgis-show")})};netgis.Panel.prototype.visible=function(){return this.container.classList.contains("netgis-show")};
+netgis.Panel.prototype.width=function(){return this.container.getBoundingClientRect().width};netgis.Panel.prototype.onHeaderClick=function(a){this.hide()};netgis.Panel.prototype.onResize=function(a){this.container.classList.contains("netgis-show")&&(a=this.container.getBoundingClientRect(),netgis.util.invoke(this.container,netgis.Events.PANEL_RESIZE,{width:a.width}))};netgis=netgis||{};netgis.SearchParcel=function(a){this.config=a;this.initElements();this.initEvents()};netgis.SearchParcel.Events=Object.freeze({TOGGLE:"search-parcel-toggle"});
+netgis.SearchParcel.prototype.initElements=function(){this.container=document.createElement("section");this.container.className="netgis-search-parcel";var a=document.createElement("section");this.top=a;this.container.appendChild(a);var b=this.createInput("Gemarkungsname:");b.style.position="relative";a.appendChild(b);this.nameInput=b.children[0];this.nameInput.setAttribute("title","ENTER: Ausw\u00e4hlen, ESCAPE: Zur\u00fccksetzen");this.nameInput.addEventListener("keyup",this.onInputNameKey.bind(this));
+this.nameLoader=document.createElement("div");this.nameLoader.className="netgis-loader netgis-text-primary netgis-hide";this.nameLoader.innerHTML="<i class='fas fa-spinner'></i>";b.appendChild(this.nameLoader);this.nameList=document.createElement("ul");a.appendChild(this.nameList);b=this.createInput("Gemarkungsnummer:");this.districtInput=b.children[0];a.appendChild(b);b=this.createInput("Flurnummer:");this.fieldInput=b.children[0];this.fieldInput.addEventListener("keyup",this.onInputFieldKey.bind(this));
+a.appendChild(b);b=this.createInput("<span>Flurst\u00fccksnummer (Z\u00e4hler/Nenner):</span>");this.parcelInputA=b.children[1];this.parcelInputA.style.width="48%";this.parcelInputB=this.parcelInputA.cloneNode(!0);this.parcelInputB.style.marginLeft="4%";b.appendChild(this.parcelInputB);a.appendChild(b);b=document.createElement("button");b.setAttribute("type","button");b.addEventListener("click",this.onParcelSearchClick.bind(this));b.className="netgis-color-a netgis-hover-c";b.innerHTML="Flurst\u00fccke suchen";
+b.style.marginTop="4mm";a.appendChild(b);b=document.createElement("section");b.className="netgis-hide";this.bottom=b;this.container.appendChild(b);var c=document.createElement("button");c.className="netgis-button netgis-clip-text netgis-color-c";c.innerHTML="<span>Flurst\u00fccke</span> <span></span><i class='netgis-icon fas fa-times'></i>";c.setAttribute("type","button");c.addEventListener("click",this.onBottomHeaderClick.bind(this));b.appendChild(c);this.parcelCount=c.getElementsByTagName("span")[1];
+this.parcelInfo=document.createElement("p");this.parcelTable=this.createTable(";Flur;Z\u00e4hler;Nenner;FKZ;Fl\u00e4che (qm)".split(";"));this.parcelTable.classList.add("netgis-hide");this.parcelTable.style.position="absolute";this.parcelTable.style.width="100%";this.parcelTable.style.top="12mm";this.parcelTable.style.bottom="0mm";this.parcelTable.style.margin="0mm";this.parcelTable.style.overflow="auto";b.appendChild(this.parcelTable);this.parcelList=this.parcelTable.getElementsByTagName("tbody")[0];
+this.parcelReset=document.createElement("button");this.parcelReset.setAttribute("type","button");this.parcelReset.addEventListener("click",this.onParcelResetClick.bind(this));this.parcelReset.className="netgis-color-a netgis-hover-c";this.parcelReset.innerHTML="Zur\u00fccksetzen";this.parcelReset.style.marginTop="4mm";a.appendChild(this.parcelReset);var d=this;window.setTimeout(function(){d.reset()},50)};netgis.SearchParcel.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onTopResize.bind(this))).observe(this.top)};
+netgis.SearchParcel.prototype.attach=function(a){a.appendChild(this.container)};netgis.SearchParcel.prototype.createInput=function(a){var b=document.createElement("label");b.className="netgis-hover-text-primary";b.innerHTML=a;a=document.createElement("input");a.setAttribute("type","text");b.appendChild(a);return b};
+netgis.SearchParcel.prototype.createNameItem=function(a){var b=document.createElement("li"),c=document.createElement("button");c.setAttribute("type","button");c.addEventListener("click",this.onNameItemClick.bind(this));c.className="netgis-color-e netgis-hover-a netgis-text-a netgis-hover-text-e";c.innerHTML=a;b.appendChild(c);return b};
+netgis.SearchParcel.prototype.createTable=function(a){var b=document.createElement("div");b.className="netgis-table-wrapper";var c=document.createElement("table");b.appendChild(c);var d=document.createElement("thead");c.appendChild(d);var e=document.createElement("tr");e.className="netgis-color-d netgis-shadow";d.appendChild(e);for(d=0;d<a.length;d++){var f=document.createElement("th");f.innerHTML=a[d];e.appendChild(f)}a=document.createElement("tbody");c.appendChild(a);return b};
+netgis.SearchParcel.prototype.createParcelItem=function(a,b,c,d,e,f,g){var h=document.createElement("tr");h.className="netgis-hover-light netgis-hover-text-primary";h.setAttribute("title","Klicken zum zoomen");h.setAttribute("data-id",d);h.setAttribute("data-field",a);h.setAttribute("data-parcel-a",b);h.setAttribute("data-parcel-b",c);h.setAttribute("data-bbox",f);h.setAttribute("data-geom",g);h.addEventListener("pointerenter",this.onParcelEnter.bind(this));h.addEventListener("pointerleave",this.onParcelLeave.bind(this));
+h.addEventListener("click",this.onParcelClick.bind(this));f=document.createElement("td");h.appendChild(f);g=document.createElement("button");g.setAttribute("type","button");g.setAttribute("title","Geometrie \u00fcbernehmen");g.addEventListener("click",this.onParcelImportClick.bind(this));g.className="netgis-text-primary netgis-hover-primary";g.innerHTML="<i class='fas fa-paste'></i>";f.appendChild(g);f=document.createElement("td");f.innerHTML=a;h.appendChild(f);a=document.createElement("td");a.innerHTML=
+b;h.appendChild(a);b=document.createElement("td");b.innerHTML=c;h.appendChild(b);c=document.createElement("td");c.innerHTML=d;h.appendChild(c);d=document.createElement("td");d.innerHTML=e;h.appendChild(d);return h};
+netgis.SearchParcel.prototype.reset=function(){this.hideBottom();this.nameLoader.classList.add("netgis-hide");this.nameInput.value="";this.districtInput.value="";this.fieldInput.value="";this.parcelInputA.value="";this.parcelInputB.value="";this.nameList.innerHTML="";this.parcelInfo.innerHTML="";this.parcelList.innerHTML="";this.parcelTable.classList.add("netgis-hide");this.parcelReset.classList.add("netgis-hide");this.parcelCount.innerHTML="";var a=this;window.setTimeout(function(){a.top.scrollTop=
+0;a.parcelTable.scrollTop=0},10);netgis.util.invoke(this.container,netgis.Events.PARCELS_RESET,null)};netgis.SearchParcel.prototype.onInputNameKey=function(a){switch(a.keyCode){case 13:this.selectFirstName();break;case 27:this.reset();break;default:this.requestName(this.nameInput.value.trim())}};
+netgis.SearchParcel.prototype.requestName=function(a){this.nameDebounce&&window.clearTimeout(this.nameDebounce);if(0!==a.length){var b=this.config.searchParcel.nameURL;b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));this.nameDebounce=window.setTimeout(this.onInputNameDebounce.bind(this,b),200);this.nameLoader.classList.remove("netgis-hide")}};netgis.SearchParcel.prototype.onInputNameDebounce=function(a){netgis.util.request(a,this.onInputNameResponse.bind(this))};
 netgis.SearchParcel.prototype.onInputNameResponse=function(a){this.nameLoader.classList.add("netgis-hide");this.nameList.innerHTML="";if("{"===a.charAt(0)||"["===a.charAt(0)){a=JSON.parse(a);for(var b=0;b<a.data.length;b++){var c=a.data[b],d=this.createNameItem(c.gmk_name);d.getElementsByTagName("button")[0].setAttribute("data-id",c.gmk_gmn);this.nameList.appendChild(d)}}};
-netgis.SearchParcel.prototype.onNameItemClick=function(a){a=a.target;var b=a.getAttribute("data-id");this.nameInput.value=a.innerHTML;this.nameList.innerHTML="";this.districtInput.value=b};netgis.SearchParcel.prototype.selectFirstName=function(){var a=this.nameList.getElementsByTagName("button");0<a.length&&a[0].click()};netgis.SearchParcel.prototype.onParcelSearchClick=function(a){this.requestParcel(this.districtInput.value.trim(),this.fieldInput.value.trim(),this.parcelInputA.value.trim(),this.parcelInputB.value.trim())};
-netgis.SearchParcel.prototype.requestParcel=function(a,b,c,d){var e=this.client.config.searchParcel.parcelURL;e=netgis.util.replace(e,"{district}",a?a:"");e=netgis.util.replace(e,"{field}",b?b:"");e=netgis.util.replace(e,"{parcelA}",c?c:"");e=netgis.util.replace(e,"{parcelB}",d?d:"");this.parcelTable.classList.add("netgis-hide");this.parcelList.innerHTML="";this.parcelInfo.innerHTML="Suche Flurst\u00fccke...";netgis.util.request(e,this.onParcelResponse.bind(this))};
-netgis.SearchParcel.prototype.onParcelResponse=function(a){a=JSON.parse(a);if(0===a.count)this.parcelInfo.innerHTML=a.Info;else{this.parcelInfo.innerHTML="Flurst\u00fccke gefunden: <span class='netgis-text-primary'>"+a.count+"</span>";for(var b=0;b<a.data.length;b++){var c=a.data[b];c=this.createParcelItem(c.fln,c.fsn_zae,c.fsn_nen,c.fsk,c.flaeche,c.bbox,c.geometry);this.parcelList.appendChild(c)}this.parcelTable.classList.remove("netgis-hide")}this.parcelReset.classList.remove("netgis-hide");this.root.classList.contains("netgis-hide")||
-this.parcelTable.scrollIntoView()};netgis.SearchParcel.prototype.onParcelEnter=function(a){a=a.target.getAttribute("data-geom");this.client.invoke(netgis.Events.PARCEL_SHOW_PREVIEW,{geom:a})};netgis.SearchParcel.prototype.onParcelLeave=function(a){this.client.invoke(netgis.Events.PARCEL_HIDE_PREVIEW,null)};netgis.SearchParcel.prototype.onParcelClick=function(a){a=a.currentTarget.getAttribute("data-bbox");this.client.invoke(netgis.Events.MAP_ZOOM_WKT,a)};
-netgis.SearchParcel.prototype.onParcelImportClick=function(a){a=a.currentTarget.parentElement.parentElement.getAttribute("data-geom");this.client.invoke(netgis.Events.IMPORT_WKT,a)};netgis.SearchParcel.prototype.onParcelResetClick=function(a){this.reset()};netgis.SearchParcel.prototype.onSetMode=function(a){a===netgis.Modes.SEARCH_PARCEL&&this.root.classList.contains("netgis-hide")?this.root.classList.remove("netgis-hide"):this.root.classList.add("netgis-hide")};
-netgis.SearchParcel.prototype.onLayerListToggle=function(a){this.root.classList.add("netgis-hide")};netgis=netgis||{};netgis.SearchPlace=function(){this.lastRequest=this.timeout=this.client=null};netgis.SearchPlace.prototype.load=function(){this.client.on(netgis.Events.SEARCH_PLACE_REQUEST,this.onSearchPlaceRequest.bind(this))};
-netgis.SearchPlace.prototype.request=function(a){if(this.client.config.search&&this.client.config.search.url){var b=this.client.config.search.url;a=a.trim();b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));b=netgis.util.replace(b,"{epsg}",4326);b=window.encodeURI(b);this.lastRequest=netgis.util.request(b,this.onSearchPlaceResponse.bind(this))}else console.warn("No search API url configured for place search!")};
-netgis.SearchPlace.prototype.onSearchPlaceRequest=function(a){var b=a.query,c=this;this.lastRequest&&this.lastRequest.abort();this.timeout&&window.clearTimeout(this.timeout);this.timeout=window.setTimeout(function(){c.request(b)},300)};netgis.SearchPlace.prototype.onSearchPlaceResponse=function(a){a=JSON.parse(a);this.client.invoke(netgis.Events.SEARCH_PLACE_RESPONSE,a)};netgis=netgis||{};
+netgis.SearchParcel.prototype.onNameItemClick=function(a){a=a.target;var b=a.getAttribute("data-id");this.nameInput.value=a.innerHTML;this.nameList.innerHTML="";this.districtInput.value=b;this.requestFieldsGeom(b)};
+netgis.SearchParcel.prototype.requestFieldsGeom=function(a){var b=this.config.searchParcel.fields_service,c=b.url;c=c+"service=WFS&version=1.0.0&request=GetFeature&outputFormat=application/json; subtype=geojson&typename="+b.name;c=c+"&filter=<Filter><PropertyIsEqualTo><PropertyName>"+(b.filter_property+"</PropertyName>");netgis.util.request(c+("<Literal>"+a+"</Literal></PropertyIsEqualTo></Filter>"),this.onFieldsGeomResponse.bind(this))};
+netgis.SearchParcel.prototype.onFieldsGeomResponse=function(a){a=JSON.parse(a);netgis.util.invoke(this.container,netgis.Events.PARCELS_FIELDS_RESPONSE,{geojson:a})};netgis.SearchParcel.prototype.selectFirstName=function(){var a=this.nameList.getElementsByTagName("button");0<a.length&&a[0].click()};netgis.SearchParcel.prototype.setDistrict=function(a,b){this.nameInput.value=a;this.districtInput.value=b;this.requestFieldsGeom(b)};
+netgis.SearchParcel.prototype.setFieldNumber=function(a){this.fieldInput.value=a;this.onParcelSearchClick()};netgis.SearchParcel.prototype.setParcelNumber=function(a,b){this.parcelInputA.value=a;this.parcelInputB.value=b;this.onParcelSearchClick()};netgis.SearchParcel.prototype.showBottom=function(){this.top.classList.add("netgis-resize-bottom");this.top.style.height="50%";this.top.style.bottom="auto";this.bottom.classList.remove("netgis-hide")};
+netgis.SearchParcel.prototype.hideBottom=function(){this.top.classList.remove("netgis-resize-bottom");this.top.style.height="auto";this.top.style.bottom="0mm";this.bottom.classList.add("netgis-hide")};netgis.SearchParcel.prototype.onInputFieldKey=function(a){switch(a.keyCode){case 13:this.onParcelSearchClick()}};netgis.SearchParcel.prototype.onParcelSearchClick=function(a){this.requestParcel(this.districtInput.value.trim(),this.fieldInput.value.trim(),this.parcelInputA.value.trim(),this.parcelInputB.value.trim())};
+netgis.SearchParcel.prototype.requestParcel=function(a,b,c,d){var e=this.config.searchParcel.parcelURL;e=netgis.util.replace(e,"{district}",a?a:"");e=netgis.util.replace(e,"{field}",b?b:"");e=netgis.util.replace(e,"{parcelA}",c?c:"");e=netgis.util.replace(e,"{parcelB}",d?d:"");this.parcelTable.classList.add("netgis-hide");this.parcelList.innerHTML="";this.parcelInfo.innerHTML="Suche Flurst\u00fccke...";netgis.util.request(e,this.onParcelResponse.bind(this))};
+netgis.SearchParcel.prototype.onParcelResponse=function(a){a=JSON.parse(a);this.parcelCount.innerHTML="("+a.count+")";if(0===a.count)this.parcelInfo.innerHTML=a.Info;else{for(var b=0;b<a.data.length;b++){var c=a.data[b];c=this.createParcelItem(c.fln,c.fsn_zae,c.fsn_nen,c.fsk,c.flaeche,c.bbox,c.geometry);this.parcelList.appendChild(c)}this.parcelTable.classList.remove("netgis-hide");this.showBottom();netgis.util.invoke(this.container,netgis.Events.PARCELS_RESPONSE,{parcels:a.data})}this.parcelReset.classList.remove("netgis-hide");
+this.container.classList.contains("netgis-hide")||this.parcelTable.scrollIntoView()};netgis.SearchParcel.prototype.onParcelEnter=function(a){a=a.target;var b=a.getAttribute("data-geom");a={id:a.getAttribute("data-id"),field:a.getAttribute("data-field"),parcelA:a.getAttribute("data-parcel-a"),parcelB:a.getAttribute("data-parcel-b"),geom:b};netgis.util.invoke(this.container,netgis.Events.PARCELS_ITEM_ENTER,a)};
+netgis.SearchParcel.prototype.onParcelLeave=function(a){netgis.util.invoke(this.container,netgis.Events.PARCELS_ITEM_LEAVE,{id:a.target.getAttribute("data-id")})};netgis.SearchParcel.prototype.onParcelClick=function(a){netgis.util.invoke(this.container,netgis.Events.PARCELS_ITEM_CLICK,{id:a.currentTarget.getAttribute("data-id")})};
+netgis.SearchParcel.prototype.onParcelImportClick=function(a){a.stopPropagation();var b=a.currentTarget.parentElement.parentElement;a=b.getAttribute("data-id");b=b.getAttribute("data-geom");netgis.util.invoke(this.container,netgis.Events.PARCELS_ITEM_IMPORT_CLICK,{id:a,geom:b})};netgis.SearchParcel.prototype.onParcelResetClick=function(a){this.reset()};
+netgis.SearchParcel.prototype.onSetMode=function(a){a===netgis.Modes.SEARCH_PARCEL&&this.container.classList.contains("netgis-hide")?this.container.classList.remove("netgis-hide"):this.container.classList.add("netgis-hide")};netgis.SearchParcel.prototype.onLayerListToggle=function(a){this.container.classList.add("netgis-hide")};
+netgis.SearchParcel.prototype.onTopResize=function(a){if(!this.bottom.classList.contains("netgis-hide")){a=this.top.getBoundingClientRect();var b=this.top.parentNode.getBoundingClientRect();this.bottom.style.top=a.bottom-b.top+"px"}};netgis.SearchParcel.prototype.onBottomHeaderClick=function(a){this.reset()};netgis=netgis||{};"use strict";netgis=netgis||{};netgis.SearchPlace=function(a){this.config=a;this.debounce=400;this.initElements();this.initEvents()};netgis.SearchPlace.Events=Object.freeze({TOGGLE:"toggle",SELECT:"select"});
+netgis.SearchPlace.prototype.initElements=function(){var a=document.createElement("div");a.className="netgis-search-place netgis-color-e netgis-shadow";this.input=document.createElement("input");this.input.setAttribute("type","text");this.input.setAttribute("placeholder","Suche...");a.appendChild(this.input);this.list=document.createElement("ul");a.appendChild(this.list);this.closer=document.createElement("button");this.closer.setAttribute("type","button");this.closer.className="netgis-button";this.closer.innerHTML=
+"<i class='fas fa-times'></i>";this.closer.addEventListener("click",this.onCloserClick.bind(this));a.appendChild(this.closer);this.container=a};
+netgis.SearchPlace.prototype.initEvents=function(){this.input.addEventListener("change",this.onInputChange.bind(this));this.input.addEventListener("keydown",this.onInputKeyDown.bind(this));this.input.addEventListener("keyup",this.onInputKeyUp.bind(this));this.input.addEventListener("click",this.onInputClick.bind(this));this.container.addEventListener("focusout",this.onFocusOut.bind(this))};netgis.SearchPlace.prototype.attach=function(a){a.appendChild(this.container)};
+netgis.SearchPlace.prototype.toggle=function(){this.container.classList.toggle("netgis-show");this.container.classList.contains("netgis-show")?this.input.focus():this.list.classList.add("netgis-hide")};
+netgis.SearchPlace.prototype.requestSearch=function(a){if(!this.lastQuery||this.lastQuery!==a){this.lastQuery=a;var b=this.config.search.url;b=netgis.util.replace(b,"{q}",window.encodeURIComponent(a));b=netgis.util.replace(b,"{epsg}",4326);b=window.encodeURI(b);this.lastRequest=netgis.util.request(b,this.onSearchResponse.bind(this))}};
+netgis.SearchPlace.prototype.createResult=function(a,b,c,d,e){var f=document.createElement("li"),g=document.createElement("button");g.className="netgis-button netgis-clip-text netgis-color-e netgis-hover-a";g.innerHTML=a;g.setAttribute("type","button");g.setAttribute("title",a);g.setAttribute("data-minx",b);g.setAttribute("data-miny",c);g.setAttribute("data-maxx",d);g.setAttribute("data-maxy",e);g.addEventListener("click",this.onResultClick.bind(this));f.appendChild(g);return f};
+netgis.SearchPlace.prototype.onSearchResponse=function(a){a=JSON.parse(a);console.info("Search Response:",a);this.list.innerHTML="";this.list.classList.remove("netgis-hide");if(a.geonames){a=a.geonames;for(var b=0;b<a.length;b++){var c=a[b],d=this.createResult(c.title,Number.parseFloat(c.minx),Number.parseFloat(c.miny),Number.parseFloat(c.maxx),Number.parseFloat(c.maxy));d.children[0].setAttribute("data-title",c.title);this.list.appendChild(d)}}};
+netgis.SearchPlace.prototype.onInputKeyDown=function(a){if(13===a.keyCode)return this.list.classList.remove("netgis-hide"),a.preventDefault(),!1};netgis.SearchPlace.prototype.onInputKeyUp=function(a){switch(a.keyCode){case 13:break;case 27:this.toggle();break;default:this.onInputChange()}};netgis.SearchPlace.prototype.onInputChange=function(a){this.timeout&&window.clearTimeout(this.timeout);this.timeout=window.setTimeout(this.onInputTimeout.bind(this),this.debounce)};
+netgis.SearchPlace.prototype.onInputTimeout=function(){var a=this.input.value;a=a.trim();0<a.length&&this.requestSearch(a)};netgis.SearchPlace.prototype.onInputClick=function(a){this.list.classList.toggle("netgis-hide")};netgis.SearchPlace.prototype.onFocusOut=function(a){a=a.relatedTarget;a!==this.input&&a!==this.list&&(a&&a.parentNode===this.list||a&&a.parentNode.parentNode===this.list||this.list.classList.add("netgis-hide"))};
+netgis.SearchPlace.prototype.onResultClick=function(a){a=a.currentTarget;var b=Number.parseFloat(a.getAttribute("data-minx")),c=Number.parseFloat(a.getAttribute("data-miny")),d=Number.parseFloat(a.getAttribute("data-maxx")),e=Number.parseFloat(a.getAttribute("data-maxy")),f=a.getAttribute("data-title");netgis.util.invoke(a,netgis.SearchPlace.Events.SELECT,{minx:b,miny:c,maxx:d,maxy:e,title:f})};
+netgis.SearchPlace.prototype.onCloserClick=function(a){this.toggle();this.list.innerHTML="";this.input.value=""};netgis=netgis||{};
 netgis.SLD=function(){return{read:function(a,b){var c={};a=(new DOMParser).parseFromString(a,"text/xml").getElementsByTagName("NamedLayer");for(var d=0;d<a.length;d++){var e=a[d],f=e.getElementsByTagName("se:Name")[0].innerHTML;console.info("Layer:",f);e=e.getElementsByTagName("se:FeatureTypeStyle");for(f=0;f<e.length;f++)for(var g=e[f].getElementsByTagName("se:Rule"),h=0;h<g.length;h++){var k=g[h],l=k.getElementsByTagName("se:Name")[0].innerHTML;console.info("Rule:",l);l=k.getElementsByTagName("se:PolygonSymbolizer")[0];k=
-l.getElementsByTagName("se:Fill")[0];l=l.getElementsByTagName("se:Stroke")[0];c.polygon={fill:k.querySelector("[name='fill']").innerHTML,stroke:l.querySelector("[name='stroke']").innerHTML,strokeWidth:Number.parseFloat(l.querySelector("[name='stroke-width']").innerHTML)}}}console.info("SLD:",c);b.invoke(netgis.Events.MAP_UPDATE_STYLE,c);return c}}}();netgis=netgis||{};netgis.Toolbar=function(){this.client=null;this.toolbars={};this.searchValue=""};
+l.getElementsByTagName("se:Fill")[0];l=l.getElementsByTagName("se:Stroke")[0];c.polygon={fill:k.querySelector("[name='fill']").innerHTML,stroke:l.querySelector("[name='stroke']").innerHTML,strokeWidth:Number.parseFloat(l.querySelector("[name='stroke-width']").innerHTML)}}}console.info("SLD:",c);b.invoke(netgis.Events.MAP_UPDATE_STYLE,c);return c}}}();netgis=netgis||{};netgis.Tabs=function(a){this.initElements(a);this.initEvents();this.setActiveTab(0)};
+netgis.Tabs.prototype.initElements=function(a){this.container=document.createElement("div");this.container.className="netgis-tabs";this.header=document.createElement("div");this.header.className="netgis-header";this.header.style.background="orange";this.container.appendChild(this.header);this.content=document.createElement("div");this.content.className="netgis-content";this.container.appendChild(this.content);for(var b=0;b<a.length;b++){var c=document.createElement("button");c.setAttribute("type",
+"button");c.addEventListener("click",this.onHeaderButtonClick.bind(this));c.className="netgis-button netgis-color-d";c.innerHTML=a[b];this.header.appendChild(c);c=document.createElement("section");c.className="netgis-color-e netgis-form";this.content.appendChild(c)}};netgis.Tabs.prototype.initEvents=function(){};netgis.Tabs.prototype.attach=function(a){a.appendChild(this.container)};
+netgis.Tabs.prototype.setActiveTab=function(a){for(var b=this.header.getElementsByClassName("netgis-button"),c=this.content.getElementsByTagName("section"),d=0;d<b.length;d++){var e=b[d],f=c[d];d===a?(e.classList.add("netgis-color-e"),e.classList.add("netgis-text-a"),e.classList.add("netgis-bar-a"),f.classList.remove("netgis-hide")):(e.classList.remove("netgis-color-e"),e.classList.remove("netgis-text-a"),e.classList.remove("netgis-bar-a"),f.classList.add("netgis-hide"))}};
+netgis.Tabs.prototype.getContentSection=function(a){return this.content.getElementsByTagName("section")[a]};netgis.Tabs.prototype.appendContent=function(a,b){this.content.getElementsByTagName("section")[a].appendChild(b)};netgis.Tabs.prototype.onHeaderButtonClick=function(a){a=a.currentTarget;for(var b=this.header.getElementsByClassName("netgis-button"),c=0,d=0;d<b.length;d++)if(b[d]===a){c=d;break}this.setActiveTab(c)};netgis=netgis||{};netgis.Toolbar=function(){this.client=null;this.toolbars={};this.searchValue=""};
 netgis.Toolbar.prototype.load=function(){var a=this.client.config;this.root=document.createElement("section");this.root.className="netgis-toolbars";if(this.client.editable){var b=1E3,c=3;netgis.util.isDefined(a.tools)&&(netgis.util.isDefined(a.tools.buffer.defaultRadius)&&(b=a.tools.buffer.defaultRadius),netgis.util.isDefined(a.tools.buffer.defaultSegments)&&(c=a.tools.buffer.defaultSegments));this.toolbars[netgis.Modes.DRAW_POINTS]=this.createToolbar();this.append(this.toolbars[netgis.Modes.DRAW_POINTS],
 this.createToolbarButton('<i class="fas fa-times"></i><span>Punkte zeichnen:</span>',this.onToolbarClose.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_POINTS],this.createToolbarCheckbox("Einrasten",this.onSnapChange.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_POINTS],this.createToolbarCheckbox("Puffern",this.onDrawBufferChange.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_POINTS],this.createToolbarInput("Radius (Meter):",b,this.onDrawBufferRadiusChange.bind(this)));
 this.append(this.toolbars[netgis.Modes.DRAW_POINTS],this.createToolbarInput("Segmente:",c,this.onDrawBufferSegmentsChange.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.DRAW_POINTS]);this.toolbars[netgis.Modes.DRAW_LINES]=this.createToolbar();this.append(this.toolbars[netgis.Modes.DRAW_LINES],this.createToolbarButton('<i class="fas fa-times"></i><span>Linien zeichnen:</span>',this.onToolbarClose.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_LINES],this.createToolbarCheckbox("Einrasten",
 this.onSnapChange.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_LINES],this.createToolbarCheckbox("Puffern",this.onDrawBufferChange.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_LINES],this.createToolbarInput("Radius (Meter):",b,this.onDrawBufferRadiusChange.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_LINES],this.createToolbarInput("Segmente:",c,this.onDrawBufferSegmentsChange.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.DRAW_LINES]);this.showDrawBufferOptions(!1);
 this.toolbars[netgis.Modes.DRAW_POLYGONS]=this.createToolbar();this.append(this.toolbars[netgis.Modes.DRAW_POLYGONS],this.createToolbarButton('<i class="fas fa-times"></i><span>Polygone zeichnen:</span>',this.onToolbarClose.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_POLYGONS],this.createToolbarCheckbox("Einrasten",this.onSnapChange.bind(this)));this.append(this.toolbars[netgis.Modes.DRAW_POLYGONS],this.createToolbarCheckbox("Tracing",this.onTracingChange.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.DRAW_POLYGONS]);
 this.toolbars[netgis.Modes.CUT_FEATURE_BEGIN]=this.createToolbar();this.append(this.toolbars[netgis.Modes.CUT_FEATURE_BEGIN],this.createToolbarButton('<i class="fas fa-times"></i><span>Feature zum Ausschneiden w\u00e4hlen:</span>',this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.CUT_FEATURE_BEGIN]);this.toolbars[netgis.Modes.CUT_FEATURE_DRAW]=this.createToolbar();this.append(this.toolbars[netgis.Modes.CUT_FEATURE_DRAW],this.createToolbarButton('<i class="fas fa-times"></i><span>Fl\u00e4che zum Ausschneiden zeichnen:</span>',
-this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.CUT_FEATURE_DRAW]);this.toolbars[netgis.Modes.MODIFY_FEATURES]=this.createToolbar();this.append(this.toolbars[netgis.Modes.MODIFY_FEATURES],this.createToolbarButton('<i class="fas fa-times"></i><span>Features verschieben:</span>',this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.MODIFY_FEATURES]);this.toolbars[netgis.Modes.DELETE_FEATURES]=this.createToolbar();this.append(this.toolbars[netgis.Modes.DELETE_FEATURES],
+this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.CUT_FEATURE_DRAW]);this.toolbars[netgis.Modes.MODIFY_FEATURES]=this.createToolbar();this.append(this.toolbars[netgis.Modes.MODIFY_FEATURES],this.createToolbarButton('<i class="fas fa-times"></i><span>Feature-Eckpunkte verschieben:</span>',this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.MODIFY_FEATURES]);this.toolbars[netgis.Modes.DELETE_FEATURES]=this.createToolbar();this.append(this.toolbars[netgis.Modes.DELETE_FEATURES],
 this.createToolbarButton('<i class="fas fa-times"></i><span>Features l\u00f6schen:</span>',this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.DELETE_FEATURES]);this.toolbars[netgis.Modes.BUFFER_FEATURE_BEGIN]=this.createToolbar();this.append(this.toolbars[netgis.Modes.BUFFER_FEATURE_BEGIN],this.createToolbarButton('<i class="fas fa-times"></i><span>Feature zum Puffern w\u00e4hlen:</span>',this.onToolbarClose.bind(this)));this.root.appendChild(this.toolbars[netgis.Modes.BUFFER_FEATURE_BEGIN]);
 this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT]=this.createToolbar();this.append(this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT],this.createToolbarButton('<i class="fas fa-times"></i><span>Feature puffern:</span>',this.onBufferCancel.bind(this)));this.append(this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT],this.createToolbarInput("Radius (Meter):",b,this.onBufferChange.bind(this)));this.append(this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT],this.createToolbarInput("Segmente:",c,this.onBufferChange.bind(this)));
 this.append(this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT],this.createToolbarButton('<i class="fas fa-check"></i><span>OK</span>',this.onBufferAccept.bind(this)));a=this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT].getElementsByTagName("input");a[0].addEventListener("keyup",this.onBufferKeyUp.bind(this));a[1].addEventListener("keyup",this.onBufferKeyUp.bind(this));a[1].setAttribute("min",1);this.root.appendChild(this.toolbars[netgis.Modes.BUFFER_FEATURE_EDIT])}this.toolbars[netgis.Modes.SEARCH_PLACE]=
@@ -232,7 +274,7 @@ this.onSearchBlur.bind(this));this.append(this.toolbars[netgis.Modes.SEARCH_PLAC
 this.client.on(netgis.Events.SET_MODE,this.onSetMode.bind(this));this.client.on(netgis.Events.SEARCH_PLACE_RESPONSE,this.onSearchPlaceResponse.bind(this))};netgis.Toolbar.prototype.createToolbar=function(){var a=document.createElement("div");a.className="netgis-toolbar netgis-dialog netgis-shadow netgis-hide";var b=document.createElement("div");a.appendChild(b);return a};netgis.Toolbar.prototype.append=function(a,b){a.getElementsByTagName("div")[0].appendChild(b)};
 netgis.Toolbar.prototype.createToolbarButton=function(a,b){var c=document.createElement("button");c.setAttribute("type","button");c.className="netgis-hover-light";c.innerHTML=a;c.addEventListener("click",b);return c};
 netgis.Toolbar.prototype.createToolbarCheckbox=function(a,b){var c=document.createElement("label");c.className="netgis-hover-light";var d=document.createElement("input");d.setAttribute("type","checkbox");d.addEventListener("change",b);c.appendChild(d);a=document.createTextNode(a);c.appendChild(a);return c};
-netgis.Toolbar.prototype.createToolbarInput=function(a,b,c){var d=document.createElement("label");d.className="netgis-hover-light";a=document.createTextNode(a);d.appendChild(a);a=document.createElement("input");a.setAttribute("type","number");a.setAttribute("min",0);a.value=b;a.addEventListener("change",c);d.appendChild(a);return d};
+netgis.Toolbar.prototype.createToolbarInput=function(a,b,c){var d=document.createElement("label");d.className="netgis-hover-light";a=document.createTextNode(a);d.appendChild(a);a=document.createElement("input");a.setAttribute("type","number");a.setAttribute("min",0);a.value=b;a.addEventListener("change",c);a.addEventListener("keyup",c);d.appendChild(a);return d};
 netgis.Toolbar.prototype.createToolbarInputText=function(a,b,c){var d=document.createElement("label");d.className="netgis-hover-light";var e=document.createElement("input");e.setAttribute("type","text");e.setAttribute("placeholder",a);e.value=b;c&&e.addEventListener("change",c);d.appendChild(e);return d};
 netgis.Toolbar.prototype.onSetMode=function(a){var b=!this.toolbars[netgis.Modes.SEARCH_PLACE].classList.contains("netgis-hide");netgis.util.foreach(this.toolbars,function(b,d){b===a?d.classList.remove("netgis-hide"):d.classList.add("netgis-hide")});switch(a){case netgis.Modes.SEARCH_PLACE:b?this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.VIEW):this.searchInput.focus();break;case netgis.Modes.BUFFER_FEATURE_EDIT:this.updateBuffer();break;case netgis.Modes.DRAW_POINTS:case netgis.Modes.DRAW_LINES:this.toolbars[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[1].checked&&
 this.client.invoke(netgis.Events.DRAW_BUFFER_ON,null)}};netgis.Toolbar.prototype.onToolbarClose=function(a){this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.VIEW)};netgis.Toolbar.prototype.searchRequest=function(a){a=a.trim();a!==this.searchValue&&(this.searchValue=a,0<a.length&&this.client.invoke(netgis.Events.SEARCH_PLACE_REQUEST,{query:a}))};netgis.Toolbar.prototype.searchClear=function(){this.searchInput.value="";this.searchList.innerHTML=""};
@@ -244,10 +286,44 @@ netgis.Toolbar.prototype.updateBuffer=function(){var a=this.toolbars[netgis.Mode
 netgis.Toolbar.prototype.onBufferAccept=function(a){this.client.invoke(netgis.Events.BUFFER_ACCEPT,null);this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.VIEW)};netgis.Toolbar.prototype.onBufferCancel=function(a){this.client.invoke(netgis.Events.BUFFER_CANCEL,null);this.client.invoke(netgis.Events.SET_MODE,netgis.Modes.VIEW)};
 netgis.Toolbar.prototype.onSnapChange=function(a){a=a.target.checked;this.toolbars[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[0].checked=a;this.toolbars[netgis.Modes.DRAW_LINES].getElementsByTagName("input")[0].checked=a;this.toolbars[netgis.Modes.DRAW_POLYGONS].getElementsByTagName("input")[0].checked=a;this.client.invoke(a?netgis.Events.SNAP_ON:netgis.Events.SNAP_OFF,null)};
 netgis.Toolbar.prototype.onTracingChange=function(a){a=a.target.checked;var b=this.toolbars[netgis.Modes.DRAW_POLYGONS].getElementsByTagName("input")[0],c=b.checked;a&&!c&&(b.checked=a,this.client.invoke(netgis.Events.SNAP_ON,null));this.client.invoke(a?netgis.Events.TRACING_ON:netgis.Events.TRACING_OFF,null)};
-netgis.Toolbar.prototype.onDrawBufferChange=function(a){a=a.target.checked;this.toolbars[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[1].checked=a;this.toolbars[netgis.Modes.DRAW_LINES].getElementsByTagName("input")[1].checked=a;this.client.invoke(a?netgis.Events.DRAW_BUFFER_ON:netgis.Events.DRAW_BUFFER_OFF,null);this.showDrawBufferOptions(a)};
+netgis.Toolbar.prototype.onDrawBufferChange=function(a){a=a.target.checked;this.toolbars[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[1].checked=a;this.toolbars[netgis.Modes.DRAW_LINES].getElementsByTagName("input")[1].checked=a;this.client.invoke(a?netgis.Events.DRAW_BUFFER_ON:netgis.Events.DRAW_BUFFER_OFF,null);this.showDrawBufferOptions(a);if(a){a=!0;this.toolbars[netgis.Modes.DRAW_LINES].classList.contains("netgis-hide")||(a=!1);var b=this.toolbars[a?netgis.Modes.DRAW_POINTS:netgis.Modes.DRAW_LINES].getElementsByTagName("input");
+a=Number.parseInt(b[2].value);b=Number.parseInt(b[3].value);this.client.invoke(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE,a);this.client.invoke(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,b)}};
 netgis.Toolbar.prototype.onDrawBufferRadiusChange=function(a){a=a.target;var b=Number.parseFloat(a.value);this.client.invoke(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE,b);var c=this.toolbars[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[2];a!==c&&(c.value=b);c=this.toolbars[netgis.Modes.DRAW_LINES].getElementsByTagName("input")[2];a!==c&&(c.value=b)};
 netgis.Toolbar.prototype.onDrawBufferSegmentsChange=function(a){a=a.target;var b=Number.parseInt(a.value);this.client.invoke(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE,b);var c=this.toolbars[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[3];a!==c&&(c.value=b);c=this.toolbars[netgis.Modes.DRAW_LINES].getElementsByTagName("input")[3];a!==c&&(c.value=b)};
-netgis.Toolbar.prototype.showDrawBufferOptions=function(a){var b=this.toolbars[netgis.Modes.DRAW_POINTS].children[0].children,c=this.toolbars[netgis.Modes.DRAW_LINES].children[0].children;a?(b[3].classList.remove("netgis-hide"),b[4].classList.remove("netgis-hide"),c[3].classList.remove("netgis-hide"),c[4].classList.remove("netgis-hide")):(b[3].classList.add("netgis-hide"),b[4].classList.add("netgis-hide"),c[3].classList.add("netgis-hide"),c[4].classList.add("netgis-hide"))};netgis=netgis||{};
-netgis.util=function(){var a=function(a,c){for(var b in a)a.hasOwnProperty(b)&&c(b,a[b])};return{isDefined:function(a){return"undefined"!==typeof a},isString:function(a){return"string"===typeof a||a instanceof String},replace:function(a,c,d){return a.replace(new RegExp(c,"g"),d)},foreach:a,template:function(b,c){a(c,function(a,c){b=b.replace(new RegExp("{"+a+"}","g"),c)});return b},newlines:function(a){return a.replace(/\n/g,"<br />")},create:function(a){var b=document.createElement("tbody");b.innerHTML=
-a;return b.children[0]},size:function(a){a=(new TextEncoder).encode(JSON.stringify(a)).length;var b=a/1024;return{bytes:a,kilobytes:b,megabytes:b/1024}},request:function(a,c){var b=new XMLHttpRequest;b.onload=function(){c(this.responseText)};b.open("GET",a,!0);b.send()},padstr:function(a,c){for(a=a.toString();a.length<c;)a="0"+a;return a},merge:function(a,c){return Object.assign(a,c)},getTimeStamp:function(){var a=new Date,c=a.getDate()+"."+(a.getMonth()+1)+"."+a.getFullYear();return c+=" "+a.getHours()+
-":"+a.getMinutes()},formatArea:function(a,c){var b=1E4<a;a=b?c?Math.round(a/1E6*1E3)/1E3:Math.round(a/1E6):c?Math.round(100*a)/100:Math.round(a);0===a&&(b=!1);return a+(b?" qkm":" qm")}}}();
+netgis.Toolbar.prototype.showDrawBufferOptions=function(a){var b=this.toolbars[netgis.Modes.DRAW_POINTS].children[0].children,c=this.toolbars[netgis.Modes.DRAW_LINES].children[0].children;a?(b[3].classList.remove("netgis-hide"),b[4].classList.remove("netgis-hide"),c[3].classList.remove("netgis-hide"),c[4].classList.remove("netgis-hide")):(b[3].classList.add("netgis-hide"),b[4].classList.add("netgis-hide"),c[3].classList.add("netgis-hide"),c[4].classList.add("netgis-hide"))};netgis=netgis||{};netgis.Toolbox=function(a){this.initElements(a);this.initEvents()};
+netgis.Toolbox.prototype.initElements=function(a){this.container=document.createElement("section");this.container.className="netgis-toolbox";var b=document.createElement("section");this.container.appendChild(b);this.top=b;this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-hand-paper'></i><span>Betrachten</span>",netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.VIEW));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-map-marker-alt'></i><span>Punkte</span>",
+netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.DRAW_POINTS));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-minus'></i><span>Linien</span>",netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.DRAW_LINES));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-vector-square'></i><span>Polygone</span>",netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.DRAW_POLYGONS));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-cut'></i><span>Ausschneiden</span>",
+netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.CUT_FEATURE_BEGIN));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-arrows-alt'></i><span>Verschieben</span>",netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.MODIFY_FEATURES));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-eraser'></i><span>L\u00f6schen</span>",netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.DELETE_FEATURES));this.addButton(this.top,"<i class='netgis-icon netgis-text-a far fa-dot-circle'></i><span>Puffern</span>",
+netgis.util.handler(netgis.Events.SET_MODE,netgis.Modes.BUFFER_FEATURE_BEGIN));this.addButton(this.top,"<i class='netgis-icon netgis-text-a fas fa-file-download'></i><span>Exportieren</span>",netgis.util.handler(netgis.Events.EXPORT_SHOW));b=document.createElement("section");b.className="netgis-hide";this.container.appendChild(b);this.bottom=b;var c=document.createElement("button");c.className="netgis-button netgis-clip-text netgis-color-c";c.innerHTML="<span>Einstellungen</span><i class='netgis-icon fas fa-times'></i>";
+c.setAttribute("type","button");c.addEventListener("click",this.onBottomHeaderClick.bind(this));b.appendChild(c);this.bottomTitle=c.getElementsByTagName("span")[0];this.bottomPanels={};b=a.tools.buffer.defaultRadius;a=a.tools.buffer.defaultSegments;c=document.createElement("div");this.addCheckbox(c,"Einrasten",netgis.util.handler(netgis.Events.SNAP_TOGGLE));this.addCheckbox(c,"Puffern",netgis.util.handler(netgis.Events.BUFFER_TOGGLE));this.addInputNumber(c,"Radius (Meter):",b,netgis.util.handler(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE));
+this.addInputNumber(c,"Segmente:",a,netgis.util.handler(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE));this.bottomPanels[netgis.Modes.DRAW_POINTS]=c;c=document.createElement("div");this.addCheckbox(c,"Einrasten",netgis.util.handler(netgis.Events.SNAP_TOGGLE));this.addCheckbox(c,"Puffern",netgis.util.handler(netgis.Events.BUFFER_TOGGLE));this.addInputNumber(c,"Radius (Meter):",b,netgis.util.handler(netgis.Events.DRAW_BUFFER_RADIUS_CHANGE));this.addInputNumber(c,"Segmente:",a,netgis.util.handler(netgis.Events.DRAW_BUFFER_SEGMENTS_CHANGE));
+this.bottomPanels[netgis.Modes.DRAW_LINES]=c;c=document.createElement("div");this.addCheckbox(c,"Einrasten",netgis.util.handler(netgis.Events.SNAP_TOGGLE));this.addCheckbox(c,"Tracing",netgis.util.handler(netgis.Events.TRACING_TOGGLE));this.bottomPanels[netgis.Modes.DRAW_POLYGONS]=c;c=document.createElement("div");this.addInputNumber(c,"Radius (Meter):",b,this.onBufferFeatureChange.bind(this));this.addInputNumber(c,"Segmente:",a,this.onBufferFeatureChange.bind(this));this.addButton(c,"<i class='netgis-icon netgis-text-a fas fa-arrow-circle-right'></i><span>Akzeptieren</span>",
+this.onBufferFeatureAccept.bind(this));this.bottomPanels[netgis.Modes.BUFFER_FEATURE_EDIT]=c;b=document.createElement("div");this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-upload'></i><span>Shapefile</span>",netgis.util.handler(netgis.Events.IMPORT_SHAPEFILE_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-upload'></i><span>GeoJSON</span>",netgis.util.handler(netgis.Events.IMPORT_GEOJSON_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-upload'></i><span>GML</span>",
+netgis.util.handler(netgis.Events.IMPORT_GML_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-upload'></i><span>Spatialite</span>",netgis.util.handler(netgis.Events.IMPORT_SPATIALITE_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-upload'></i><span>Geopackage</span>",netgis.util.handler(netgis.Events.IMPORT_GEOPACKAGE_SHOW));this.bottomPanels[netgis.Modes.IMPORT]=b;b=document.createElement("div");this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-download'></i><span>PDF</span>",
+netgis.util.handler(netgis.Events.EXPORT_PDF_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-download'></i><span>JPEG</span>",netgis.util.handler(netgis.Events.EXPORT_JPEG_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-download'></i><span>PNG</span>",netgis.util.handler(netgis.Events.EXPORT_PNG_SHOW));this.addButton(b,"<i class='netgis-icon netgis-text-a fas fa-file-download'></i><span>GIF</span>",netgis.util.handler(netgis.Events.EXPORT_GIF_SHOW));
+this.bottomPanels[netgis.Modes.EXPORT]=b;this.setBuffer(!1)};netgis.Toolbox.prototype.initEvents=function(){this.resizeObserver=(new ResizeObserver(this.onTopResize.bind(this))).observe(this.top)};netgis.Toolbox.prototype.attach=function(a){a.appendChild(this.container)};
+netgis.Toolbox.prototype.addButton=function(a,b,c){var d=document.createElement("button");d.className="netgis-button netgis-clip-text netgis-color-e netgis-hover-a";d.innerHTML=b;d.setAttribute("type","button");c&&(d.onclick=c);a&&a.appendChild(d);return d};
+netgis.Toolbox.prototype.addCheckbox=function(a,b,c){var d=document.createElement("label");d.className="netgis-noselect netgis-hover-a";var e=document.createElement("input");e.setAttribute("type","checkbox");d.appendChild(e);var f=document.createElement("span");f.innerHTML=b;d.appendChild(f);c&&(e.onchange=c);a&&a.appendChild(d);return e};
+netgis.Toolbox.prototype.addInputNumber=function(a,b,c,d){var e=document.createElement("label");e.className="netgis-noselect netgis-hover-a";var f=document.createElement("span");f.innerHTML=b;e.appendChild(f);b=document.createElement("input");b.setAttribute("type","number");b.setAttribute("min",0);b.value=c;e.appendChild(b);d&&(b.onchange=d,b.onkeyup=d);a&&a.appendChild(e);return b};
+netgis.Toolbox.prototype.setMode=function(a){for(var b=this.top.getElementsByTagName("button"),c=0;c<b.length;c++)b[c].classList.remove("netgis-bold");for(var d in this.bottomPanels)c=this.bottomPanels[d],c.parentNode===this.bottom&&this.bottom.removeChild(c);switch(a){case netgis.Modes.VIEW:b[0].classList.add("netgis-bold");this.bottomTitle.innerHTML="";break;case netgis.Modes.DRAW_POINTS:b[1].classList.add("netgis-bold");this.bottomTitle.innerHTML="Punkte";break;case netgis.Modes.DRAW_LINES:b[2].classList.add("netgis-bold");
+this.bottomTitle.innerHTML="Linien";break;case netgis.Modes.DRAW_POLYGONS:b[3].classList.add("netgis-bold");this.bottomTitle.innerHTML="Polygone";break;case netgis.Modes.CUT_FEATURE_BEGIN:case netgis.Modes.CUT_FEATURE_DRAW:b[4].classList.add("netgis-bold");this.bottomTitle.innerHTML="Ausschneiden";break;case netgis.Modes.MODIFY_FEATURES:b[5].classList.add("netgis-bold");this.bottomTitle.innerHTML="Verschieben";break;case netgis.Modes.DELETE_FEATURES:b[6].classList.add("netgis-bold");this.bottomTitle.innerHTML=
+"L\u00f6schen";break;case netgis.Modes.BUFFER_FEATURE_BEGIN:case netgis.Modes.BUFFER_FEATURE_EDIT:b[7].classList.add("netgis-bold");this.bottomTitle.innerHTML="Puffern";break;case netgis.Modes.IMPORT:b[8].classList.add("netgis-bold");this.bottomTitle.innerHTML="Importieren";break;case netgis.Modes.EXPORT:b[9].classList.add("netgis-bold"),this.bottomTitle.innerHTML="Exportieren"}(c=this.bottomPanels[a])?(this.bottom.appendChild(c),this.showBottom()):this.hideBottom()};
+netgis.Toolbox.prototype.setSnap=function(a){this.bottomPanels[netgis.Modes.DRAW_POINTS].getElementsByTagName("input")[0].checked=a;this.bottomPanels[netgis.Modes.DRAW_LINES].getElementsByTagName("input")[0].checked=a;this.bottomPanels[netgis.Modes.DRAW_POLYGONS].getElementsByTagName("input")[0].checked=a};
+netgis.Toolbox.prototype.setBuffer=function(a){var b=this.bottomPanels[netgis.Modes.DRAW_POINTS].getElementsByTagName("label"),c=this.bottomPanels[netgis.Modes.DRAW_LINES].getElementsByTagName("label");b[1].getElementsByTagName("input")[0].checked=a;(c[1].getElementsByTagName("input")[0].checked=a)?(b[2].classList.remove("netgis-hide"),b[3].classList.remove("netgis-hide"),c[2].classList.remove("netgis-hide"),c[3].classList.remove("netgis-hide")):(b[2].classList.add("netgis-hide"),b[3].classList.add("netgis-hide"),
+c[2].classList.add("netgis-hide"),c[3].classList.add("netgis-hide"))};netgis.Toolbox.prototype.setBufferRadius=function(a){var b=this.bottomPanels[netgis.Modes.DRAW_POINTS].getElementsByTagName("input"),c=this.bottomPanels[netgis.Modes.DRAW_LINES].getElementsByTagName("input");b[2].value=a;c[2].value=a};
+netgis.Toolbox.prototype.setBufferSegments=function(a){var b=this.bottomPanels[netgis.Modes.DRAW_POINTS].getElementsByTagName("input"),c=this.bottomPanels[netgis.Modes.DRAW_LINES].getElementsByTagName("input");b[3].value=a;c[3].value=a};netgis.Toolbox.prototype.showBottom=function(){this.top.classList.add("netgis-resize-bottom");this.top.style.height="50%";this.top.style.bottom="auto";this.bottom.classList.remove("netgis-hide")};
+netgis.Toolbox.prototype.hideBottom=function(){this.top.classList.remove("netgis-resize-bottom");this.top.style.height="auto";this.top.style.bottom="0mm";this.bottom.classList.add("netgis-hide")};netgis.Toolbox.prototype.onTopResize=function(a){if(!this.bottom.classList.contains("netgis-hide")){a=this.top.getBoundingClientRect();var b=this.top.parentNode.getBoundingClientRect();this.bottom.style.top=a.bottom-b.top+"px"}};
+netgis.Toolbox.prototype.onBottomHeaderClick=function(a){netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.VIEW)};netgis.Toolbox.prototype.onBufferFeatureChange=function(a){var b=this.bottomPanels[netgis.Modes.BUFFER_FEATURE_EDIT].getElementsByTagName("input");a=Number.parseFloat(b[0].value);b=Number.parseInt(b[1].value);netgis.util.invoke(this.container,netgis.Events.BUFFER_CHANGE,{radius:a,segments:b})};
+netgis.Toolbox.prototype.onBufferFeatureAccept=function(a){netgis.util.invoke(this.container,netgis.Events.BUFFER_ACCEPT,null);netgis.util.invoke(this.container,netgis.Events.SET_MODE,netgis.Modes.VIEW)};netgis=netgis||{};netgis.Tree=function(){this.initElements()};netgis.Tree.Events=Object.freeze({ITEM_CHANGE:"item-change"});netgis.Tree.prototype.initElements=function(){var a=document.createElement("ul");a.className="netgis-tree";this.container=a};netgis.Tree.prototype.attach=function(a){a.appendChild(this.container)};
+netgis.Tree.prototype.addFolder=function(a,b,c,d){var e=document.createElement("li");e.className="netgis-folder";e.setAttribute("data-id",b);b=document.createElement("details");e.appendChild(b);var f=document.createElement("summary");f.className="netgis-button netgis-noselect netgis-clip-text netgis-color-e netgis-hover-a";f.innerHTML="<i class='netgis-icon netgis-hide-open fas fa-folder'></i><i class='netgis-icon netgis-show-open fas fa-folder-open'></i><span>"+c+"</span>";b.appendChild(f);c=document.createElement("label");
+f.appendChild(c);f=document.createElement("input");f.setAttribute("type","checkbox");f.onchange=this.onFolderChange.bind(this);c.appendChild(f);c=document.createElement("ul");b.appendChild(c);a=a?a.getElementsByTagName("ul")[0]:this.container;d?a.insertBefore(e,a.firstChild):a.appendChild(e);return e};
+netgis.Tree.prototype.addCheckbox=function(a,b,c){var d=document.createElement("li");d.className="netgis-item";var e=document.createElement("label");e.className="netgis-button netgis-noselect netgis-clip-text netgis-color-e netgis-hover-a";e.innerHTML="<span>"+c+"</span>";d.appendChild(e);c=document.createElement("input");c.setAttribute("type","checkbox");c.setAttribute("data-id",b);c.onchange=this.onItemChange.bind(this);e.insertBefore(c,e.firstChild);a?a.getElementsByTagName("ul")[0].appendChild(d):
+this.container.appendChild(d);return d};netgis.Tree.prototype.addButton=function(a,b,c){var d=document.createElement("li"),e=document.createElement("button");e.innerHTML=b;e.className="netgis-button netgis-color-e netgis-text-a netgis-hover-a netgis-clip-text";e.setAttribute("type","button");d.appendChild(e);c&&(e.onclick=c);a?a.getElementsByTagName("ul")[0].appendChild(d):this.container.appendChild(d);return d};
+netgis.Tree.prototype.setItemChecked=function(a,b){var c=this.container.getElementsByClassName("netgis-item");a=a.toString();for(var d=0;d<c.length;d++){var e=c[d].getElementsByTagName("input")[0];e.getAttribute("data-id")===a&&e.checked!==b&&e.click()}};netgis.Tree.prototype.setFolderParent=function(a,b){var c=a.parentNode;c&&c.removeChild(a);null!==b?b.getElementsByTagName("ul")[0].appendChild(a):this.container.appendChild(a)};
+netgis.Tree.prototype.updateFolderCheck=function(a){a||(a=this.container);for(var b=a.getElementsByClassName("netgis-item"),c=0,d=0;d<b.length;d++){var e=b[d].getElementsByTagName("input")[0];e.checked&&c++}e=a.getElementsByTagName("input")[0];d=0;0<c&&(d=1);c===b.length&&(d=2);switch(d){case 0:e.checked=!1;e.classList.remove("netgis-partial");break;case 1:e.checked=!0;e.classList.add("netgis-partial");break;case 2:e.checked=!0,e.classList.remove("netgis-partial")}(a=a.parentElement)&&a!==this.container&&
+(a=a.parentElement.parentElement)&&-1!==a.className.search("netgis-folder")&&this.updateFolderCheck(a)};netgis.Tree.prototype.onFolderChange=function(a){var b=a.currentTarget;a=b.checked;b=b.parentElement.parentElement.parentElement.parentElement;for(var c=b.getElementsByTagName("input"),d=1;d<c.length;d++){var e=c[d];e.checked!==a&&e.click()}this.updateFolderCheck(b);a=b.parentElement.parentElement.parentElement;-1!==a.className.search("netgis-folder")&&this.updateFolderCheck(a)};
+netgis.Tree.prototype.onItemChange=function(a){a=a.currentTarget;var b=a.checked,c=a.getAttribute("data-id"),d=Number.parseInt(c);Number.isNaN(d)||(c=d);d=a.parentElement.parentElement.parentElement.parentElement.parentElement;netgis.util.invoke(a,netgis.Tree.Events.ITEM_CHANGE,{id:c,checked:b});-1!==d.className.search("netgis-folder")&&this.updateFolderCheck(d)};netgis=netgis||{};
+netgis.util=function(){var a=function(a,b){for(var c in a)a.hasOwnProperty(c)&&b(c,a[c])},b=function(){return navigator.language||"de-DE"};return{isDefined:function(a){return"undefined"!==typeof a},isString:function(a){return"string"===typeof a||a instanceof String},replace:function(a,b,e){return a.replace(new RegExp(b,"g"),e)},foreach:a,template:function(b,d){a(d,function(a,c){b=b.replace(new RegExp("{"+a+"}","g"),c)});return b},newlines:function(a){return a.replace(/\n/g,"<br />")},create:function(a){var b=
+document.createElement("tbody");b.innerHTML=a;return b.children[0]},size:function(a){a=(new TextEncoder).encode(JSON.stringify(a)).length;var b=a/1024;return{bytes:a,kilobytes:b,megabytes:b/1024}},request:function(a,b){var c=new XMLHttpRequest;c.onload=function(){b(this.responseText)};c.open("GET",a,!0);c.send()},padstr:function(a,b){for(a=a.toString();a.length<b;)a="0"+a;return a},merge:function(a,b){return Object.assign(a,b)},getTimeStamp:function(a){var b=new Date;if(!0===a){a=b.getFullYear();
+var c=b.getMonth()+1,f=b.getDate(),g=b.getHours(),h=b.getMinutes();b=b.getSeconds();10>c&&(c="0"+c);10>f&&(f="0"+f);10>g&&(g="0"+g);10>h&&(h="0"+h);10>b&&(b="0"+b);a=[a,c,f,"_",g,h,b].join("")}else a=b.getDate()+"."+(b.getMonth()+1)+"."+b.getFullYear(),a+=" "+b.getHours()+":"+b.getMinutes();return a},getUserLanguage:b,getFileExtension:function(a){a=a.split(".");return 1>=a.length?"":a[a.length-1]},formatArea:function(a,d,e,f){a=(e=a>(e||1E5))?d?Math.round(a/1E6*1E3)/1E3:Math.round(a/1E6):d?Math.round(100*
+a)/100:Math.round(a);0===a&&(e=!1);a=a.toLocaleString(b());return a+(e?" km\u00b2":" m\u00b2")},invoke:function(a,b,e){a.dispatchEvent(new CustomEvent(b,{bubbles:!0,detail:e}))},handler:function(a,b){return function(c){b||(b=c);netgis.util.invoke(this,a,b)}}}}();