[Mapbender-commits] r2977 - in branches/tree_dev: http/php http/x_test lib

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Thu Sep 18 09:23:55 EDT 2008


Author: christoph
Date: 2008-09-18 09:23:55 -0400 (Thu, 18 Sep 2008)
New Revision: 2977

Added:
   branches/tree_dev/http/php/mod_customTree.php
   branches/tree_dev/http/php/mod_customTree_server.php
   branches/tree_dev/lib/buttonNew.js
   branches/tree_dev/lib/customTreeController.js
   branches/tree_dev/lib/customTreeModel.js
Removed:
   branches/tree_dev/http/x_test/customTreeController.js
   branches/tree_dev/http/x_test/customTreeModel.js
Modified:
   branches/tree_dev/http/x_test/tree.html
Log:
latest development

Added: branches/tree_dev/http/php/mod_customTree.php
===================================================================
--- branches/tree_dev/http/php/mod_customTree.php	                        (rev 0)
+++ branches/tree_dev/http/php/mod_customTree.php	2008-09-18 13:23:55 UTC (rev 2977)
@@ -0,0 +1,247 @@
+<?php
+require_once(dirname(__FILE__) . "/../php/mb_validatePermission.php");
+require_once(dirname(__FILE__) . "/../classes/class_json.php");
+?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET;?>" />
+		<title>Untitled Document</title>
+		<style type="text/css">
+			.ui-selecting {
+			  color:red;
+			}
+			.treeNode {
+			  color:green;
+			}
+			.treeLeaf {
+			  color:blue;
+			}
+			.ui-selected {
+			  border-width:thin;
+			  border-style:solid;
+			  border-color:red;
+			  background-color:transparent;
+			  font-size:9px;
+			}
+			.ui-draggable {
+			}
+			.div-border {
+			  border-width:thin;
+			  border-style:solid;
+			  border-color:black;
+			  background-color:transparent;
+			  font-size:9px;
+			}
+			.contextMenu
+			{
+				display:none;
+			}
+		</style>
+		<link rel='stylesheet' type='text/css' href='../css/popup.css'>
+		<script type='text/javascript'>
+<?php
+
+	require_once(dirname(__FILE__) . "/../extensions/jquery-1.2.6.min.js");
+	require_once(dirname(__FILE__) . "/../extensions/jquery-ui-personalized-1.5.2.js");
+	require_once(dirname(__FILE__) . "/../extensions/jquery.contextmenu.r2.js");
+	require_once(dirname(__FILE__) . "/../extensions/jqjson.js");
+	require_once(dirname(__FILE__) . "/../javascripts/popup.js");
+	require_once(dirname(__FILE__) . "/../javascripts/event.js");
+	require_once(dirname(__FILE__) . "/../../lib/customTreeModel.js");
+	require_once(dirname(__FILE__) . "/../../lib/customTreeController.js");
+	require_once(dirname(__FILE__) . "/../../lib/buttonNew.js");
+
+?>
+			var myTree = new CustomTree();
+
+			var applicationId;
+
+			var findAllWmsInTree = function (aTree) {
+				return findAllWmsInNode(aTree.root).sort();
+			};
+
+			findAllWmsInNode = function (aNode) {
+				if (!aNode.isFolder) {
+					return [aNode.wmsId];
+				}
+				var wmsIdArray = [];
+				for (var i = 0; i < aNode.childNodeList.count(); i++) {
+					var child = aNode.childNodeList.get(i);
+					var newArray = findAllWmsInNode(child);
+					wmsIdArray = wmsIdArray.concat(newArray);
+				}
+				return wmsIdArray;
+			};
+
+			var addMissingWmsToCustomTree = function (aTree, anApplicationId) {
+				// get available WMS ...
+				var queryObj = {
+					command:"getWmsByApplication",
+					parameters: {
+						"applicationId": anApplicationId
+					}
+				};				
+
+				$.post("../php/mod_customTree_server.php", {
+					queryObj:$.toJSON(queryObj)
+				}, function (json, status) {
+					var replyObj = eval('(' + json + ')');
+
+					var root = aTree.root;
+
+					var wmsIdArray = findAllWmsInTree(aTree);
+					
+					for (var index in replyObj.data.wmsArray) {
+						var found = false;
+						for (var j = 0; j < wmsIdArray.length; j++) {
+							if (wmsIdArray[j] == index) {
+								found = true;
+								break;
+							}
+						}
+						if (!found) {
+							var wmsNode = new CustomTreeNode();
+							wmsNode.name = replyObj.data.wmsArray[index];
+							wmsNode.wmsId = index;
+							myTree.root.append(wmsNode);
+						}
+					}
+
+					displayMyTree = new customTreeController(myTree, {
+						contextMenu: true,
+						droppable: true,
+						id: "myTree"
+					});
+				});
+			};
+
+			var getCustomTreeByApplication = function (applicationName) {
+				// load a previously saved 
+				// customized tree from the database
+				var queryObj = {
+					command:"getCustomTreeByApplication",
+					parameters: {
+						"applicationId":applicationName
+					}
+				};				
+
+				$.post("../php/mod_customTree_server.php", {
+					queryObj:$.toJSON(queryObj)
+				}, function (json, status) {
+					var replyObj = eval('(' + json + ')');
+
+					myTree = new CustomTree();
+					var root = myTree.root;
+					root.name = "(" + applicationId + ")";
+
+					var nodeArray = replyObj.data.nodeArray;
+					
+					myTree.importNestedSets(nodeArray);
+
+					addMissingWmsToCustomTree(myTree, applicationId);
+
+					displayMyTree = new customTreeController(myTree, {
+						contextMenu: true,
+						droppable: true,
+						id: "myTree"
+					});
+				});
+			};
+
+			var selectApplication = function (applicationName) {
+
+				applicationId = applicationName;
+
+				getCustomTreeByApplication(applicationId);
+			}
+			
+			var getApplications = function () {
+				var queryObj = {
+					command:"getApplications"
+				};				
+				$.post("../php/mod_customTree_server.php", {
+					queryObj:$.toJSON(queryObj)
+				}, function (json, status) {
+					var replyObj = eval('(' + json + ')');
+
+					$select = $("#applicationSelect");
+					$select.change(function () {
+						selectApplication(this.options[this.selectedIndex].value);
+					});
+
+					for (var index in replyObj.data.applicationArray) {
+						var currentApplication = replyObj.data.applicationArray[index];
+						$currentOption = $("<option id='application" + index + "' value='" + currentApplication + "'>" + currentApplication + "</option>");
+						$select.append($currentOption);
+					}
+				});
+			};
+			
+			var Save = {
+				buttonParameters : {
+					on:"../img/button_blink_red/wmc_save_on.png",
+					over:"../img/button_blink_red/wmc_save_over.png",
+					off:"../img/button_blink_red/wmc_save_off.png",
+					type:"toggle"
+				},
+				updateDatabase : function (callback) {
+					var data = {
+						"applicationId": applicationId,
+						"folderArray": myTree.exportNestedSets()
+					};
+					var queryObj = {
+						command:"update",
+						parameters:{
+							data: data
+						}
+					};
+					$.post("mod_customTree_server.php", {
+						queryObj:$.toJSON(queryObj)	
+					}, function (json, status) {
+						var replyObj = eval('(' + json + ')');
+						alert(replyObj.success);
+						callback();
+					});
+				}
+			};
+						
+			$(function () {
+
+				getApplications();
+
+				var toolbox = new ButtonGroup("controls");
+
+				// save tool
+				var saveButton = new Button(Save.buttonParameters);
+				toolbox.add(saveButton);
+
+				saveButton.registerPush(function () {
+					Save.updateDatabase(saveButton.triggerStop);	
+				});
+			});
+			
+		</script>
+	</head>
+	<body>
+		<select id='applicationSelect'>
+			<option>...</option>
+		</select>
+		<div id="controls"></div>
+		<hr>
+		<div class="contextMenu" id="folderMenu">
+			<ul>
+				<li id="addFolder"><img src="images/folder_add.png" /> Add </li>
+				<li id="deleteFolder"><img src="images/folder_delete.png" /> Delete</li>
+				<li id="editFolder"><img src="images/folder_edit.png" /> Edit</li>
+			</ul>
+		</div>
+		<div class="contextMenu" id="rootMenu">
+			<ul>
+				<li id="addFolder"><img src="images/folder_add.png" /> Add </li>
+			</ul>
+		</div>
+		<div id='myTree'></div>
+		<div id='wmsTree'></div>
+	</body>
+</html>
\ No newline at end of file

