[Mapbender-commits] r1026 - trunk/mapbender/http/javascripts

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Wed Jan 24 08:08:13 EST 2007


Author: christoph
Date: 2007-01-24 08:08:13 -0500 (Wed, 24 Jan 2007)
New Revision: 1026

Modified:
   trunk/mapbender/http/javascripts/mod_digitize_tab.php
Log:
add ajax style digitization

Modified: trunk/mapbender/http/javascripts/mod_digitize_tab.php
===================================================================
--- trunk/mapbender/http/javascripts/mod_digitize_tab.php	2007-01-24 13:05:32 UTC (rev 1025)
+++ trunk/mapbender/http/javascripts/mod_digitize_tab.php	2007-01-24 13:08:13 UTC (rev 1026)
@@ -19,8 +19,8 @@
 
 session_start();
 import_request_variables("PG");
-require_once(dirname(__FILE__)."/../php/mb_validateSession.php");
-require_once(dirname(__FILE__)."/../../conf/mapbender.conf");
+require_once("../php/mb_validateSession.php");
+require_once("../../conf/mapbender.conf");
 $con = db_connect($DBSERVER,$OWNER,$PW);
 db_select_db(DB,$con);
 $gui_id = $_SESSION["mb_user_gui"];
@@ -38,7 +38,7 @@
 ?>
 <title>Digitize</title>
 <?php
-$digitize_conf_filename = "digitize.conf";
+$digitize_conf_filename = "digitize_default.conf";
 include '../include/dyn_css.php';
 
 $con = db_connect($DBSERVER,$OWNER,$PW);
@@ -53,26 +53,22 @@
 	$e_target = explode(",",$row["e_target"]);
 	$cnt++;
 }
-echo "<script type='text/javascript'><!--\n";
+if($cnt > 1) echo "alert('digitize_button: ID not unique!');";
 
-if($cnt > 1){
-	echo "alert('digitize_button: ID not unique!');";
-}
-
-echo "var mod_digitize_target = '".$e_target[0]."';\n";
-echo "var mod_digitize_frame = '".$e_target[1]."';\n";
-require_once(dirname(__FILE__)."/mod_geometryArray.js");
-require_once(dirname(__FILE__)."/mod_highlight.php");
-#require_once(dirname(__FILE__)."/../../conf/" . $digitize_conf_filename);
+echo "<script language='JavaScript'>";
+echo "var mod_digitize_target = '".$e_target[0]."';";
+echo "var mod_digitize_frame = '".$e_target[1]."';";
+include("../../conf/" . $digitize_conf_filename);
 ?>
 
 var wfsWindow;	
 var dwin = null;
 var wfs_conf = new Array();
-var d = new GeometryArray();
+var d = new parent.GeometryArray();
 var mod_digitize_width;
 var mod_digitize_height;
 var mod_digitizeEvent = false;
+var digi_hl;
 
 var button_point = "Point";
 var button_line = "Line";
@@ -80,16 +76,19 @@
 var button_move = "dragBasePoint";
 var button_insert = "setBasePoint";
 var button_delete = "delBasePoint";
+var button_clear = "clear";
+var button_combine = "combine";
 
-
 try {if(mod_digitize_elName){}}catch(e) {mod_digitize_elName = "digitize";}
 
 // ------------------------------------------------------------------------------------------------------------------------
 // --- polygon, line, point insertion (begin) ----------------------------------------------------------------------------------------------
 