Added: branches/tree_dev/http/php/mod_customTree_server.php
===================================================================
--- branches/tree_dev/http/php/mod_customTree_server.php	                        (rev 0)
+++ branches/tree_dev/http/php/mod_customTree_server.php	2008-09-18 13:23:55 UTC (rev 2977)
@@ -0,0 +1,166 @@
+<?php
+require_once(dirname(__FILE__) . "/../classes/class_json.php");
+require_once(dirname(__FILE__) . "/../classes/class_user.php");
+
+/**
+ * encodes and delivers the data
+ * 
+ * @param object the un-encoded object 
+ */
+function sendOutput($out){
+	global $json;
+	$output = $json->encode($out);
+	header("Content-Type: text/x-json");
+	echo $output;
+}
+
+
+$json = new Mapbender_JSON();
+$queryObj = $json->decode(stripslashes($_REQUEST['queryObj']));
+$resultObj = array();
+$data = array();
+$e = new mb_exception("command: " . $queryObj->command);
+
+$userId = $_SESSION[mb_user_id];
+$user = new User($userId);
+
+switch($queryObj->command){
+
+	case 'getApplications':
+		// get all of the users applications
+		$allowedApplicationArray = $user->getApplicationsByPermission();
+
+		// get all of the users applications that contain treeGDE
+		$sql = "SELECT fkey_gui_id FROM gui_element WHERE " . 
+				"e_id = 'treeGDE' AND fkey_gui_id IN (";
+		
+		$v = array();
+		$t = array();
+		foreach ($allowedApplicationArray as $i => $application) {
+			array_push($v, $application);
+			array_push($t, "s");
+			if ($i > 0) {
+				$sql .= ",";
+			}
+			$sql .= "$" . ($i+1);
+		}
+		$sql .= ")";
+		$res = db_prep_query($sql, $v, $t);
+		$applicationArray = array();
+		while ($row = db_fetch_array($res)) {
+			array_push($applicationArray, $row[0]);
+		}
+		
+		$data = array("applicationArray" => $applicationArray);
+		$resultObj["data"] = $data;
+		break;
+
+	case 'getWmsByApplication':
+		$applicationId = $queryObj->parameters->applicationId;
+
+		// get all of the users applications
+		$allowedApplicationArray = $user->getApplicationsByPermission();
+
+		if (in_array($applicationId, $allowedApplicationArray)) {
+			$sql = "SELECT b.wms_id AS id, b.wms_title AS title " . 
+				"FROM gui_wms AS a, wms AS b " . 
+				"WHERE a.fkey_wms_id = b.wms_id AND a.fkey_gui_id = $1";
+			$v = array($applicationId);
+			$t = array("s");
+			$res = db_prep_query($sql,$v,$t);
+
+			$wmsArray = array();
+			while ($row = db_fetch_array($res)) {
+				$wmsArray[$row["id"]] = $row["title"];
+			}
+			$data = array("wmsArray" => $wmsArray);
+			$resultObj["data"] = $data;
+			
+		}
+		else {
+			$resultObj["data"] = array("wmsArray" => array());
+		}		
+		break;
+	
+	case 'getCustomTreeByApplication':
+		$applicationId = $queryObj->parameters->applicationId;
+
+		// get all of the users applications
+		$allowedApplicationArray = $user->getApplicationsByPermission();
+
+		if (in_array($applicationId, $allowedApplicationArray)) {
+			$sql = "SELECT lft, rgt, my_layer_title, wms_id " . 
+				"FROM gui_treegde " . 
+				"WHERE fkey_gui_id = $1 ORDER BY lft";
+			$v = array($applicationId);
+			$t = array("s");
+			$res = db_prep_query($sql,$v,$t);
+
+			$nodeArray = array();
+			while ($row = db_fetch_array($res)) {
+				
+				$wmsIdArray = explode(",", $row["wms_id"]);
+				$wmsArray = array();
+				foreach ($wmsIdArray as $wmsId) {
+					$sqlWms = "SELECT wms_title FROM wms WHERE wms_id = $1";
+					$vWms = array($wmsId);
+					$tWms = array("i");
+					$resWms = db_prep_query($sqlWms, $vWms, $tWms);
+					$rowWms = db_fetch_array($resWms);
+					$wmsArray[$wmsId] = $rowWms[0];
+				}
+				
+				$currentNode = array(
+					"left" => $row["lft"],
+					"right" => $row["rgt"],
+					"name" => $row["my_layer_title"],
+					"wms" => $wmsArray
+				);
+				array_push($nodeArray, $currentNode);
+			}
+			$data = array("nodeArray" => $nodeArray);
+			$resultObj["data"] = $data;
+			
+		}
+		else {
+			$resultObj["data"] = array("nodeArray" => array());
+		}		
+		break;
+
+	case 'update':
+		$elementArray = $queryObj->parameters->data->folderArray;		
+		$applicationId = $queryObj->parameters->data->applicationId;		
+		$sql = "DELETE FROM gui_treegde WHERE fkey_gui_id = $1";
+		$v = array($applicationId);
+		$t = array("s");
+		$res = db_prep_query($sql, $v, $t);
+		
+		for ($i = 0; $i < count($elementArray); $i++) {
+	
+			$currentElement = $elementArray[$i];
+
+			$sql = "INSERT INTO gui_treegde (fkey_gui_id, lft, rgt, " . 
+				"my_layer_title, wms_id) VALUES ($1, $2, $3, $4, $5)";
+			$v = array(
+				$applicationId, 
+				$currentElement->left, 
+				$currentElement->right, 
+				$currentElement->name, 
+				$currentElement->wms
+			);
+			$t = array("s", "i", "i", "s", "s");
+			$res = db_prep_query($sql, $v, $t);
+		}
+		$data = array("sql" => $sql, "data" => $v);
+		$resultObj["data"] = $data;
+		$resultObj["success"] = "Elements have been updated in the database.";
+		break;
+	
+
+	// Invalid command
+	default:
+		$resultObj["error"] = "no action specified...";
+}
+
+sendOutput($resultObj);
+?>
\ No newline at end of file