-function appendGeometry(obj) {
+function appendGeometryArray(obj) {
 	executeDigitizePreFunctions();
-	d.appendMember(obj);
+	for (i=0; i<obj.count(); i++) {
+		d.appendMember(obj.get(i));
+	}
 	executeDigitizeSubFunctions();
 }
 
@@ -105,7 +104,7 @@
 	if (e) {
 		// track mouse position
 		parent.mb_getMousePos(e, mod_digitize_target);
-		var currentPos = new Point(parent.clickX, parent.clickY);
+		var currentPos = new parent.Point(parent.clickX, parent.clickY);
 		s.check(currentPos);
 	}
 	else {
@@ -141,15 +140,15 @@
 	}
 	else {
 		parent.mb_getMousePos(e,mod_digitize_target);
-		realWorldPos = mapToReal(mod_digitize_target,new Point(parent.clickX,parent.clickY));
+		realWorldPos = parent.mapToReal(mod_digitize_target,new parent.Point(parent.clickX,parent.clickY));
 	}
 	
-	if (d.get(-1).geomtype == geomTypePolygon && d.getGeometry(-1,-1).count() > 1 && d.getGeometry(-1,-1).get(0).equals(realWorldPos)) {
+	if (d.get(-1).geomtype == parent.geomTypePolygon && d.getGeometry(-1,-1).count() > 1 && d.getGeometry(-1,-1).get(0).equals(realWorldPos)) {
 				
 		// close the polygon
 		parent.mb_disableThisButton(button_polygon);
 	}
-	else if (d.get(-1).geomtype == geomTypeLine && d.getGeometry(-1,-1).count() > 1 && d.getGeometry(-1,-1).get(-1).equals(realWorldPos)) {
+	else if (d.get(-1).geomtype == parent.geomTypeLine && d.getGeometry(-1,-1).count() > 1 && d.getGeometry(-1,-1).get(-1).equals(realWorldPos)) {
 		// close the line
 		parent.mb_disableThisButton(button_line);
 	}
@@ -157,18 +156,20 @@
 		// set the calculated real world position as point of the geometry
 		d.getGeometry(-1,-1).addPoint(realWorldPos);
 		
-		if(d.get(-1).geomtype == geomTypePoint){
+		if(d.get(-1).geomtype == parent.geomTypePoint){
 			parent.mb_disableThisButton(button_point);
 		}
 		
 		// add first point of polygon to snapping list (if three points have been inserted).
-		else if (d.get(-1).geomtype == geomTypePolygon && d.getGeometry(-1,-1).count() == 3) {
+		else if (d.get(-1).geomtype == parent.geomTypePolygon && d.getGeometry(-1,-1).count() == 3) {
 			s.add(d, 0, -1, -1)
 		}
 
 		// add last point of line to snapping list (if at least two points have been inserted).
-		else if (d.get(-1).geomtype == geomTypeLine && d.getGeometry(-1,-1).count() >= 2) {
-			s.store(d, mod_digitizeEvent);
+		else if (d.get(-1).geomtype == parent.geomTypeLine && d.getGeometry(-1,-1).count() >= 2) {
+			if (mod_digitizeEvent != button_move) {
+				s.store(d);
+			}
 			s.add(d, -1, -1, -1)
 		}
 	}
@@ -230,7 +231,7 @@
 	
 	parent.mb_getMousePos(e, mod_digitize_target);
 	var pos = parent.makeClickPos2RealWorldPos(mod_digitize_target,parent.clickX, parent.clickY);
-	var p = new Point(pos[0], pos[1]);
+	var p = new parent.Point(pos[0], pos[1]);
 	d.getGeometry(i,j).addPointAtIndex(p, k);
 
 	executeDigitizeSubFunctions();
@@ -248,7 +249,7 @@
 function selectBasepoint(e){
 	if(basepointDragActive == false && mod_digitizeEvent == button_move){
 		basepointDragActive = true;
-		s.store(d, mod_digitizeEvent, d.getPoint(basepointMemberIndex, basepointGeometryIndex, basepointPointIndex));
+		s.store(d, d.getPoint(basepointMemberIndex, basepointGeometryIndex, basepointPointIndex));
 		basepointObject.onmouseup = releaseBasepoint;
 		basepointObject.onmousemove = dragBasepoint;
 	}
@@ -257,7 +258,7 @@
 function dragBasepoint(e){
 	if(basepointDragActive){
 		parent.mb_getMousePos(e, mod_digitize_target);
-		var currentPos = new Point(parent.clickX, parent.clickY);
+		var currentPos = new parent.Point(parent.clickX, parent.clickY);
 		var res = s.check(currentPos);
 
 		// replace basepoint by transparent blob
@@ -276,6 +277,15 @@
 	}
 }
 	
+function updateAllPointsOfNonTransactionalLike(oldP, newP){ 
+	for (var i = 0; i < d.count(); i++) {
+		if (isTransactional(d.get(i))) {
+			d.get(i).updateAllPointsLike(oldP, newP);
+		}
+	}
+}
+
+	
 function releaseBasepoint(e){
 	
 	var i = basepointMemberIndex;
@@ -284,19 +294,29 @@
 	basepointDragActive = false;
 	
 	parent.mb_getMousePos(e, mod_digitize_target);
-	var basepointDragEnd = new Point(parent.clickX, parent.clickY);
+	var basepointDragEnd = new parent.Point(parent.clickX, parent.clickY);
 	basepointObject.onmousedown = null;
 	var p = parent.makeClickPos2RealWorldPos(mod_digitize_target, basepointDragEnd.x, basepointDragEnd.y);
 
-	var oldPoint = cloneObject(d.getPoint(i,j,k));
+	var oldPoint = parent.cloneObject(d.getPoint(i,j,k));
 	if (s.isSnapped() == true) {
-		var snappedPoint = cloneObject(s.getSnappedPoint(d));
-		d.updateAllPointsLike(oldPoint, snappedPoint);
+		var snappedPoint = parent.cloneObject(s.getSnappedPoint(d));
+		if (nonTransactionalEditable == false) {
+			updateAllPointsOfNonTransactionalLike(oldPoint, snappedPoint);
+		}
+		else {
+			d.updateAllPointsLike(oldPoint, snappedPoint);
+		}
 		s.clean();
 	}
 	else {
-		var newPoint = new Point(p[0],p[1]);
-		d.updateAllPointsLike(oldPoint, newPoint);
+		var newPoint = new parent.Point(p[0],p[1]);
+		if (nonTransactionalEditable == false) {
+			updateAllPointsOfNonTransactionalLike(oldPoint, newPoint);
+		}
+		else {
+			d.updateAllPointsLike(oldPoint, newPoint);
+		}
 	}
 	basepointMemberIndex = null;
 	basepointGeometryIndex = null;
@@ -340,8 +360,12 @@
 	parent.mb_registerInitFunctions("window.frames['"+ mod_digitize_elName + "'].setStyleForTargetFrame()");
 	parent.mb_registerInitFunctions("window.frames['"+ mod_digitize_elName + "'].checkDigitizeTag()");
 	parent.mb_registerInitFunctions("window.frames['"+ mod_digitize_elName + "'].initialiseSnapping()");
+	parent.mb_registerInitFunctions("window.frames['"+ mod_digitize_elName + "'].initialiseHighlight()");
 	parent.mb_registerSubFunctions("window.frames['" + mod_digitize_elName + "'].updateExtent()");
 	parent.mb_registerSubFunctions("window.frames['"+ mod_digitize_elName + "'].drawDashedLine()");
+	parent.mb_registerWfsReadSubFunctions(function(geom){parent.tab_open(mod_digitize_elName);parent.window.frames[mod_digitize_elName].appendGeometryArray(geom)});
+	parent.mb_registerWfsWriteSubFunctions(function(){parent.zoom(mod_digitize_target, true, 0.999)});
+	
 }
 
 function checkDigitizeTag(){
@@ -366,10 +390,11 @@
 }
 
 function initialiseSnapping(){
-//	try {if(snappingTolerance){}}catch(e) {var snappingTolerance;}
-//	try {if(snappingColor){}}catch(e) {var snappingColor;}
-	s = new Snapping(mod_digitize_target, snappingTolerance, snappingColor, true);
+	s = new parent.Snapping(mod_digitize_target, snappingTolerance, snappingColor, true);
 }
+function initialiseHighlight(){
+	digi_hl = new parent.Highlight(new Array(mod_digitize_target), "digi_hl");
+}
 // --- registered functions (end) -----------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------------------------------
 
@@ -377,17 +402,11 @@
 // --- button handling (begin) --------------------------------------------------------------------------------------------
 
 function displayButtons(){
-//	try {if(geomList_x){}}catch(e) {var geomList_x = 10;}
-//	try {if(geomList_y){}}catch(e) {var geomList_y = 10;}
-//	try {if(buttonDig_id.length){}}catch(e) {var buttonDig_id = new Array();alert("exception: no digitisation buttons found in element vars.")}
 	for (var i = 0 ; i < buttonDig_id.length ; i ++) {
 		if (parseInt(buttonDig_on[i])==1) {
 			var divTag = document.createElement("div");
 			divTag.setAttribute("id", "div_" + buttonDig_id[i]);
 // FIREFOX 
-//			divTag.setAttribute("style", "position:absolute; top:"+buttonDig_y[i]+"px; left:"+buttonDig_x[i]+"px;", 0);
-//			var tagContent = "<img name=\""+buttonDig_id[i]+"\" onmouseover=\"parent.mb_regButton_frame('initDigButton', mod_digitize_elName, "+i+");\" id=\""+buttonDig_id[i]+"\" title=\""+buttonDig_title_off[i]+"\" src=\""+buttonDig_imgdir+buttonDig_src[i]+"\">";
-
 			document.getElementById("digButtons").appendChild(divTag);
 
 //IE WORKAROUND, WORKS ALSO FOR FIREFOX
@@ -395,7 +414,6 @@
 			parent.writeTag(mod_digitize_elName,"div_" + buttonDig_id[i],tagContent);
 		}
 	}
-//	document.getElementById("listOfGeometries").setAttribute("style", "position:absolute; top:"+geomList_y+"px; left:"+geomList_x+"px;");
 }
 
 function initDigButton(ind, pos){
@@ -417,23 +435,38 @@
 		mod_digitizeEvent = obj.id;
 		executeDigitizePreFunctions();
 	}
-	else if (obj.id == button_point || obj.id == button_line || obj.id == button_polygon){
+	else if (obj.id == button_point || obj.id == button_line || obj.id == button_polygon || obj.id == button_clear || obj.id == button_combine){
 		mod_digitizeEvent = obj.id;
 		executeDigitizePreFunctions();
 		obj.title = obj.title_off;
 		if (obj.id == button_point) {
-			d.addMember(geomTypePoint);
+			d.addMember(parent.geomTypePoint);
 			d.get(-1).addGeometry();
 		}
 		else if (obj.id == button_polygon) {
-			d.addMember(geomTypePolygon);
+			d.addMember(parent.geomTypePolygon);
 			d.get(-1).addGeometry();
 		}
 		else if (obj.id == button_line) {
-			d.addMember(geomTypeLine);
+			d.addMember(parent.geomTypeLine);
 			d.get(-1).addGeometry();
 		}
-		s.store(d, mod_digitizeEvent);
+		else if (obj.id == button_clear) {
+			var clear = confirm('clear list of geometries?');
+			if (clear == true) {
+				d = new parent.GeometryArray();
+				parent.mb_disableThisButton(button_clear);
+			}
+		}
+		else if (obj.id == button_combine) {
+//			d.combineToMultiGeometry();
+//			prompt('', d.toJSONString());
+//			parent.mb_ajax_post("../php/jsonTest.php", {json:d.toJSONString()}, function(test, status) {
+//				alert(test);
+//			});
+			parent.mb_disableThisButton(button_combine);
+		}
+		if (mod_digitizeEvent == button_point || mod_digitizeEvent == button_line || mod_digitizeEvent == button_polygon || mod_digitizeEvent == button_insert ) s.store(d);
 		var el = parent.frames[mod_digitize_target].document;
 		el.onmousemove = mod_digitize_go;
 	}
@@ -446,6 +479,9 @@
 		mod_digitize_timeout();
 		executeDigitizeSubFunctions();
 	}
+	else if (obj.id == button_clear) {
+		executeDigitizeSubFunctions();
+	}
 }
 // --- button handling (end) ----------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------------------------------
@@ -460,125 +496,8 @@
 	mod_digitize_epsg = parent.mb_mapObj[anInd].epsg;
 }
 
-function calculateActualDash(p0, p1, width, height) {
-	// p0 is leftmost point
-	if (p0.x > p1.x) {var p_temp = p0; p0 = p1; p1 = p_temp; p_temp = null;}
-	
-	var p = p0; var q = p1; var m; var draw = true;
-	
-	// if line is not vertical
-	if (p1.x != p0.x) {
-
-		// calculate slope
-		m = -(p1.y-p0.y)/(p1.x-p0.x); 
-
-		// check if p is left of the right vertical of the screen && the line is not above or below the screen
-		if (p0.x < width && p1.x > 0 && !(p0.y < 0 && p1.y < 0) && !(p0.y > height && p1.y > height) ) {
-			
-			// if p is left of the screen
-			if (p0.x < 0) {
-			
-				//calculate intersection of line with left vertical of screen
-				var iy = p0.y - m*(0-p0.x);
-
-				// if intersection is visible
-				if (iy > 0 && iy < height) {p = new Point(0, iy);}
-				// if intersection is below the screen
-				else if (iy > height) {
-					// calculate intersection with lower horizontal
-				    var ix = p0.x+((p0.y - height)/m);
-				    if (ix > 0 && ix < width) {p = new Point(ix, height);}
-					else draw = false;
-				}
-				// if intersection is above the screen
-				else if (iy < 0) {
-					// calculate intersection with upper horizontal
-				    var ix = p0.x+(p0.y/m);
-				    if (ix > 0 && ix < width) {p = new Point(ix, 0);}
-					else draw = false;
-				}
-				else draw = false;
-			}
-			else if (p0.y >= 0 && p0.y <= height) {p = p0;}
-			else if (p0.y < 0) {
-				// calculate intersection with upper horizontal
-			    var ix = p0.x+(p0.y/m);
-			    if (ix > 0 && ix < width) {p = new Point(ix, 0);}
-				else draw = false;
-			}
-			else if (p0.y > height && m > 0) {
-				// calculate intersection with lower horizontal
-			    var ix = p0.x+((p0.y - height)/m);
-			    if (ix > 0 && ix < width) {p = new Point(ix, height);}
-				else draw = false;
-			}
-			else draw = false;
-			
-			// calculate q coordinates
-			if (draw == true) {
-				
-				// q is right of the screen
-				if (p1.x > width) {
-					// calculate intersection with right vertical of the screen
-					var iy = p1.y - m*(width-p1.x);
-
-					if (iy > 0 && iy < height) {q = new Point(width, iy);}
-					else if (iy < 0) {
-						// calculate intersection with upper horizontal
-					    var ix = p0.x+(p0.y/m);
-					    if (ix > 0 && ix < width) {q = new Point(ix, 0);}
-						else draw = false;
-					}
-					else if (iy > height) {
-						// calculate intersection with lower horizontal
-					    var ix = p0.x+((p0.y - height)/m);
-					    if (ix > 0 && ix < width) {q = new Point(ix, height);}
-						else draw = false;
-					}
-					else draw = false;
-				}
-				else if (p1.y >= 0 && p1.y <= height) {q = p1;}
-				else if (p1.y < 0) {
-					// calculate intersection with upper horizontal
-				    var ix = p1.x+(p1.y/m);
-				    if (ix > 0 && ix < width) {q = new Point(ix, 0);}
-					else draw = false;
-				}
-				else if (p1.y > height) {
-					// calculate intersection with lower horizontal
-				    var ix = p1.x+((p1.y- height)/m) ;
-				    if (ix > 0 && ix < width) {q = new Point(ix, height);}
-					else draw = false;
-				}
-			} 
-		}
-		else draw = false;
-	}
-	// the line is vertical
-	else {
-		// check if line is not above or below the screen
-		if (!(p0.y < 0 && p1.y < 0) && !(p0.y > height && p1.y > height)) {
-			if (p0.y < 0) {p = new Point(p0.x, 0);}
-			else if (p0.y > height) {p = new Point(p0.x, height);}
-			else p = p0;
-			
-			if (p1.y < 0) {q = new Point(p0.x, 0);}
-			else if (p1.y > height) {q = new Point(p0.x, height);}
-			else q = p1;
-		}
-		else draw = false;
-	}
-	
-	if (draw == true) {
-		var points = new Array();
-		points[0] = new Point(Math.round(q.x), Math.round(q.y)); 
-		points[1] = new Point(Math.round(p.x), Math.round(p.y)); 
-		return points;
-	}
-	else return false;
-}
-
 function drawDashedLine(){
+	digi_hl.clean();
 	var smP = "";
 	smP += "<div class='t_img'>";
 	smP += "<img src='"+parent.mb_trans.src+"' width='"+mod_digitize_width+"' height='0'></div>";
@@ -586,34 +505,39 @@
 	smP += "<img src='"+parent.mb_trans.src+"' width='0' height='"+mod_digitize_height+"'></div>";
 
 	for(var i=0; i<d.count(); i++){
-		for(var j=0; j<d.get(i).count(); j++){
-			for(var k = 0; k < d.getGeometry(i,j).count(); k++){
-				var pos = parent.makeRealWorld2mapPos(mod_digitize_target,d.getPoint(i,j,k).x,d.getPoint(i,j,k).y);
-				
-				if (!d.getGeometry(i,j).isComplete() && 
-					( (k == 0 && d.get(i).geomtype == geomTypePolygon) || (k == d.getGeometry(i,j).count()-1 && d.get(i).geomtype == geomTypeLine))) {
-					smP += "<div class='bp' style='top:"+(pos[1]-2)+"px;left:"+(pos[0]-2)+"px;z-index:50;background-color:"+linepointColor+"'";
+		if (nonTransactionalEditable == false && !isTransactional(d.get(i))) {
+			digi_hl.add(d.get(i), nonTransactionalColor);
+		}
+		else {
+			for(var j=0; j<d.get(i).count(); j++){
+				for(var k = 0; k < d.getGeometry(i,j).count(); k++){
+					var pos = parent.makeRealWorld2mapPos(mod_digitize_target,d.getPoint(i,j,k).x,d.getPoint(i,j,k).y);
+					
+					if (!d.getGeometry(i,j).isComplete() && 
+						( (k == 0 && d.get(i).geomtype == parent.geomTypePolygon) || (k == d.getGeometry(i,j).count()-1 && d.get(i).geomtype == parent.geomTypeLine))) {
+						smP += "<div class='bp' style='top:"+(pos[1]-2)+"px;left:"+(pos[0]-2)+"px;z-index:50;background-color:"+linepointColor+"'";
+					}
+					else {
+						smP += "<div class='bp' style='top:"+(pos[1]-2)+"px;left:"+(pos[0]-2)+"px;z-index:50;'";
+					}
+					if(j==0 && d.get(i).geomtype == parent.geomTypePolygon && d.getGeometry(i,j).complete == false){
+						smP += " title='"+closePolygon_title+"' ";
+					}
+					if(mod_digitizeEvent == button_move || mod_digitizeEvent == button_insert || mod_digitizeEvent == button_delete) {
+						smP += " onmouseover='parent.window.frames[\""+mod_digitize_elName+"\"].handleBasepoint(this,"+i+","+j+","+k+")' ;";
+					}
+					smP += "></div>";
 				}
-				else {
-					smP += "<div class='bp' style='top:"+(pos[1]-2)+"px;left:"+(pos[0]-2)+"px;z-index:50;'";
+				var mapObjInd = parent.getMapObjIndexByName(mod_digitize_target);
+				for(var k = 1; k < d.getGeometry(i,j).count(); k++){
+					var p0 = parent.realToMap(mod_digitize_target, d.getPoint(i,j,k));
+					var p1 = parent.realToMap(mod_digitize_target, d.getPoint(i,j,k-1));
+					points = parent.calculateVisibleDash(p0, p1, parent.mb_mapObj[mapObjInd].width, parent.mb_mapObj[mapObjInd].height);
+					if (points != false) {
+						smP += evaluateDashes(points[0], points[1], i, j, k);
+					}
 				}
-				if(j==0 && d.get(i).geomtype == geomTypePolygon && d.getGeometry(i,j).complete == false){
-					smP += " title='"+closePolygon_title+"' ";
-				}
-				if(mod_digitizeEvent == button_move || mod_digitizeEvent == button_insert || mod_digitizeEvent == button_delete) {
-					smP += " onmouseover='parent.window.frames[\""+mod_digitize_elName+"\"].handleBasepoint(this,"+i+","+j+","+k+")' ;";
-				}
-				smP += "></div>";
 			}
-			for(var k = 1; k < d.getGeometry(i,j).count(); k++){
-				var p0 = parent.realToMap(mod_digitize_target, d.getPoint(i,j,k));
-				var p1 = parent.realToMap(mod_digitize_target, d.getPoint(i,j,k-1));
-				
-				points = calculateActualDash(p0, p1, mod_digitize_width, mod_digitize_height);
-				if (points != false) {
-					smP += evaluateDashes(points[0], points[1], i, j, k);
-				}
-			}
 		}
 	}
 	parent.writeTag(mod_digitize_target,"digitize",smP);
@@ -621,11 +545,11 @@
 
 function evaluateDashes(start, end, memberIndex, geomIndex, pointIndex){
 	var str_dashedLine = "";
-	var delta = new Point(end.x - start.x, end.y - start.y);
+	var delta = new parent.Point(end.x - start.x, end.y - start.y);
 	 
 	var vecLength = start.dist(end);
 	var n = Math.round(vecLength/dotDistance);
-	var step = new Point(delta.x/n, delta.y/n);
+	var step = new parent.Point(delta.x/n, delta.y/n);
 	for(var i=1; i<n; i++){
 		var x = Math.round(start.x + i * step.x) - 2;
 		var y = Math.round(start.y + i * step.y) - 2;
@@ -645,41 +569,71 @@
 	return str_dashedLine;
 }
 
+function isTransactional(geom) {
+//	alert(typeof(geom.wfs_conf) + " " + geom.wfs_conf + " " + wfs_conf.length);
+	if (typeof(geom.wfs_conf) == 'number') {
+		if (geom.wfs_conf >= 0 && geom.wfs_conf < wfs_conf.length) {
+			if (!(wfs_conf[geom.wfs_conf]['wfs_transaction'] == "" && wfs_conf[geom.wfs_conf]['fkey_featuretype_id'] == "")) {
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+function isValidWfsConfIndex (wfsConf, wfsConfIndex) {
+	return typeof(wfsConfIndex) == "number" && wfsConfIndex >=0 && wfsConfIndex < wfsConf.length
+}
+
 function getName (geom) {
 	wfs_conf_id = geom.wfs_conf;
-	if (wfs_conf_id == -1) {return "new";}
 	wfs_conf = parent.get_complete_wfs_conf();
-	var resultName = "";
-	for (var i = 0 ; i < wfs_conf[wfs_conf_id]['element'].length ; i++) {
-		if (wfs_conf[wfs_conf_id]['element'][i]['f_show'] == 1) {
-			resultName += geom.e.getElementValueByName(wfs_conf[wfs_conf_id]['element'][i]['element_name']) + " ";
+	if (isValidWfsConfIndex(wfs_conf, wfs_conf_id)) {
+		var resultName = "";
+		for (var i = 0 ; i < wfs_conf[wfs_conf_id]['element'].length ; i++) {
+			if (wfs_conf[wfs_conf_id]['element'][i]['f_show'] == 1) {
+				resultName += geom.e.getElementValueByName(wfs_conf[wfs_conf_id]['element'][i]['element_name']) + " ";
+			}
 		}
+		if (resultName == "") {
+			resultName = wfs_conf[wfs_conf_id]['g_label'];
+		}
+		return resultName;
 	}
-	if (resultName == "") {
-		return wfs_conf[wfs_conf_id]['g_label'];
+	else {
+		return "new";
 	}
-	return resultName;
 }
 
 function updateListOfGeometries(){
 	var listOfGeom = "<table style='position:absolute; top:"+geomList_y+"px; left:"+geomList_x+"px;'>\n";
-	for (var i = 0 ; i < d.count(); i ++) {
-		listOfGeom += "\t<tr>\n\t\t<td>\n";
-		listOfGeom += "\t\t\t<img src = '"+buttonDig_imgdir+buttonDig_wfs_src+"' title='"+buttonDig_wfs_title+"' onclick='showWfs("+i+")'>\n";
-		listOfGeom += "\t\t</td>\n\t\t<td>\n";
-		listOfGeom += "\t\t\t<img src = '"+buttonDig_imgdir+buttonDig_remove_src+"' title='"+buttonDig_remove_title+"' onclick='parent.mb_disableThisButton(mod_digitizeEvent);d.del("+i+");executeDigitizeSubFunctions();'>\n";
-		listOfGeom += "\t\t</td>\n\t\t<td style = 'color:blue;font-size:12px'>\n";
-		listOfGeom += "\t\t\t<div onmouseover='parent.mb_wfs_perform(\"over\",d.get("+i+"));' ";
-		listOfGeom += " onmouseout='parent.mb_wfs_perform(\"out\",d.get("+i+"))' ";
+	if (d.count() > 0) {
+		wfs_conf = parent.get_complete_wfs_conf();
+		for (var i = 0 ; i < d.count(); i ++) {
 
-		listOfGeom += " onclick='parent.mb_wfs_perform(\"click\",d.get("+i+"));' ";
-		var geomName = getName(d.get(i)); 
-		
-		if (d.get(i).geomtype == geomTypePolygon) {geomName += " (polygon)";}
-		else if (d.get(i).geomtype == geomTypeLine) {geomName += " (line)";}
-		else if (d.get(i).geomtype == geomTypePoint) {geomName += " (point)";}
-		
-		listOfGeom += ">" + geomName +"</div>\t\t</td>\n";
+			if (!(nonTransactionalEditable == false && !isTransactional(d.get(i)))) {
+	
+				listOfGeom += "\t<tr>\n\t\t<td>\n";
+				listOfGeom += "\t\t\t<img src = '"+buttonDig_imgdir+buttonDig_wfs_src+"' title='"+buttonDig_wfs_title+"' onclick='showWfs("+i+")'>\n";
+				listOfGeom += "\t\t</td>\n\t\t<td>\n";
+				listOfGeom += "\t\t\t<img src = '"+buttonDig_imgdir+buttonDig_remove_src+"' title='"+buttonDig_remove_title+"' onclick='parent.mb_disableThisButton(mod_digitizeEvent);d.del("+i+");executeDigitizeSubFunctions();'>\n";
+				listOfGeom += "\t\t</td>\n\t\t<td>\n";
+	
+				if (isValidWfsConfIndex(wfs_conf, d.get(i).wfs_conf)) {
+					listOfGeom += "\t\t\t<img src = '"+buttonDig_imgdir+buttonDig_remove_src+"' title='"+buttonDig_remove_title+"' onclick=\"var deltrans = confirm('Delete geometry from database?');if (deltrans) dbGeom('delete', "+i+")\">\n";
+				}
+				listOfGeom += "\t\t</td>\n\t\t<td style = 'color:blue;font-size:12px'>\n";
+				listOfGeom += "\t\t\t<div onmouseover='parent.mb_wfs_perform(\"over\",d.get("+i+"));' ";
+				listOfGeom += " onmouseout='parent.mb_wfs_perform(\"out\",d.get("+i+"))' ";
+				listOfGeom += " onclick='parent.mb_wfs_perform(\"click\",d.get("+i+"));' ";
+				var geomName = getName(d.get(i)); 
+				if (d.get(i).geomtype == parent.geomTypePolygon) {geomName += " (polygon)";}
+				else if (d.get(i).geomtype == parent.geomTypeLine) {geomName += " (line)";}
+				else if (d.get(i).geomtype == parent.geomTypePoint) {geomName += " (point)";}
+				
+				listOfGeom += ">" + geomName +"</div>\t\t</td>\n\t</tr>\n";
+			}
+		}
 	}
 	listOfGeom += "</table>\n";
 	parent.writeTag(mod_digitize_elName,"listOfGeometries",listOfGeom);
@@ -691,6 +645,7 @@
 // (if the original wfs is the selected wfs, the values are set too)
 function buildElementForm(wfsConfIndex, memberIndex){
 	var selMember = memberIndex;
+	
 	if (parseInt(d.get(memberIndex).wfs_conf) != parseInt(wfsConfIndex)) {memberIndex=-1;}
 
 	var str = "";
@@ -717,45 +672,50 @@
 					wfsElementName = c['f_label']; 
 				}
 				
-				if (parseInt(c['f_geom']) != 1) {
-					str += "\t\t<tr>\n\t\t\t<td>\n";
-					str += "\t\t\t\t" + wfsElementName + "\n\t\t\t</td>\n\t\t\t<td colspan = 2>\n";
+				if (parseInt(c['f_geom']) != 1 && parseInt(c['f_edit']) == 1) {
+					str += "\t\t<tr>\n";
+					str += "\t\t\t<td>\n\t\t\t\t" + wfsElementName + "\n\t\t\t</td>\n";
+					str += "\t\t\t<td colspan = 2>\n";
 
-					if (c['f_box'] == "") {
-						var elementValue;
-						if (parseInt(memberIndex) != -1) {
-							for (var j = 0 ; j < memEl.count() ; j ++) {
-								if (memEl.getName(j) == c['element_name']) {
-									elementValue = memEl.getValue(j);
-								}
+					var elementValue = "";
+					if (parseInt(memberIndex) != -1) {
+						for (var j = 0 ; j < memEl.count() ; j ++) {
+							if (memEl.getName(j) == c['element_name']) {
+								elementValue = memEl.getValue(j);
 							}
 						}
-	
+					}
+					if (c['f_form_element_html'] == "") {
 						str += "\t\t\t\t<input name='" + wfsElementName + "' type='text' size=20 value = '" + elementValue + "'>\n";
 					}
 					else {
-						box = c['f_box']; 
-						str += box;
+						var formElementHtml = c['f_form_element_html']; 
+						// preselect the correct entry of the box
+						var patternString = "option value='"+elementValue+"'";
+						var pattern = new RegExp(patternString);
+						formElementHtml = formElementHtml.replace(pattern, patternString+" selected");
+						str += formElementHtml;
 					}
-					str += "\t\t\t</td>\n\t\t</tr>\n";
+					str += "\t\t\t</td>\n";
+					str += "\t\t</tr>\n";
 				}
 				else geom = wfsElementName;
 			}
 
 			if (wfs['wfs_transaction']) {
-				str += "\t\t<tr>\n";
 				var colspan = 0;
+				str += "\t\t<tr>\n";
 				if (geom) {
-					str += "\t\t\t<td><input type='button' name='saveButton' value='Save' onclick=\"window.opener.dbGeom('save', "+selMember+");window.close()\" /></td>\n";
+					str += "\t\t\t<td><input type='button' name='saveButton' value='Save' onclick=\"if (window.opener.formCorrect(document.getElementById('wfs_conf'))){window.opener.dbGeom('save', "+selMember+")}else{alert('Bitte treffen Sie eine Auswahl.');};\" /></td>\n";
 				}
 				else colspan++;
 
 				if (parseInt(memberIndex) != -1 && fid) {
 					if (geom) {
-						str += "\t\t\t<td><input type='button' name='updateButton' value='Update' onclick=\"window.opener.dbGeom('update', "+selMember+");window.close()\"/></td>\n";
+						str += "\t\t\t<td><input type='button' name='updateButton' value='Update' onclick=\"if (window.opener.formCorrect(document.getElementById('wfs_conf'))){window.opener.dbGeom('update', "+selMember+")}else{alert('Bitte treffen Sie eine Auswahl.');};\"/></td>\n";
 					}
 					else colspan++;
-					str += "\t\t\t<td><input type='button' name='deleteButton' value='Delete' onclick=\"window.opener.dbGeom('delete', "+selMember+");window.close()\"/></td>\n";
+//					str += "\t\t\t<td><input type='button' name='deleteButton' value='Delete' onclick=\"if (window.opener.formCorrect(document.getElementById('wfs_conf'))){window.opener.dbGeom('delete', "+selMember+")}else{alert('Bitte treffen Sie eine Auswahl.');};\"/></td>\n";
 				}
 				else colspan++;
 				
@@ -774,11 +734,31 @@
 }
 
 
+function formCorrect(form) {
+	isCorrect = true;
+	isCorrect = isCorrect && validBoxEntrySelected(form);
+}
+
+function validBoxEntrySelected(form){
+	var isCorrect = true;
+	for (var i = 0; i < form.childNodes.length && isCorrect == true; i++) {
+		if (form.childNodes[i].nodeName.toUpperCase() == "SELECT") {
+			if (parseInt(form.childNodes[i].selectedIndex) == 0) {
+				return false;
+			}
+		}
+		else if (form.childNodes[i].hasChildNodes()) {
+			isCorrect = validBoxEntrySelected(form.childNodes[i]);
+		}
+	}
+	return isCorrect;
+}
+
+
 //
 // this method opens a new window and displays the attributes in wfs_conf
 //
 function showWfs(index) {
-
 	wfsWindow = open("", "wfsattributes", "width=400, height=300, resizable, dependent=yes, scrollbars=yes");
 	wfsWindow.document.open("text/html");
 	wfsWindow.document.writeln("<html><head></head><body></body></html>");
@@ -798,15 +778,20 @@
 	str += ">\n\t\t";
 
 	for (var attr in wfs_conf) {
-		str += "<option value='" + attr + "'";
-
-		// if the geometry is already associated with a wfs
-		if (parseInt(d.get(index).wfs_conf) == parseInt(attr)) {
-			str += " selected";
-			defaultIndex = parseInt(attr);
+		if (isValidWfsConfIndex(wfs_conf, parseInt(d.get(index).wfs_conf))) {
+			if (parseInt(d.get(index).wfs_conf) == parseInt(attr)) {
+				str += "<option value='" + attr + "'";
+				str += " selected";
+				defaultIndex = parseInt(attr);
+				str += ">" + wfs_conf[attr]['wfs_conf_abstract'];
+				str += "</option>\n\t\t";
+			}
 		}
-		str += ">" + wfs_conf[attr]['wfs_conf_abstract'];
-		str += "</option>\n\t\t";
+		else {
+			str += "<option value='" + attr + "'";
+			str += ">" + wfs_conf[attr]['wfs_conf_abstract'];
+			str += "</option>\n\t\t";
+		}
 	
 	}
 	str += "</select>\n\t\t</form>\n\t";
@@ -816,7 +801,6 @@
 	}
 	str += "\n</div>";
 	
-	
 	wfsWindow.document.write(str);
 	wfsWindow.document.close();
 
@@ -830,174 +814,67 @@
 }
 
 function dbGeom(type,m) {
-	d.get(m).wfs_conf = wfsWindow.document.forms[0].wfs.options[wfsWindow.document.forms[0].wfs.selectedIndex].value;
-	d.get(m).e = new Wfs_element();
-
+	if (typeof(wfsWindow) != 'undefined') {
+		d.get(m).wfs_conf = parseInt(wfsWindow.document.forms[0].wfs.options[wfsWindow.document.forms[0].wfs.selectedIndex].value);
+		d.get(m).e = new parent.Wfs_element();
+	}
+	else {
+		wfs_conf = parent.get_complete_wfs_conf();
+	}
+	
 	var myconf = wfs_conf[d.get(m).wfs_conf];
+	
 	var mapObjInd = parent.getMapObjIndexByName(mod_digitize_target);
-	var fid = false;
 
 	if (myconf['featuretype_srs'] != parent.mb_mapObj[mapObjInd].epsg) {
 		alert("fatal error: EPSG mismatch. "+ parent.mb_mapObj[mapObjInd].epsg + " / "+ myconf['featuretype_srs']);
 	}
 	else {
-		var myform = wfsWindow.document.forms[1];
-	
-		for (var i=0; i<myform.length; i++){
-			if (myform.elements[i].name == "fid") {
-				fid = myform.elements[i].value;
-			}
-			else if (myform.elements[i].type == 'text' ){
-				d.get(m).e.setElement(myform.elements[i].name, myform.elements[i].value);
-			}
-		}
-		document.sendForm.url.value = myconf['wfs_transaction'];
-		var str = '<wfs:Transaction version="1.0.0" service="WFS" xmlns="http://www.someserver.com/myns" ';
-
-		var ns_gml = false;	var ns_ogc = false;	var ns_xsi = false;	var ns_wfs = false;	var ns_topp = false;
+		var fid = false;
+		if (typeof(wfsWindow) != 'undefined') {
+			var myform = wfsWindow.document.forms[1];
 		
-		for (var q = 0 ; q < myconf['namespaces'].length ; q++) {
-			if (myconf['namespaces'][q]['name'] == "gml") ns_gml = true;
-			else if (myconf['namespaces'][q]['name'] == "ogc") ns_ogc = true;
-			else if (myconf['namespaces'][q]['name'] == "xsi") ns_xsi = true;
-			else if (myconf['namespaces'][q]['name'] == "wfs") ns_wfs = true;
-			else if (myconf['namespaces'][q]['name'] == "topp") ns_topp = true;
-			str += 'xmlns:' + myconf['namespaces'][q]['name'] + '="' + myconf['namespaces'][q]['location'] + '" ';
-		}
-		
-		if (ns_gml == false) str += 'xmlns:gml="http://www.opengis.net/gml" ';
-		if (ns_ogc == false) str += 'xmlns:ogc="http://www.opengis.net/ogc" ';
-		if (ns_xsi == false) str += 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
-		if (ns_topp == false) str += 'xmlns:topp="http://www.someserver.com/topp" ';
-		if (ns_wfs == false) str += 'xmlns:wfs="http://www.opengis.net/wfs" ';
-		
-		str += 'xsi:schemaLocation="http://www.someserver.com/myns http://wms1.ccgis.de/geoserver-1.3-beta4/wfs/getCapabilities?request=describefeaturetype&amp;typename=mapbender_user http://www.opengis.net/wfs../wfs/1.0.0/WFS-transaction.xsd">';
-
-		
-		//
-		// ---------------------------------------- SAVE -------------------------------------------------
-		//
-		if (type == "save") {
-			str += '<wfs:Insert><'+ myconf['featuretype_name']+'>';
-			for(var i=0; i<d.get(m).e.count(); i++){
-				if(d.get(m).e.getValue(i) != ""){
-					var tmp = d.get(m).e.getName(i);
-					str += '<' + tmp  + '>' + d.get(m).e.getValue(i) + '</' + tmp  + '>';
+			for (var i=0; i<myform.length; i++){
+				if (myform.elements[i].name == "fid") {
+					fid = myform.elements[i].value;
 				}
-			}
-			for(var j=0; j<myconf['element'].length; j++){
-				if(myconf['element'][j]['f_geom'] == 1){
-					var el_geom = myconf['element'][j]['element_name'];	
+				else if (myform.elements[i].type == 'text' ){
+					d.get(m).e.setElement(myform.elements[i].name, myform.elements[i].value);
 				}
-			}
-			str += '<' + el_geom + '>';	
-			if(d.get(m).geomtype == geomTypePoint){
-				str += '<gml:Point srsName="' + myconf['featuretype_srs'] + '">';
-				str += '<gml:coordinates>';
-				str += d.getPoint(m,0,0).x + "," + d.getPoint(m,0,0).y; 
-				str += '</gml:coordinates>';
-				str += '</gml:Point>';		
-			}
-			if(d.get(m).geomtype == geomTypeLine){
-				str += '<gml:MultiLineString srsName="' + myconf['featuretype_srs'] + '">';
-				str += '<gml:lineStringMember><gml:LineString><gml:coordinates>';
-				for(var k=0; k<d.getGeometry(m,0).count(); k++){
-					if(k>0)	str += " ";	
-					str += d.getPoint(m,0,k).x + "," + d.getPoint(m,0,k).y;
-				} 
-				str += '</gml:coordinates></gml:LineString></gml:lineStringMember>';
-				str += '</gml:MultiLineString>';
-			}
-			if(d.get(m).geomtype == geomTypePolygon){
-				str += '<gml:MultiPolygon srsName="' + myconf['featuretype_srs'] + '">';
-				str += '<gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>';
-
-				for(var k=0; k<d.getGeometry(m,0).count(); k++){
-					if(k>0)	str += " ";	
-					str += d.getPoint(m,0,k).x + "," + d.getPoint(m,0,k).y;
-				} 
-				str += '</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon>';
-			}
-			str += '</' + el_geom + '></'+ myconf['featuretype_name']+'></wfs:Insert>';		
-		}
-		//
-		// --------------------------------------- UPDATE ------------------------------------------------
-		//
-		else if (type == "update") {
-			str += '<wfs:Update typeName="'+ myconf['featuretype_name']+'">';
-			for(var i=0; i<d.get(m).e.count(); i++){
-				if(d.get(m).e.getValue(i) != ""){
-					str += '<wfs:Property>';
-					str += '<wfs:Name>'+d.get(m).e.getName(i)+'</wfs:Name>';
-					str += '<wfs:Value>'+d.get(m).e.getValue(i)+'</wfs:Value>';
-					str += '</wfs:Property>';
+				// selectbox
+				else if (typeof(myform.elements[i].selectedIndex) == 'number') {
+					d.get(m).e.setElement(myform.elements[i].name, myform.elements[i].options[myform.elements[i].selectedIndex].value);
 				}
 			}
-			for(var j=0; j<myconf['element'].length; j++){
-				if(myconf['element'][j]['f_geom'] == 1){
-					var el_geom = myconf['element'][j]['element_name'];	
-				}
-			}
-			str += '<' + el_geom + '>';	
-			str += '<wfs:Property><wfs:Name>' + el_geom + '</wfs:Name><wfs:Value>';
-			if(d.get(m).geomtype == geomTypePoint){
-				str += '<gml:Point srsName="' + myconf['featuretype_srs'] + '"><gml:coordinates>';
-				str += d.getPoint(m,0,0).x + "," + d.getPoint(m,0,0).y; 
-				str += '</gml:coordinates></gml:Point>';		
-			}
-			if(d.get(m).geomtype == geomTypeLine){
-				str += '<gml:MultiLineString srsName="' + myconf['featuretype_srs'] + '">';
-				str += '<gml:lineStringMember><gml:LineString><gml:coordinates>';
-				for(var k=0; k<d.getGeometry(m,0).count(); k++){
-					if(k>0)	str += " ";	
-					str += d.getPoint(m,0,k).x + "," + d.getPoint(m,0,k).y;
-				} 
-				str += '</gml:coordinates></gml:LineString></gml:lineStringMember>';
-				str += '</gml:MultiLineString>';
-			}
-			if(d.get(m).geomtype == geomTypePolygon){
-				str += '<gml:MultiPolygon srsName="' + myconf['featuretype_srs'] + '">';
-				str += '<gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>';
-				for(var k=0; k<d.getGeometry(m,0).count(); k++){
-					if(k>0)	str += " ";	
-					str += d.getPoint(m,0,k).x + "," + d.getPoint(m,0,k).y;
-				} 
-				str += '</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon>';
-			}
-			str += '</wfs:Value></wfs:Property>';
-			str += '</' + el_geom + '>';
-			str += '<ogc:Filter><ogc:FeatureId fid="'+fid+'"/></ogc:Filter>';
-			str += '</wfs:Update>';
 		}
-		//
-		// --------------------------------------- DELETE ------------------------------------------------
-		//
-		else if (type == "delete") {
-			str += '<wfs:Delete typeName="'+ myconf['featuretype_name']+'">';
-			for(var j=0; j<myconf['element'].length; j++){
-				if(myconf['element'][j]['f_geom'] == 1){
-					var el_geom = myconf['element'][j]['element_name'];	
-				}
-			}
-			str += '<ogc:Filter><ogc:FeatureId fid="'+fid+'"/></ogc:Filter>';
-			str += '</wfs:Delete>';
+		else {
+			fid = d.get(m).e.getElementValueByName('fid');
 		}
-		
-		str += '</wfs:Transaction>';
-		document.sendForm.filter.value = str;
-		document.sendForm.onlineresource.value = myconf['wfs_transaction'];
-		document.sendForm.submit();
+
+		str = parent.get_wfs_str(myconf, d, m, type, fid);
+		parent.mb_ajax_post("../extensions/geom2wfst.php", {'filter':str,'url':myconf['wfs_transaction']}, function(xml,status){
+			wfsSubWrite(m,type,status);
+//			var serializer = new XMLSerializer();
+//			var xml_string = serializer.serializeToString(xml);
+//			prompt('', xml_string);
+		});
 	}
 }
-// -->
+
+function wfsSubWrite(m,type,status) {
+	parent.mb_execWfsWriteSubFunctions();
+	if (type == 'delete') {
+		parent.mb_disableThisButton(mod_digitizeEvent);
+		d.del(m);
+	}
+	executeDigitizeSubFunctions();
+	alert(status);
+}
+
 	</script>
 	</head>
 	<body onload="registerFunctions();displayButtons();">
 		<table cellpadding='0' cellspacing='0' align = center><tr><td><div id='digButtons'></div></td></tr></table>
 		<div id = 'listOfGeometries'></div>
-		<form name='sendForm' action='../extensions/geom2wfst.php' method='POST' TARGET='wfsupdate'>
-			<input type='hidden' name='url'><input type='hidden' name='filter'><input type='hidden' name='onlineresource'>
-		</form>
-		<iframe id='wfsupdate' name='wfsupdate' width=0 height=0></iframe>
 	</body>
 </html>
\ No newline at end of file



More information about the Mapbender_commits mailing list