Deleted: branches/tree_dev/http/x_test/customTreeController.js
===================================================================
--- branches/tree_dev/http/x_test/customTreeController.js	2008-09-18 13:11:52 UTC (rev 2976)
+++ branches/tree_dev/http/x_test/customTreeController.js	2008-09-18 13:23:55 UTC (rev 2977)
@@ -1,239 +0,0 @@
-var customTreeController = function (myTree) {
-//	this.myTree = new CustomTree();
-//	this.myTree.root.name = "My tree";
-
-	this.myTree = myTree;
-	this.$root = $("<ul></ul>");
-
-	var that = this;
-	var currentlyDraggedNode;
-	
-	// --------------- BEHAVIOUR (begin) ------------------
-	
-	var addLeafBehaviour = function ($domNode, treeNode) {
-		// enable context menu
-		$label = $domNode.children().eq(0);
-		addContextMenuToLeaf($domNode, treeNode);
-
-		// make leaves draggable
-		makeNodeDraggable($domNode, treeNode);
-	};
-	
-	var addFolderBehaviour = function ($domNode, treeNode) {
-		$label = $domNode.children().eq(0);
-		if (treeNode != that.myTree.root) {
-			// enable folder closing and opening
-			addOpenCloseBehaviour($label);
-
-			// enable context menu
-			addContextMenuToFolder($domNode, treeNode);
-
-			// make inner nodes draggable
-			makeNodeDraggable($domNode, treeNode);
-		}
-		else {
-			// enable context menu
-			addContextMenuToRoot($domNode, treeNode);
-		}		
-
-		// make all folders droppable
-		makeNodeDroppable($label, treeNode);
-	};
-
-
-	var deleteNode = function (treeNode) {
-		treeNode.remove();
-	};
-
-	var editNode = function ($domNode, treeNode) {
-		var newName = prompt('Name');
-		if (newName) {
-			treeNode.setName(newName);
-		}	
-	};
-	
-	var addNode = function ($domNode, treeNode) {
-		var newChild = treeNode.addChild();
-		$newNode = createFolder(newChild);
-		var $folder = $domNode.children().eq(1);
-		$folder.append($newNode);
-	};
-
-	//
-	// CONTEXT MENU
-	//
-	var addContextMenuToLeaf = function ($domNode, treeNode) {
-		$domNode.contextMenu('leafMenu', {
-			onContextMenu: function(e) {
-				return true;
-			},
-			onShowMenu: function(e, menu) {
-				return menu;
-			},
-			bindings: {
-				'deleteService': function () {
-					deleteNode(treeNode);
-				}
-			}
-		});
-	}
-	
-	var addContextMenuToFolder = function ($domNode, treeNode) {
-		$domNode.contextMenu('folderMenu', {
-			onContextMenu: function(e){
-				return true;
-			},
-			onShowMenu: function(e, menu){
-				return menu;
-			},
-			bindings: {
-				'addFolder': function(item){
-					addNode($domNode, treeNode);
-				},
-				'deleteFolder': function(){
-					deleteNode(treeNode);
-				},
-				'editFolder': function(){
-					editNode($domNode, treeNode);
-				}
-			}
-		});
-	};
-	
-	var addContextMenuToRoot = function ($domNode, treeNode) {
-		$domNode.contextMenu('rootMenu', {
-			onContextMenu: function(e){
-				return true;
-			},
-			onShowMenu: function(e, menu){
-				return menu;
-			},
-			bindings: {
-				'addFolder': function(item){
-					addNode($domNode, treeNode);
-				}
-			}
-		});
-	};
-	
-	//
-	// OPEN AND CLOSE BEHAVIOUR
-	// 
-	var addOpenCloseBehaviour = function ($domNode) {
-		$domNode.toggle(function () {
-			$(this).siblings().hide("fast");
-		}, function () {
-			$(this).siblings().show("fast");
-		});		
-	};
-	
-	//
-	// DRAGGABLE AND DROPPABLE
-	//
-	var makeNodeDraggable = function ($domNode, treeNode) {
-		$domNode.draggable({
-			"helper": "clone",
-			"start": function(){
-				$(this).addClass("currently-dragging");
-				currentlyDraggedNode = treeNode;
-			}
-		});
-	};
-	
-	var makeNodeDroppable = function ($domNode, treeNode) {
-		$domNode.droppable({
-			"accept": function ($draggable) {
-				var $invalidDroppables = $(".currently-dragging .treeNodeDrop");
-				var $invalidDroppablesMinusThis = $invalidDroppables.not($domNode);
-
-				if ($invalidDroppables.size() > $invalidDroppablesMinusThis.size()) {
-					return false;
-				}
-				return true;
-			},
-			"tolerance": "pointer", 
-			"drop": function (e, ui) {
-				$toDomNode = $(this);
-				$fromDomNode = $(ui.draggable);
-				
-				currentlyDraggedNode.afterMove = function () {
-					$toDomNode.next().append($(ui.draggable));
-					$(".treeLeaf").removeAttr("style");
-					$("*").removeClass("currently-dragging");
-				};
-				currentlyDraggedNode.move(treeNode);
-			}
-		});		
-	};
-	
-	// --------------- BEHAVIOUR (end) ------------------
-
-	var createLeaf = function (treeNode) {
-		var $currentItem = $("<li class='treeLeaf'></li>");
-		var $currentLabel = $("<span>" + treeNode.name + "</span>");
-
-		$currentItem.append($currentLabel);
-		addLeafBehaviour($currentItem, treeNode);
-
-		treeNode.$domNode = $currentItem;
-
-		treeNode.afterRemove = function () {
-			$currentItem.remove();
-		};
-
-		return $currentItem;
-	};
-	
-	var createFolder = function (treeNode) {
-		var $currentItem = $("<li class='treeNode'></li>");
-		var $currentLabel = $("<div class='treeNodeDrop'><span>" + treeNode.name + "</span></div>");
-		var $currentFolder = $("<ul></ul>");
-		
-		$currentItem.append($currentLabel);
-		$currentItem.append($currentFolder);
-
-		addFolderBehaviour($currentItem, treeNode);
-
-		treeNode.$domNode = $currentItem;
-
-		treeNode.afterRemove = function () {
-			$currentItem.remove();
-		};
-
-		treeNode.afterSetName = function () {
-			$currentLabel.children().eq(0).html(treeNode.name);
-		};
-		return $currentItem;
-	};
-	
-	/**
-	 *  A recursive function to draw the nodes of a tree and attach 
-	 *  draggables and droppables
-	 *  
-	 * @param {Object} $domNode
-	 * @param {Object} treeNode
-	 */
-	var drawNode = function ($domNode, treeNode) {
-		var numOfChildren = treeNode.childNodeList.count();
-		var $newNode;
-
-		if (numOfChildren === 0) {
-			$newNode = createLeaf(treeNode);
-		}
-		else {
-			$newNode = createFolder(treeNode);
-
-			// visit the child nodes (depth first)
-			var $folder = $newNode.children().eq(1);
-			for (var i = 0; i < numOfChildren; i++) {
-				drawNode.apply(that, [$folder, treeNode.childNodeList.get(i)]);
-			}
-		}		
-		// attach node to tree
-		$domNode.append($newNode);
-	};
-
-	$(document.body).append(that.$root);
-	drawNode(that.$root, that.myTree.root);
-};
-

Deleted: branches/tree_dev/http/x_test/customTreeModel.js
===================================================================
--- branches/tree_dev/http/x_test/customTreeModel.js	2008-09-18 13:11:52 UTC (rev 2976)
+++ branches/tree_dev/http/x_test/customTreeModel.js	2008-09-18 13:23:55 UTC (rev 2977)
@@ -1,298 +0,0 @@
-/**
- * @class A List object is an array of arbitrary objects with additional methods. 
- *
- * @constructor
- */
-var List = function() {
-	
-	/**
-	 * gets the number of elements in this {@link List}
-	 *
-	 * @returns number of elements in this {@link List}
-	 * @type Integer
-	 */
-	this.count = function() {
-		return this.list.length;
-	};
-
-	/**
-	 * deletes the object at index i; -1 refers to the last object in this {@link List}
-	 *
-	 * @param {Integer} i index
-	 */
-	this.del = function(i){
-		i = this.getIndex(i);
-		if (i !== false) {
-			for(var z = i; z < this.count() - 1; z++){
-				this.list[z] = this.list[z+1];
-			}
-			this.list.length -= 1;
-			return true;
-		}
-		return false;
-	};
-
-	/**
-	 * empties this {@link List}
-	 */
-	this.empty = function() {
-		while (this.list !== null && this.count() > 0) {
-			this.list.pop();
-		}
-	};
-	
-	/**
-	 * @param {Integer} i index
-	 * @returns the object at index i; -1 refers to the last object in this {@link List}
-	 * @type Integer or false
-	 */
-	this.get = function(i) {
-		i = this.getIndex(i);
-		if (i !== false) {return this.list[i];}
-		return false;		
-	};
-	/**
-	 * adds a reference to item to this {@link List}.
-	 *
-	 * @param {Object} item an object
-	 */
-	this.add = function(item) {
-		var i = this.list.length;
-		this.list[i] = item;
-	};
-	/**
-	 * adds a copy of item to this {@link List}.
-	 *
-	 * @param {Object} item an object
-	 */
-	this.addCopy = function(item) {
-		this.add(cloneObject(item));
-	};
-	/**
-	 * attaches the {@link List} aList to this {@link List}
-	 *
-	 * @param {List} aList another list
-	 */
-	this.union = function(aList) {
-		for (var i=0; i < aList.count(); i++) {this.addCopy(aList.get(i));}
-	};
-	/**
-	 * checks if the index is valid and returns it if it is; if i == -1, the correct index is retrieved.
-	 *
-	 * @private
-	 * @return Integer or false
-	 * @type Integer
-	 */
-	this.getIndex = function(i){ 
-		var len = this.list.length;
-		if (i<0 && len + i > -1) {
-			return len + i;			
-		}
-		else if (i > -1 && i < len){
-			return i;
-		}
-		var e = new Mb_exception("class List: function getIndex: member index " + i + " is not valid");
-		return false;
-	};
-	/**
-	 * @returns a {String} representation of this List
-	 * @type String
-	 */
-	this.toString = function(){
-		var str = "";
-		for (var i =0 ; i < this.count() ; i++){
-			str += this.get(i).toString();
-		}
-		return str;	
-	};	
-	
-	this.list = null;
-};
-
-/**
- * A tree 
- * 
- * Using adjacency model 
- * 
- * w/ nested sets output
- */
-var CustomTree = function () {
-	this.root = new CustomTreeNode (null);
-	
-	var that = this;
-	
-	/**
-	 * Returns this tree as nested sets
-	 */
-	this.toString = function () {
-		// initialising recursion
-		var nodeArray = toStringNode.apply(this, [[], this.root, 1]);
-		return $.toJSON(nodeArray);
-	};
-
-	/**
-	 * Create this tree from nested sets
-	 */
-	this.fromString = function(str){
-		var nodeArray = eval(str);
-
-		if(nodeArray===undefined || nodeArray.length<1)
-			return false;
-		
-		//numeric sort function
-		var nodeSort = function(a,b){
-			return a.left-b.left;
-		}
-
-		//sort nodes by their left
-		nodeArray.sort(nodeSort);
-		
-		//apply root node
-		var currentNode = this.root;
-		currentNode.applyKeys(nodeArray[0]);
-
-		var rights = [nodeArray[0].right];
-		for(var i=1;i<nodeArray.length;i++){
-			//finish all nodes that have no further childs
-			while(rights[rights.length-1]<nodeArray[i].left){
-				rights.pop();
-				currentNode = currentNode.parentNode;
-				
-				//check if there is an errror in data or we have muliple roots				
-				if(currentNode == null)
-					return false;
-			}
-
-			//insert new node
-			var newNode = new CustomTreeNode(currentNode);
-			rights.push(nodeArray[i].right);
-			newNode.applyKeys(nodeArray[i]);
-			currentNode.append(newNode);
-			
-			//new node is the one that take next childs
-			currentNode = newNode;
-		}
-		return true;
-	}
-
-	var toStringNode = function (nodeArray, node, nextLeft) {
-		var left = nextLeft;
-		var right;
-		var newLeft = nextLeft + 1;
-		var nodeCount = node.childNodeList.count();
-
-		// node has children...
-		if (nodeCount > 0) {
-			for (var i = 0; i < nodeCount; i++) {
-				var currentChild = node.childNodeList.get(i);
-				// ... recursion
-				nodeArray = toStringNode.apply(that, [nodeArray, currentChild, newLeft]);
-				newLeft = nodeArray[-1 + nodeArray.length].right + 1;
-			}		
-			right = newLeft;
-		}
-		// node is a leaf...
-		else {
-			right = left + 1;
-		}
-		nodeArray.push({
-			"left": left,
-			"right": right,
-			"name": node.name
-		});
-		return nodeArray;
-	};
-};
-
-/**
- *  A list of nodes
- */
-var CustomTreeChildList = function () {
-	this.list = [];
-};
-
-CustomTreeChildList.prototype = new List();
-
-
-
-
-/**
- * A single node
- * 
- * @param {Object} parentNode
- */
-var CustomTreeNode = function (parentNode) {
-	this.name;
-	this.parentNode = parentNode;
-	this.childNodeList = new CustomTreeChildList();
-
-	this.$domNode = null;
-	
-	this.applyKeys = function(obj){
-		this.name = obj.name;
-	}
-
-	this.afterMove = function () {
-	};
-	
-	this.afterRemove = function () {
-	};
-	
-	this.afterAddChild = function () {
-	};
-
-	this.afterSetName = function () {
-	};
-
-	this.setName = function (newName) {
-		this.name = newName;
-		this.afterSetName();
-	};
-
-	this.addChild = function () {
-		this.childNodeList.add(new CustomTreeNode(this));
-		var newChild = this.childNodeList.get(-1);
-		newChild.name = "(new node)";
-		this.afterAddChild();
-		return newChild;
-	};
-	
-	this.getNumberOfChildren = function () {
-		var cnt = this.childNodeList.count();
-		var numOfChildren = cnt;
-		if (cnt > 0) {
-			for (var i = 0; i < cnt; i++) {
-				numOfChildren += this.childNodeList.get(i).getNumberOfChildren();				
-			}
-		}
-		return numOfChildren;
-	};
-	
-	this.remove = function () {
-		this.childNodeArray = [];
-		this.parentNode.removeChild(this);
-		this.parentNode = null;
-		this.afterRemove();
-	};
-	
-	this.removeChild = function (someNode) {
-		for (var i = 0;  i < this.childNodeList.count(); i++) {
-			var child = this.childNodeList.get(i);
-			if (child == someNode) {
-				this.childNodeList.del(i);
-				break;
-			}
-		}
-	};
-	
-	this.move = function (toParent) {
-		this.parentNode.removeChild(this);
-		toParent.append(this);
-		this.afterMove();
-	};
-	
-	this.append = function (someNode) {
-		someNode.parentNode = this;
-		this.childNodeList.add(someNode);
-	};
-};
\ No newline at end of file

Modified: branches/tree_dev/http/x_test/tree.html
===================================================================
--- branches/tree_dev/http/x_test/tree.html	2008-09-18 13:11:52 UTC (rev 2976)
+++ branches/tree_dev/http/x_test/tree.html	2008-09-18 13:23:55 UTC (rev 2977)
@@ -36,12 +36,18 @@
 	display:none;
 }
 </style>
+		<link rel='stylesheet' type='text/css' href='../css/popup.css'>
+		
 		<script type="text/javascript" src="../extensions/jquery-1.2.6.min.js"></script>
 		<script type="text/javascript" src="../extensions/jquery-ui-personalized-1.5.2.js"></script>
 		<script type="text/javascript" src="../extensions/jquery.contextmenu.r2.js"></script>
 		<script type="text/javascript" src="../extensions/jqjson.js"></script>
+		<script type="text/javascript" src="../javascripts/popup.js"></script>
+		<script type="text/javascript" src="../javascripts/event.js"></script>
 		<script type="text/javascript" src="customTreeModel.js"></script>
 		<script type="text/javascript" src="customTreeController.js"></script>
+		<script type="text/javascript" src="buttonNew.js"></script>
+		<script type="text/javascript" src="saveButton.js"></script>
 		<script type="text/javascript">
 
 			// see example at http://guxx.de/2007/05/30/nested-sets/
@@ -87,7 +93,7 @@
 			
 			var wmsTree = new CustomTree();
 			var wmsRoot = wmsTree.root;
-			wmsRoot.name = "(root)";
+			wmsRoot.name = "WMS";
 			
 			var wms1Node = new CustomTreeNode();
 			wms1Node.name = "Germany";
@@ -103,9 +109,42 @@
 			
 			
 			$(function () {
-				var displayTree = new customTreeController(myTree);
+				var displayTree = new customTreeController(myTree, {
+					contextMenu: true,
+					droppable: true
+				});
 			
-				var displayWmsTree = new customTreeController(wmsTree);
+				var displayWmsTree = new customTreeController(wmsTree, {
+					contextMenu: true,
+					droppable: true
+				});
+
+				//
+				// create the toolbox
+				//
+				var controlPopup;
+				controlPopup = new mb_popup({
+					left:300,
+					top:300,
+					width:180,
+					height:80,
+					html:"<div id='controls'></div>",
+					title:"Toolbox"
+				});
+				var toolbox = new ButtonGroup("controls");
+
+				// save tool
+				var saveButton = new Button(Save.buttonParameters);
+				toolbox.add(saveButton);
+
+				saveButton.registerPush(function () {
+					Save.updateDatabase(saveButton.triggerStop);	
+				});
+				
+				//
+				// display the toolbox
+				//
+				controlPopup.show();
 			});
 			
 		</script>

Added: branches/tree_dev/lib/buttonNew.js
===================================================================
--- branches/tree_dev/lib/buttonNew.js	                        (rev 0)
+++ branches/tree_dev/lib/buttonNew.js	2008-09-18 13:23:55 UTC (rev 2977)
@@ -0,0 +1,129 @@
+
+/**
+ * A group of buttons. 
+ */
+function ButtonGroup (nodeId) {
+	var buttonArray = [];
+	var node = "#" + nodeId;
+	
+	this.add = function (button) {
+		if (!button.constructor == "Button") {
+			console.log("not a button, but a %s", button.constructor);
+			return false;
+		}
+		if (button.type == "toggle") {
+			for (var i = 0; i < buttonArray.length; i++) {
+				var currentButton = buttonArray[i];
+				currentButton.registerPush(button.triggerStop);
+				button.registerPush(currentButton.triggerStop);
+			}
+		}
+		else if (button.type == "singular") {
+			button.registerPush(button.triggerStop);	
+		}
+		buttonArray.push(button);
+		$(node).append(button.getNode());
+	}
+}
+	
+	
+function Button (options) {
+	//
+	// API
+	//
+	this.registerStart = function (func) {
+		start.register(func);
+	};
+	
+	this.registerStop = function (func) {
+		stop.register(func);
+	};
+	
+	this.registerPush = function (func) {
+		push.register(func);
+	};
+	
+	this.registerRelease = function (func) {
+		release.register(func);
+	};
+
+	this.triggerStart = function () {
+		start.trigger();
+	};
+	
+	this.triggerStop = function () {
+		stop.trigger();
+	};
+
+	this.triggerPush = function () {
+		push.trigger();
+	};
+	
+	this.triggerRelease = function () {
+		release.trigger();
+	};
+
+	this.getNode = function () {
+		return $node;
+	};
+	
+	//
+	// constructor
+	//
+	/**
+	 * Is triggered if the button is pushed, may
+	 * also be triggered by other actions.
+	 * Changes the button image source.
+	 */
+	var start = new MapbenderEvent();
+	/**
+	 * Is triggered if the button is released, may
+	 * also be triggered by other actions.
+	 * Changes the button image source.
+	 */
+	var stop = new MapbenderEvent();
+	/**
+	 * Is only called after the button has been 
+	 * manually pushed by the user.
+	 * Triggers "start".
+	 */
+	var push = new MapbenderEvent();
+
+	/**
+	 * Is only called after the button has been 
+	 * manually released by the user.
+	 * Triggers "stop".
+	 */
+	var release = new MapbenderEvent();
+	
+	start.register(function() {
+		isOn = true;
+		$node.attr("src", srcOn);
+	});
+	
+	stop.register(function() {
+		$node.attr("src", srcOff);
+		isOn = false;
+	});
+	
+	push.register(function() {
+		start.trigger();
+	});
+	
+	release.register(function() {
+		stop.trigger();
+	});
+	
+	var srcOn = (options.on) ? options.on : null;
+	var srcOff = (options.off) ? options.off : null;
+	var srcOver = (options.over) ? options.over : null;
+	this.type = (options.type) ? options.type : "default";
+		 
+	var $node = $("<img style='padding:5px' src='" + srcOff + "'/>");
+	var isOn = false;
+	
+	$node.click(function() {
+		(!isOn) ? push.trigger() : release.trigger();	
+	});
+}
+

Copied: branches/tree_dev/lib/customTreeController.js (from rev 2953, branches/tree_dev/http/x_test/customTreeController.js)
===================================================================
--- branches/tree_dev/lib/customTreeController.js	                        (rev 0)
+++ branches/tree_dev/lib/customTreeController.js	2008-09-18 13:23:55 UTC (rev 2977)
@@ -0,0 +1,271 @@
+var currentlyDraggedNode;
+
+var customTreeController = function (myTree, options) {
+//	this.myTree = new CustomTree();
+//	this.myTree.root.name = "My tree";
+
+
+	this.options = options;
+	this.myTree = myTree;
+	
+	this.$root = $("<ul></ul>");
+
+	var that = this;
+	
+	// --------------- BEHAVIOUR (begin) ------------------
+	
+	var addLeafBehaviour = function ($domNode, treeNode) {
+		$label = $domNode.children().eq(0);
+		
+		// enable context menu
+		if (that.options.contextMenu) {
+			addContextMenuToLeaf($domNode, treeNode);
+		}
+
+		// make leaves draggable
+		makeNodeDraggable($domNode, treeNode);
+		
+		treeNode.hasChanged = function () {
+			console.log(that.myTree);
+		};
+	};
+	
+	var addFolderBehaviour = function ($domNode, treeNode) {
+		$label = $domNode.children().eq(0);
+		if (treeNode != that.myTree.root) {
+			// enable folder closing and opening
+			addOpenCloseBehaviour($label);
+
+			// enable context menu
+			if (that.options.contextMenu) {
+				addContextMenuToFolder($domNode, treeNode);
+			}
+
+			// make inner nodes draggable
+			makeNodeDraggable($domNode, treeNode);
+		}
+		else {
+			// enable context menu
+			if (that.options.contextMenu) {
+				addContextMenuToRoot($domNode, treeNode);
+			}
+		}		
+
+		// make all folders droppable
+		if (that.options.droppable) {
+			makeNodeDroppable($label, treeNode);
+		}
+
+		treeNode.hasChanged = function () {
+			console.log(that.myTree);
+		};
+	};
+
+
+	var deleteNode = function (treeNode) {
+		treeNode.remove();
+	};
+
+	var editNode = function ($domNode, treeNode) {
+		var newName = prompt('Name');
+		if (newName) {
+			treeNode.setName(newName);
+		}	
+	};
+	
+	var addNode = function ($domNode, treeNode) {
+		var newChild = treeNode.addChild();
+	};
+
+	//
+	// CONTEXT MENU
+	//
+	var addContextMenuToLeaf = function ($domNode, treeNode) {
+		$domNode.contextMenu('leafMenu', {
+			onContextMenu: function(e) {
+				return true;
+			},
+			onShowMenu: function(e, menu) {
+				return menu;
+			},
+			bindings: {
+				'deleteService': function () {
+					deleteNode(treeNode);
+				}
+			}
+		});
+	}
+	
+	var addContextMenuToFolder = function ($domNode, treeNode) {
+		$domNode.contextMenu('folderMenu', {
+			onContextMenu: function(e){
+				return true;
+			},
+			onShowMenu: function(e, menu){
+				return menu;
+			},
+			bindings: {
+				'addFolder': function(item){
+					addNode($domNode, treeNode);
+				},
+				'deleteFolder': function(){
+					deleteNode(treeNode);
+				},
+				'editFolder': function(){
+					editNode($domNode, treeNode);
+				}
+			}
+		});
+	};
+	
+	var addContextMenuToRoot = function ($domNode, treeNode) {
+		$domNode.contextMenu('rootMenu', {
+			onContextMenu: function(e){
+				return true;
+			},
+			onShowMenu: function(e, menu){
+				return menu;
+			},
+			bindings: {
+				'addFolder': function(item){
+					addNode($domNode, treeNode);
+				}
+			}
+		});
+	};
+	
+	//
+	// OPEN AND CLOSE BEHAVIOUR
+	// 
+	var addOpenCloseBehaviour = function ($domNode) {
+		$domNode.toggle(function () {
+			$(this).siblings().hide("fast");
+		}, function () {
+			$(this).siblings().show("fast");
+		});		
+	};
+	
+	//
+	// DRAGGABLE AND DROPPABLE
+	//
+	var makeNodeDraggable = function ($domNode, treeNode) {
+		$domNode.draggable({
+			"helper": "clone",
+			"start": function(){
+				$(this).addClass("currently-dragging");
+				currentlyDraggedNode = treeNode;
+			}
+		});
+	};
+	
+	var makeNodeDroppable = function ($domNode, treeNode) {
+		$domNode.droppable({
+			"accept": function ($draggable) {
+				var $invalidDroppables = $(".currently-dragging .treeNodeDrop");
+				var $invalidDroppablesMinusThis = $invalidDroppables.not($domNode);
+
+				if ($invalidDroppables.size() > $invalidDroppablesMinusThis.size()) {
+					return false;
+				}
+				return true;
+			},
+			"tolerance": "pointer", 
+			"drop": function (e, ui) {
+				$toDomNode = $(this);
+				$fromDomNode = $(ui.draggable);
+				
+				currentlyDraggedNode.afterMove = function () {
+					$toDomNode.next().append($(ui.draggable));
+					$(".treeLeaf").removeAttr("style");
+					$("*").removeClass("currently-dragging");
+				};
+				currentlyDraggedNode.move(treeNode);
+			}
+		});		
+	};
+	
+	// --------------- BEHAVIOUR (end) ------------------
+
+	var createLeaf = function (treeNode) {
+		var $currentItem = $("<li class='treeLeaf'></li>");
+		var $currentLabel = $("<span>" + treeNode.name + "</span>");
+
+		$currentItem.append($currentLabel);
+		addLeafBehaviour($currentItem, treeNode);
+
+		treeNode.$domNode = $currentItem;
+		treeNode.isFolder = false;
+
+		treeNode.afterRemove = function () {
+			$currentItem.remove();
+		};
+
+		return $currentItem;
+	};
+	
+	var createFolder = function (treeNode) {
+		var $currentItem = $("<li class='treeNode'></li>");
+		var $currentLabel = $("<div class='treeNodeDrop'><span>" + treeNode.name + "</span></div>");
+		var $currentFolder = $("<ul></ul>");
+		
+		$currentItem.append($currentLabel);
+		$currentItem.append($currentFolder);
+		treeNode.isFolder = true;
+
+		addFolderBehaviour($currentItem, treeNode);
+
+		treeNode.$domNode = $currentItem;
+
+		treeNode.afterRemove = function () {
+			$currentItem.remove();
+		};
+
+		treeNode.afterSetName = function () {
+			$currentLabel.children().eq(0).html(treeNode.name);
+		};
+
+		treeNode.afterAddChild = function (newChild) {
+			$newNode = createFolder(newChild);
+			var $folder = $currentItem.children().eq(1);
+			$folder.append($newNode);
+		};
+
+		treeNode.afterAppend = function (newChild) {
+			$newNode = createFolder(newChild);
+			var $folder = $currentItem.children().eq(1);
+			$folder.append($newNode);
+		};
+		return $currentItem;
+	};
+	
+	/**
+	 *  A recursive function to draw the nodes of a tree and attach 
+	 *  draggables and droppables
+	 *  
+	 * @param {Object} $domNode
+	 * @param {Object} treeNode
+	 */
+	var drawNode = function ($domNode, treeNode) {
+		var numOfChildren = treeNode.childNodeList.count();
+		var $newNode;
+
+		if (numOfChildren === 0 && treeNode != that.myTree.root && !treeNode.isFolder) {
+			$newNode = createLeaf(treeNode);
+		}
+		else {
+			$newNode = createFolder(treeNode);
+
+			// visit the child nodes (depth first)
+			var $folder = $newNode.children().eq(1);
+			for (var i = 0; i < numOfChildren; i++) {
+				drawNode.apply(that, [$folder, treeNode.childNodeList.get(i)]);
+			}
+		}		
+		// attach node to tree
+		$domNode.append($newNode);
+	};
+
+	$("#" + this.options.id).empty();
+	$("#" + this.options.id).append(that.$root);
+	drawNode(that.$root, that.myTree.root);
+};
\ No newline at end of file

Copied: branches/tree_dev/lib/customTreeModel.js (from rev 2953, branches/tree_dev/http/x_test/customTreeModel.js)
===================================================================
--- branches/tree_dev/lib/customTreeModel.js	                        (rev 0)
+++ branches/tree_dev/lib/customTreeModel.js	2008-09-18 13:23:55 UTC (rev 2977)
@@ -0,0 +1,390 @@
+/**
+ * @class A List object is an array of arbitrary objects with additional methods. 
+ *
+ * @constructor
+ */
+var List = function() {
+	
+	/**
+	 * gets the number of elements in this {@link List}
+	 *
+	 * @returns number of elements in this {@link List}
+	 * @type Integer
+	 */
+	this.count = function() {
+		return this.list.length;
+	};
+
+	/**
+	 * deletes the object at index i; -1 refers to the last object in this {@link List}
+	 *
+	 * @param {Integer} i index
+	 */
+	this.del = function(i){
+		i = this.getIndex(i);
+		if (i !== false) {
+			for(var z = i; z < this.count() - 1; z++){
+				this.list[z] = this.list[z+1];
+			}
+			this.list.length -= 1;
+			return true;
+		}
+		return false;
+	};
+
+	/**
+	 * empties this {@link List}
+	 */
+	this.empty = function() {
+		while (this.list !== null && this.count() > 0) {
+			this.list.pop();
+		}
+	};
+	
+	/**
+	 * @param {Integer} i index
+	 * @returns the object at index i; -1 refers to the last object in this {@link List}
+	 * @type Integer or false
+	 */
+	this.get = function(i) {
+		i = this.getIndex(i);
+		if (i !== false) {return this.list[i];}
+		return false;		
+	};
+	/**
+	 * adds a reference to item to this {@link List}.
+	 *
+	 * @param {Object} item an object
+	 */
+	this.add = function(item) {
+		var i = this.list.length;
+		this.list[i] = item;
+	};
+	/**
+	 * adds a copy of item to this {@link List}.
+	 *
+	 * @param {Object} item an object
+	 */
+	this.addCopy = function(item) {
+		this.add(cloneObject(item));
+	};
+	/**
+	 * attaches the {@link List} aList to this {@link List}
+	 *
+	 * @param {List} aList another list
+	 */
+	this.union = function(aList) {
+		for (var i=0; i < aList.count(); i++) {this.addCopy(aList.get(i));}
+	};
+	/**
+	 * checks if the index is valid and returns it if it is; if i == -1, the correct index is retrieved.
+	 *
+	 * @private
+	 * @return Integer or false
+	 * @type Integer
+	 */
+	this.getIndex = function(i){ 
+		var len = this.list.length;
+		if (i<0 && len + i > -1) {
+			return len + i;			
+		}
+		else if (i > -1 && i < len){
+			return i;
+		}
+		var e = new Mb_exception("class List: function getIndex: member index " + i + " is not valid");
+		return false;
+	};
+	/**
+	 * @returns a {String} representation of this List
+	 * @type String
+	 */
+	this.toString = function(){
+		var str = "";
+		for (var i =0 ; i < this.count() ; i++){
+			str += this.get(i).toString();
+		}
+		return str;	
+	};	
+	
+	this.list = null;
+};
+
+/**
+ * A tree 
+ * 
+ * Using adjacency model 
+ * 
+ * w/ nested sets output
+ */
+var CustomTree = function () {
+	this.root = new CustomTreeNode (null);
+	
+	var that = this;
+	
+	this.toNestedSets = function () {
+		var nodeArray = toNestedSetsNode.apply(this, [[], this.root, 1]);
+		return nodeArray;
+	}
+	
+	var toNestedSetsNode = function (nodeArray, node, nextLeft) {
+		var left = nextLeft;
+		var right;
+		var newLeft = nextLeft + 1;
+		var nodeCount = node.childNodeList.count();
+		var wmsIdArray = [];
+
+		var containsFolder = false;
+		for (var i = 0; i < nodeCount; i++) {
+			var currentChild = node.childNodeList.get(i);
+			// ... recursion
+			if (currentChild.isFolder) {
+				nodeArray = toNestedSetsNode.apply(that, [nodeArray, currentChild, newLeft]);
+				newLeft = nodeArray[-1 + nodeArray.length].right + 1;
+				containsFolder = true;
+			}
+			else {
+				wmsIdArray.push(currentChild.wmsId);
+			}
+		}		
+
+		// node has NOT at least one child which is a folder
+		if (containsFolder) {
+			right = newLeft;
+		}
+		else {
+			right = left + 1;
+		}
+
+		nodeArray.push({
+			"left": left,
+			"right": right,
+			"name": node.name,
+			"isFolder": node.isFolder,
+			"wms": wmsIdArray.join(",")
+		});
+		return nodeArray;
+	};
+
+	/**
+	 * Returns this tree as nested sets
+	 */
+	this.toString = function () {
+		return $.toJSON(this.exportNestedSets());
+	};
+
+	this.exportNestedSets = function () {
+		// initialising recursion
+		return nodeArray = toNestedSetsNode.apply(this, [[], this.root, 1]);
+	};
+
+	/**
+	 * Create this tree from nested sets
+	 */
+	this.fromString = function(str){
+		var nodeArray = eval(str);
+		this.importNestedSets(nodeArray);
+	};
+
+	this.importNestedSets = function (nodeArray) {
+		
+		if(nodeArray===undefined || nodeArray.length<1)
+			return false;
+		
+		//numeric sort function
+		var nodeSort = function(a,b){
+			return a.left-b.left;
+		}
+
+		//sort nodes by their left
+		nodeArray.sort(nodeSort);
+		
+		//apply root node
+		var currentNode = this.root;
+		currentNode.applyKeys(nodeArray[0]);
+
+		var rights = [nodeArray[0].right];
+		for (var i = 1; i < nodeArray.length; i++) {
+
+			//finish all nodes that have no further childs
+			while (rights[rights.length-1] < nodeArray[i].left){
+				rights.pop();
+				currentNode = currentNode.parentNode;
+				
+				//check if there is an error in data or we have muliple roots				
+				if(currentNode == null)
+					return false;
+			}
+
+			//insert new node
+			var newNode = new CustomTreeNode(currentNode);
+			rights.push(nodeArray[i].right);
+			newNode.applyKeys(nodeArray[i]);
+			currentNode.append(newNode);
+
+			// add WMS
+			var wmsIdArray = nodeArray[i].wms;
+			for (var j in wmsIdArray) {
+				var newWmsNode = new CustomTreeNode(newNode);
+				newWmsNode.wmsId = j;
+				newWmsNode.name = wmsIdArray[j];
+				newNode.append(newWmsNode);
+			}
+			
+			//new node is the one that take next childs
+			currentNode = newNode;
+		}
+		return true;
+	}
+
+	var toStringNode = function (nodeArray, node, nextLeft) {
+		var left = nextLeft;
+		var right;
+		var newLeft = nextLeft + 1;
+		var nodeCount = node.childNodeList.count();
+
+		// node has children...
+		if (nodeCount > 0) {
+			for (var i = 0; i < nodeCount; i++) {
+				var currentChild = node.childNodeList.get(i);
+				// ... recursion
+				nodeArray = toStringNode.apply(that, [nodeArray, currentChild, newLeft]);
+				newLeft = nodeArray[-1 + nodeArray.length].right + 1;
+			}		
+			right = newLeft;
+		}
+		// node is a leaf...
+		else {
+			right = left + 1;
+		}
+		nodeArray.push({
+			"left": left,
+			"right": right,
+			"name": node.name,
+			"id": node.id
+		});
+		return nodeArray;
+	};
+	
+	this.empty = function () {
+		for (var i = -1 + this.root.childNodeList.count(); i >= 0; i--) {
+			var currentChild = this.root.childNodeList.get(i);
+			currentChild.remove();
+		}
+	};
+};
+
+/**
+ *  A list of nodes
+ */
+var CustomTreeChildList = function () {
+	this.list = [];
+};
+
+CustomTreeChildList.prototype = new List();
+
+
+
+
+/**
+ * A single node
+ * 
+ * @param {Object} parentNode
+ */
+var CustomTreeNode = function (parentNode) {
+	this.name;
+	this.isFolder = false;
+	this.parentNode = parentNode;
+	this.childNodeList = new CustomTreeChildList();
+
+	this.applyKeys = function(obj){
+		this.name = obj.name;
+	}
+
+	this.afterMove = function () {
+	};
+	
+	this.afterRemove = function () {
+	};
+	
+	this.afterAddChild = function () {
+	};
+
+	this.afterSetName = function () {
+	};
+
+	this.setName = function (newName) {
+		this.name = newName;
+		this.afterSetName();
+		this.hasChanged();
+	};
+
+	this.hasChanged = function () {
+		
+	};
+	
+	this.addChild = function () {
+		this.childNodeList.add(new CustomTreeNode(this));
+
+		var newChild = this.childNodeList.get(-1);
+		newChild.name = "(new node)";
+		newChild.isFolder = true;
+
+		this.afterAddChild(newChild);
+		this.hasChanged();
+		return newChild;
+	};
+	
+	this.getNumberOfChildren = function () {
+		var cnt = this.childNodeList.count();
+		var numOfChildren = cnt;
+		if (cnt > 0) {
+			for (var i = 0; i < cnt; i++) {
+				numOfChildren += this.childNodeList.get(i).getNumberOfChildren();				
+			}
+		}
+		return numOfChildren;
+	};
+	
+	this.remove = function () {
+		this.childNodeArray = [];
+		this.parentNode.removeChild(this);
+		this.parentNode = null;
+		this.afterRemove();
+		this.hasChanged();
+	};
+	
+	this.removeChild = function (someNode) {
+		for (var i = 0;  i < this.childNodeList.count(); i++) {
+			var child = this.childNodeList.get(i);
+			if (child == someNode) {
+				this.childNodeList.del(i);
+				break;
+			}
+		}
+	};
+	
+	this.move = function (toParent) {
+		this.parentNode.removeChild(this);
+		toParent.append(this);
+		this.afterMove();
+		this.hasChanged();
+	};
+	
+	this.append = function (someNode) {
+		someNode.parentNode = this;
+		this.childNodeList.add(someNode);
+		this.isFolder = true;
+//		this.afterAppend(someNode);
+		this.hasChanged();
+	};
+	
+	this.containsFolder = function () {
+		for (var i = 0;  i < this.childNodeList.count(); i++) {
+			var child = this.childNodeList.get(i);
+			if (child.isFolder) {
+				return true;
+			}
+		}
+		return false;	
+	};
+};
\ No newline at end of file



More information about the Mapbender_commits mailing list