[Mapbender-commits] r3957 - in branches/print_dev: http/extensions http/img http/img/button_digitize http/javascripts http/php lib resources/db/update

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Fri May 22 08:10:55 EDT 2009


Author: mschulz
Date: 2009-05-22 08:10:55 -0400 (Fri, 22 May 2009)
New Revision: 3957

Added:
   branches/print_dev/http/extensions/jquery-ui-personalized-1.5.2.js
   branches/print_dev/http/extensions/jquery.contextmenu.r2.js
   branches/print_dev/http/img/OSGeo_logo.png
   branches/print_dev/http/img/button_digitize/geomClone.png
   branches/print_dev/http/javascripts/mod_addWmsFromFilteredList_button.php
   branches/print_dev/http/php/mod_customTree.php
   branches/print_dev/http/php/mod_customTree_server.php
   branches/print_dev/lib/customTreeController.js
   branches/print_dev/lib/customTreeModel.js
   branches/print_dev/resources/db/update/update_2.7.sql
Log:
merged from trunk

Added: branches/print_dev/http/extensions/jquery-ui-personalized-1.5.2.js
===================================================================
--- branches/print_dev/http/extensions/jquery-ui-personalized-1.5.2.js	                        (rev 0)
+++ branches/print_dev/http/extensions/jquery-ui-personalized-1.5.2.js	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,1134 @@
+/*
+ * jQuery UI @VERSION
+ *
+ * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI
+ */
+;(function($) {
+
+$.ui = {
+	plugin: {
+		add: function(module, option, set) {
+			var proto = $.ui[module].prototype;
+			for(var i in set) {
+				proto.plugins[i] = proto.plugins[i] || [];
+				proto.plugins[i].push([option, set[i]]);
+			}
+		},
+		call: function(instance, name, args) {
+			var set = instance.plugins[name];
+			if(!set) { return; }
+			
+			for (var i = 0; i < set.length; i++) {
+				if (instance.options[set[i][0]]) {
+					set[i][1].apply(instance.element, args);
+				}
+			}
+		}	
+	},
+	cssCache: {},
+	css: function(name) {
+		if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; }
+		var tmp = $('<div class="ui-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
+		
+		//if (!$.browser.safari)
+			//tmp.appendTo('body'); 
+		
+		//Opera and Safari set width and height to 0px instead of auto
+		//Safari returns rgba(0,0,0,0) when bgcolor is not set
+		$.ui.cssCache[name] = !!(
+			(!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
+			!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
+		);
+		try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
+		return $.ui.cssCache[name];
+	},
+	disableSelection: function(el) {
+		$(el).attr('unselectable', 'on').css('MozUserSelect', 'none');
+	},
+	enableSelection: function(el) {
+		$(el).attr('unselectable', 'off').css('MozUserSelect', '');
+	},
+	hasScroll: function(e, a) {
+		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
+		if (e[scroll] > 0) return true; e[scroll] = 1;
+		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
+		return has;
+	}
+};
+
+
+/** jQuery core modifications and additions **/
+
+var _remove = $.fn.remove;
+$.fn.remove = function() {
+	$("*", this).add(this).triggerHandler("remove");
+	return _remove.apply(this, arguments );
+};
+
+// $.widget is a factory to create jQuery plugins
+// taking some boilerplate code out of the plugin code
+// created by Scott González and Jörn Zaefferer
+function getter(namespace, plugin, method) {
+	var methods = $[namespace][plugin].getter || [];
+	methods = (typeof methods == "string" ? methods.split(/,?\s+/) : methods);
+	return ($.inArray(method, methods) != -1);
+}
+
+$.widget = function(name, prototype) {
+	var namespace = name.split(".")[0];
+	name = name.split(".")[1];
+	
+	// create plugin method
+	$.fn[name] = function(options) {
+		var isMethodCall = (typeof options == 'string'),
+			args = Array.prototype.slice.call(arguments, 1);
+		
+		if (isMethodCall && getter(namespace, name, options)) {
+			var instance = $.data(this[0], name);
+			return (instance ? instance[options].apply(instance, args)
+				: undefined);
+		}
+		
+		return this.each(function() {
+			var instance = $.data(this, name);
+			if (isMethodCall && instance && $.isFunction(instance[options])) {
+				instance[options].apply(instance, args);
+			} else if (!isMethodCall) {
+				$.data(this, name, new $[namespace][name](this, options));
+			}
+		});
+	};
+	
+	// create widget constructor
+	$[namespace][name] = function(element, options) {
+		var self = this;
+		
+		this.widgetName = name;
+		this.widgetBaseClass = namespace + '-' + name;
+		
+		this.options = $.extend({}, $.widget.defaults, $[namespace][name].defaults, options);
+		this.element = $(element)
+			.bind('setData.' + name, function(e, key, value) {
+				return self.setData(key, value);
+			})
+			.bind('getData.' + name, function(e, key) {
+				return self.getData(key);
+			})
+			.bind('remove', function() {
+				return self.destroy();
+			});
+		this.init();
+	};
+	
+	// add widget prototype
+	$[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+};
+
+$.widget.prototype = {
+	init: function() {},
+	destroy: function() {
+		this.element.removeData(this.widgetName);
+	},
+	
+	getData: function(key) {
+		return this.options[key];
+	},
+	setData: function(key, value) {
+		this.options[key] = value;
+		
+		if (key == 'disabled') {
+			this.element[value ? 'addClass' : 'removeClass'](
+				this.widgetBaseClass + '-disabled');
+		}
+	},
+	
+	enable: function() {
+		this.setData('disabled', false);
+	},
+	disable: function() {
+		this.setData('disabled', true);
+	}
+};
+
+$.widget.defaults = {
+	disabled: false
+};
+
+
+/** Mouse Interaction Plugin **/
+
+$.ui.mouse = {
+	mouseInit: function() {
+		var self = this;
+	
+		this.element.bind('mousedown.'+this.widgetName, function(e) {
+			return self.mouseDown(e);
+		});
+		
+		// Prevent text selection in IE
+		if ($.browser.msie) {
+			this._mouseUnselectable = this.element.attr('unselectable');
+			this.element.attr('unselectable', 'on');
+		}
+		
+		this.started = false;
+	},
+	
+	// TODO: make sure destroying one instance of mouse doesn't mess with
+	// other instances of mouse
+	mouseDestroy: function() {
+		this.element.unbind('.'+this.widgetName);
+		
+		// Restore text selection in IE
+		($.browser.msie
+			&& this.element.attr('unselectable', this._mouseUnselectable));
+	},
+	
+	mouseDown: function(e) {
+		// we may have missed mouseup (out of window)
+		(this._mouseStarted && this.mouseUp(e));
+		
+		this._mouseDownEvent = e;
+		
+		var self = this,
+			btnIsLeft = (e.which == 1),
+			elIsCancel = (typeof this.options.cancel == "string" ? $(e.target).parents().add(e.target).filter(this.options.cancel).length : false);
+		if (!btnIsLeft || elIsCancel || !this.mouseCapture(e)) {
+			return true;
+		}
+		
+		this._mouseDelayMet = !this.options.delay;
+		if (!this._mouseDelayMet) {
+			this._mouseDelayTimer = setTimeout(function() {
+				self._mouseDelayMet = true;
+			}, this.options.delay);
+		}
+		
+		if (this.mouseDistanceMet(e) && this.mouseDelayMet(e)) {
+			this._mouseStarted = (this.mouseStart(e) !== false);
+			if (!this._mouseStarted) {
+				e.preventDefault();
+				return true;
+			}
+		}
+		
+		// these delegates are required to keep context
+		this._mouseMoveDelegate = function(e) {
+			return self.mouseMove(e);
+		};
+		this._mouseUpDelegate = function(e) {
+			return self.mouseUp(e);
+		};
+		$(document)
+			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+		
+		return false;
+	},
+	
+	mouseMove: function(e) {
+		// IE mouseup check - mouseup happened when mouse was out of window
+		if ($.browser.msie && !e.button) {
+			return this.mouseUp(e);
+		}
+		
+		if (this._mouseStarted) {
+			this.mouseDrag(e);
+			return false;
+		}
+		
+		if (this.mouseDistanceMet(e) && this.mouseDelayMet(e)) {
+			this._mouseStarted =
+				(this.mouseStart(this._mouseDownEvent, e) !== false);
+			(this._mouseStarted ? this.mouseDrag(e) : this.mouseUp(e));
+		}
+		
+		return !this._mouseStarted;
+	},
+	
+	mouseUp: function(e) {
+		$(document)
+			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+		
+		if (this._mouseStarted) {
+			this._mouseStarted = false;
+			this.mouseStop(e);
+		}
+		
+		return false;
+	},
+	
+	mouseDistanceMet: function(e) {
+		return (Math.max(
+				Math.abs(this._mouseDownEvent.pageX - e.pageX),
+				Math.abs(this._mouseDownEvent.pageY - e.pageY)
+			) >= this.options.distance
+		);
+	},
+	
+	mouseDelayMet: function(e) {
+		return this._mouseDelayMet;
+	},
+	
+	// These are placeholder methods, to be overriden by extending plugin
+	mouseStart: function(e) {},
+	mouseDrag: function(e) {},
+	mouseStop: function(e) {},
+	mouseCapture: function(e) { return true; }
+};
+
+$.ui.mouse.defaults = {
+	cancel: null,
+	distance: 1,
+	delay: 0
+};
+
+})(jQuery);
+/*
+ * jQuery UI Draggable
+ *
+ * Copyright (c) 2008 Paul Bakaus
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Draggables
+ *
+ * Depends:
+ *	ui.core.js
+ */
+(function($) {
+
+$.widget("ui.draggable", $.extend({}, $.ui.mouse, {
+	init: function() {
+		
+		//Initialize needed constants
+		var o = this.options;
+
+		//Position the node
+		if (o.helper == 'original' && !(/(relative|absolute|fixed)/).test(this.element.css('position')))
+			this.element.css('position', 'relative');
+
+		this.element.addClass('ui-draggable');
+		(o.disabled && this.element.addClass('ui-draggable-disabled'));
+		
+		this.mouseInit();
+		
+	},
+	mouseStart: function(e) {
+		var o = this.options;
+		
+		if (this.helper || o.disabled || $(e.target).is('.ui-resizable-handle')) return false;
+		
+		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
+		
+	
+		$(this.options.handle, this.element).find("*").andSelf().each(function() {
+			if(this == e.target) handle = true;
+		});
+		if (!handle) return false;
+		
+		if($.ui.ddmanager) $.ui.ddmanager.current = this;
+		
+		//Create and append the visible helper
+		this.helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone() : this.element);
+		if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+		if(this.helper[0] != this.element[0] && !(/(fixed|absolute)/).test(this.helper.css("position"))) this.helper.css("position", "absolute");
+		
+		/*
+		 * - Position generation -
+		 * This block generates everything position related - it's the core of draggables.
+		 */
+		
+		this.margins = {																				//Cache the margins
+			left: (parseInt(this.element.css("marginLeft"),10) || 0),
+			top: (parseInt(this.element.css("marginTop"),10) || 0)
+		};		
+		
+		this.cssPosition = this.helper.css("position");													//Store the helper's css position
+		this.offset = this.element.offset();															//The element's absolute position on the page
+		this.offset = {																					//Substract the margins from the element's absolute offset
+			top: this.offset.top - this.margins.top,
+			left: this.offset.left - this.margins.left
+		};
+		
+		this.offset.click = {																			//Where the click happened, relative to the element
+			left: e.pageX - this.offset.left,
+			top: e.pageY - this.offset.top
+		};
+		
+		this.offsetParent = this.helper.offsetParent(); var po = this.offsetParent.offset();			//Get the offsetParent and cache its position
+		if(this.offsetParent[0] == document.body && $.browser.mozilla) po = { top: 0, left: 0 };		//Ugly FF3 fix
+		this.offset.parent = {																			//Store its position plus border
+			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+		};
+		
+		var p = this.element.position();																//This is a relative to absolute position minus the actual position calculation - only used for relative positioned helpers
+		this.offset.relative = this.cssPosition == "relative" ? {
+			top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.offsetParent[0].scrollTop,
+			left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.offsetParent[0].scrollLeft
+		} : { top: 0, left: 0 };
+		
+		this.originalPosition = this.generatePosition(e);												//Generate the original position
+		this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };//Cache the helper size
+		
+		if(o.cursorAt) {
+			if(o.cursorAt.left != undefined) this.offset.click.left = o.cursorAt.left + this.margins.left;
+			if(o.cursorAt.right != undefined) this.offset.click.left = this.helperProportions.width - o.cursorAt.right + this.margins.left;
+			if(o.cursorAt.top != undefined) this.offset.click.top = o.cursorAt.top + this.margins.top;
+			if(o.cursorAt.bottom != undefined) this.offset.click.top = this.helperProportions.height - o.cursorAt.bottom + this.margins.top;
+		}
+		
+		
+		/*
+		 * - Position constraining -
+		 * Here we prepare position constraining like grid and containment.
+		 */	
+		
+		if(o.containment) {
+			if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+			if(o.containment == 'document' || o.containment == 'window') this.containment = [
+				0 - this.offset.relative.left - this.offset.parent.left,
+				0 - this.offset.relative.top - this.offset.parent.top,
+				$(o.containment == 'document' ? document : window).width() - this.offset.relative.left - this.offset.parent.left - this.helperProportions.width - this.margins.left - (parseInt(this.element.css("marginRight"),10) || 0),
+				($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.offset.relative.top - this.offset.parent.top - this.helperProportions.height - this.margins.top - (parseInt(this.element.css("marginBottom"),10) || 0)
+			];
+			
+			if(!(/^(document|window|parent)$/).test(o.containment)) {
+				var ce = $(o.containment)[0];
+				var co = $(o.containment).offset();
+				
+				this.containment = [
+					co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) - this.offset.relative.left - this.offset.parent.left,
+					co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) - this.offset.relative.top - this.offset.parent.top,
+					co.left+Math.max(ce.scrollWidth,ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - this.offset.relative.left - this.offset.parent.left - this.helperProportions.width - this.margins.left - (parseInt(this.element.css("marginRight"),10) || 0),
+					co.top+Math.max(ce.scrollHeight,ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - this.offset.relative.top - this.offset.parent.top - this.helperProportions.height - this.margins.top - (parseInt(this.element.css("marginBottom"),10) || 0)
+				];
+			}
+		}
+		
+		//Call plugins and callbacks
+		this.propagate("start", e);
+		
+		this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };//Recache the helper size
+		if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
+		
+		this.helper.addClass("ui-draggable-dragging");
+		this.mouseDrag(e); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+		return true;
+	},
+	convertPositionTo: function(d, pos) {
+		if(!pos) pos = this.position;
+		var mod = d == "absolute" ? 1 : -1;
+		return {
+			top: (
+				pos.top																	// the calculated relative position
+				+ this.offset.relative.top	* mod										// Only for relative positioned nodes: Relative offset from element to offset parent
+				+ this.offset.parent.top * mod											// The offsetParent's offset without borders (offset + border)
+				- (this.cssPosition == "fixed" || (this.cssPosition == "absolute" && this.offsetParent[0] == document.body) ? 0 : this.offsetParent[0].scrollTop) * mod	// The offsetParent's scroll position, not if the element is fixed
+				+ (this.cssPosition == "fixed" ? $(document).scrollTop() : 0) * mod
+				+ this.margins.top * mod												//Add the margin (you don't want the margin counting in intersection methods)
+			),
+			left: (
+				pos.left																// the calculated relative position
+				+ this.offset.relative.left	* mod										// Only for relative positioned nodes: Relative offset from element to offset parent
+				+ this.offset.parent.left * mod											// The offsetParent's offset without borders (offset + border)
+				- (this.cssPosition == "fixed" || (this.cssPosition == "absolute" && this.offsetParent[0] == document.body) ? 0 : this.offsetParent[0].scrollLeft) * mod	// The offsetParent's scroll position, not if the element is fixed
+				+ (this.cssPosition == "fixed" ? $(document).scrollLeft() : 0) * mod
+				+ this.margins.left * mod												//Add the margin (you don't want the margin counting in intersection methods)
+			)
+		};
+	},
+	generatePosition: function(e) {
+		
+		var o = this.options;
+		var position = {
+			top: (
+				e.pageY																	// The absolute mouse position
+				- this.offset.click.top													// Click offset (relative to the element)
+				- this.offset.relative.top												// Only for relative positioned nodes: Relative offset from element to offset parent
+				- this.offset.parent.top												// The offsetParent's offset without borders (offset + border)
+				+ (this.cssPosition == "fixed" || (this.cssPosition == "absolute" && this.offsetParent[0] == document.body) ? 0 : this.offsetParent[0].scrollTop)	// The offsetParent's scroll position, not if the element is fixed
+				- (this.cssPosition == "fixed" ? $(document).scrollTop() : 0)
+			),
+			left: (
+				e.pageX																	// The absolute mouse position
+				- this.offset.click.left												// Click offset (relative to the element)
+				- this.offset.relative.left												// Only for relative positioned nodes: Relative offset from element to offset parent
+				- this.offset.parent.left												// The offsetParent's offset without borders (offset + border)
+				+ (this.cssPosition == "fixed" || (this.cssPosition == "absolute" && this.offsetParent[0] == document.body) ? 0 : this.offsetParent[0].scrollLeft)	// The offsetParent's scroll position, not if the element is fixed
+				- (this.cssPosition == "fixed" ? $(document).scrollLeft() : 0)
+			)
+		};
+		
+		if(!this.originalPosition) return position;										//If we are not dragging yet, we won't check for options
+		
+		/*
+		 * - Position constraining -
+		 * Constrain the position to a mix of grid, containment.
+		 */
+		if(this.containment) {
+			if(position.left < this.containment[0]) position.left = this.containment[0];
+			if(position.top < this.containment[1]) position.top = this.containment[1];
+			if(position.left > this.containment[2]) position.left = this.containment[2];
+			if(position.top > this.containment[3]) position.top = this.containment[3];
+		}
+		
+		if(o.grid) {
+			var top = this.originalPosition.top + Math.round((position.top - this.originalPosition.top) / o.grid[1]) * o.grid[1];
+			position.top = this.containment ? (!(top < this.containment[1] || top > this.containment[3]) ? top : (!(top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+			
+			var left = this.originalPosition.left + Math.round((position.left - this.originalPosition.left) / o.grid[0]) * o.grid[0];
+			position.left = this.containment ? (!(left < this.containment[0] || left > this.containment[2]) ? left : (!(left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+		}
+		
+		return position;
+	},
+	mouseDrag: function(e) {
+		
+		//Compute the helpers position
+		this.position = this.generatePosition(e);
+		this.positionAbs = this.convertPositionTo("absolute");
+		
+		//Call plugins and callbacks and use the resulting position if something is returned		
+		this.position = this.propagate("drag", e) || this.position;
+		
+		if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+		if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+		if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
+		
+		return false;
+	},
+	mouseStop: function(e) {
+		
+		//If we are using droppables, inform the manager about the drop
+		var dropped = false;
+		if ($.ui.ddmanager && !this.options.dropBehaviour)
+			var dropped = $.ui.ddmanager.drop(this, e);		
+		
+		if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true) {
+			var self = this;
+			$(this.helper).animate(this.originalPosition, parseInt(this.options.revert, 10) || 500, function() {
+				self.propagate("stop", e);
+				self.clear();
+			});
+		} else {
+			this.propagate("stop", e);
+			this.clear();
+		}
+		
+		return false;
+	},
+	clear: function() {
+		this.helper.removeClass("ui-draggable-dragging");
+		if(this.options.helper != 'original' && !this.cancelHelperRemoval) this.helper.remove();
+		//if($.ui.ddmanager) $.ui.ddmanager.current = null;
+		this.helper = null;
+		this.cancelHelperRemoval = false;
+	},
+	
+	// From now on bulk stuff - mainly helpers
+	plugins: {},
+	uiHash: function(e) {
+		return {
+			helper: this.helper,
+			position: this.position,
+			absolutePosition: this.positionAbs,
+			options: this.options			
+		};
+	},
+	propagate: function(n,e) {
+		$.ui.plugin.call(this, n, [e, this.uiHash()]);
+		if(n == "drag") this.positionAbs = this.convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
+		return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.uiHash()], this.options[n]);
+	},
+	destroy: function() {
+		if(!this.element.data('draggable')) return;
+		this.element.removeData("draggable").unbind(".draggable").removeClass('ui-draggable');
+		this.mouseDestroy();
+	}
+}));
+
+$.extend($.ui.draggable, {
+	defaults: {
+		appendTo: "parent",
+		axis: false,
+		cancel: ":input",
+		delay: 0,
+		distance: 1,
+		helper: "original"
+	}
+});
+
+$.ui.plugin.add("draggable", "cursor", {
+	start: function(e, ui) {
+		var t = $('body');
+		if (t.css("cursor")) ui.options._cursor = t.css("cursor");
+		t.css("cursor", ui.options.cursor);
+	},
+	stop: function(e, ui) {
+		if (ui.options._cursor) $('body').css("cursor", ui.options._cursor);
+	}
+});
+
+$.ui.plugin.add("draggable", "zIndex", {
+	start: function(e, ui) {
+		var t = $(ui.helper);
+		if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex");
+		t.css('zIndex', ui.options.zIndex);
+	},
+	stop: function(e, ui) {
+		if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex);
+	}
+});
+
+$.ui.plugin.add("draggable", "opacity", {
+	start: function(e, ui) {
+		var t = $(ui.helper);
+		if(t.css("opacity")) ui.options._opacity = t.css("opacity");
+		t.css('opacity', ui.options.opacity);
+	},
+	stop: function(e, ui) {
+		if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity);
+	}
+});
+
+$.ui.plugin.add("draggable", "iframeFix", {
+	start: function(e, ui) {
+		$(ui.options.iframeFix === true ? "iframe" : ui.options.iframeFix).each(function() {					
+			$('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
+			.css({
+				width: this.offsetWidth+"px", height: this.offsetHeight+"px",
+				position: "absolute", opacity: "0.001", zIndex: 1000
+			})
+			.css($(this).offset())
+			.appendTo("body");
+		});
+	},
+	stop: function(e, ui) {
+		$("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	
+	}
+});
+
+$.ui.plugin.add("draggable", "scroll", {
+	start: function(e, ui) {
+		var o = ui.options;
+		var i = $(this).data("draggable");
+		o.scrollSensitivity	= o.scrollSensitivity || 20;
+		o.scrollSpeed		= o.scrollSpeed || 20;
+		
+		i.overflowY = function(el) {
+			do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode);
+			return $(document);
+		}(this);
+		i.overflowX = function(el) {
+			do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode);
+			return $(document);
+		}(this);
+		
+		if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') i.overflowYOffset = i.overflowY.offset();
+		if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') i.overflowXOffset = i.overflowX.offset();
+		
+	},
+	drag: function(e, ui) {
+		
+		var o = ui.options;
+		var i = $(this).data("draggable");
+		
+		if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') {
+			if((i.overflowYOffset.top + i.overflowY[0].offsetHeight) - e.pageY < o.scrollSensitivity)
+				i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed;
+			if(e.pageY - i.overflowYOffset.top < o.scrollSensitivity)
+				i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;
+							
+		} else {
+			if(e.pageY - $(document).scrollTop() < o.scrollSensitivity)
+				$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+			if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+				$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+		}
+		
+		if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') {
+			if((i.overflowXOffset.left + i.overflowX[0].offsetWidth) - e.pageX < o.scrollSensitivity)
+				i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed;
+			if(e.pageX - i.overflowXOffset.left < o.scrollSensitivity)
+				i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;
+		} else {
+			if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+				$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+			if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+				$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+		}
+		
+	}
+});
+
+$.ui.plugin.add("draggable", "snap", {
+	start: function(e, ui) {
+		
+		var inst = $(this).data("draggable");
+		inst.snapElements = [];
+		$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() {
+			var $t = $(this); var $o = $t.offset();
+			if(this != inst.element[0]) inst.snapElements.push({
+				item: this,
+				width: $t.outerWidth(), height: $t.outerHeight(),
+				top: $o.top, left: $o.left
+			});
+		});
+		
+	},
+	drag: function(e, ui) {
+		
+		var inst = $(this).data("draggable");
+		var d = ui.options.snapTolerance || 20;
+		var x1 = ui.absolutePosition.left, x2 = x1 + inst.helperProportions.width,
+			y1 = ui.absolutePosition.top, y2 = y1 + inst.helperProportions.height;
+		
+		for (var i = inst.snapElements.length - 1; i >= 0; i--){
+			
+			var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, 
+				t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
+			
+			//Yes, I know, this is insane ;)
+			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue;
+			
+			if(ui.options.snapMode != 'inner') {
+				var ts = Math.abs(t - y2) <= 20;
+				var bs = Math.abs(b - y1) <= 20;
+				var ls = Math.abs(l - x2) <= 20;
+				var rs = Math.abs(r - x1) <= 20;
+				if(ts) ui.position.top = inst.convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
+				if(bs) ui.position.top = inst.convertPositionTo("relative", { top: b, left: 0 }).top;
+				if(ls) ui.position.left = inst.convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
+				if(rs) ui.position.left = inst.convertPositionTo("relative", { top: 0, left: r }).left;
+			}
+			
+			if(ui.options.snapMode != 'outer') {
+				var ts = Math.abs(t - y1) <= 20;
+				var bs = Math.abs(b - y2) <= 20;
+				var ls = Math.abs(l - x1) <= 20;
+				var rs = Math.abs(r - x2) <= 20;
+				if(ts) ui.position.top = inst.convertPositionTo("relative", { top: t, left: 0 }).top;
+				if(bs) ui.position.top = inst.convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
+				if(ls) ui.position.left = inst.convertPositionTo("relative", { top: 0, left: l }).left;
+				if(rs) ui.position.left = inst.convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
+			}
+			
+		};
+	}
+});
+
+$.ui.plugin.add("draggable", "connectToSortable", {
+	start: function(e,ui) {
+	
+		var inst = $(this).data("draggable");
+		inst.sortables = [];
+		$(ui.options.connectToSortable).each(function() {
+			if($.data(this, 'sortable')) {
+				var sortable = $.data(this, 'sortable');
+				inst.sortables.push({
+					instance: sortable,
+					shouldRevert: sortable.options.revert
+				});
+				sortable.refreshItems();	//Do a one-time refresh at start to refresh the containerCache	
+				sortable.propagate("activate", e, inst);
+			}
+		});
+
+	},
+	stop: function(e,ui) {
+		
+		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+		var inst = $(this).data("draggable");
+		
+		$.each(inst.sortables, function() {
+			if(this.instance.isOver) {
+				this.instance.isOver = 0;
+				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+				if(this.shouldRevert) this.instance.options.revert = true; //revert here
+				this.instance.mouseStop(e);
+				
+				//Also propagate receive event, since the sortable is actually receiving a element
+				this.instance.element.triggerHandler("sortreceive", [e, $.extend(this.instance.ui(), { sender: inst.element })], this.instance.options["receive"]);
+
+				this.instance.options.helper = this.instance.options._helper;
+			} else {
+				this.instance.propagate("deactivate", e, inst);
+			}
+
+		});
+		
+	},
+	drag: function(e,ui) {
+
+		var inst = $(this).data("draggable"), self = this;
+		
+		var checkPos = function(o) {
+				
+			var l = o.left, r = l + o.width,
+				t = o.top, b = t + o.height;
+
+			return (l < (this.positionAbs.left + this.offset.click.left) && (this.positionAbs.left + this.offset.click.left) < r
+					&& t < (this.positionAbs.top + this.offset.click.top) && (this.positionAbs.top + this.offset.click.top) < b);				
+		};
+		
+		$.each(inst.sortables, function(i) {
+
+			if(checkPos.call(inst, this.instance.containerCache)) {
+
+				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+				if(!this.instance.isOver) {
+					this.instance.isOver = 1;
+
+					//Now we fake the start of dragging for the sortable instance,
+					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+					this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
+					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
+					this.instance.options.helper = function() { return ui.helper[0]; };
+				
+					e.target = this.instance.currentItem[0];
+					this.instance.mouseCapture(e, true);
+					this.instance.mouseStart(e, true, true);
+
+					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+					this.instance.offset.click.top = inst.offset.click.top;
+					this.instance.offset.click.left = inst.offset.click.left;
+					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
+					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
+					
+					inst.propagate("toSortable", e);
+				
+				}
+				
+				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+				if(this.instance.currentItem) this.instance.mouseDrag(e);
+				
+			} else {
+				
+				//If it doesn't intersect with the sortable, and it intersected before,
+				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+				if(this.instance.isOver) {
+					this.instance.isOver = 0;
+					this.instance.cancelHelperRemoval = true;
+					this.instance.options.revert = false; //No revert here
+					this.instance.mouseStop(e, true);
+					this.instance.options.helper = this.instance.options._helper;
+					
+					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+					this.instance.currentItem.remove();
+					if(this.instance.placeholder) this.instance.placeholder.remove();
+					
+					inst.propagate("fromSortable", e);
+				}
+				
+			};
+
+		});
+
+	}
+});
+
+$.ui.plugin.add("draggable", "stack", {
+	start: function(e,ui) {
+		var group = $.makeArray($(ui.options.stack.group)).sort(function(a,b) {
+			return (parseInt($(a).css("zIndex"),10) || ui.options.stack.min) - (parseInt($(b).css("zIndex"),10) || ui.options.stack.min);
+		});
+		
+		$(group).each(function(i) {
+			this.style.zIndex = ui.options.stack.min + i;
+		});
+		
+		this[0].style.zIndex = ui.options.stack.min + group.length;
+	}
+});
+
+})(jQuery);
+/*
+ * jQuery UI Droppable
+ *
+ * Copyright (c) 2008 Paul Bakaus
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ * 
+ * http://docs.jquery.com/UI/Droppables
+ *
+ * Depends:
+ *	ui.core.js
+ *	ui.draggable.js
+ */
+(function($) {
+
+$.widget("ui.droppable", {
+	init: function() {
+
+		this.element.addClass("ui-droppable");
+		this.isover = 0; this.isout = 1;
+		
+		//Prepare the passed options
+		var o = this.options, accept = o.accept;
+		o = $.extend(o, {
+			accept: o.accept && o.accept.constructor == Function ? o.accept : function(d) {
+				return $(d).is(accept);
+			}
+		});
+		
+		//Store the droppable's proportions
+		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
+		
+		// Add the reference and positions to the manager
+		$.ui.ddmanager.droppables.push(this);
+		
+	},
+	plugins: {},
+	ui: function(c) {
+		return {
+			draggable: (c.currentItem || c.element),
+			helper: c.helper,
+			position: c.position,
+			absolutePosition: c.positionAbs,
+			options: this.options,
+			element: this.element
+		};
+	},
+	destroy: function() {
+		var drop = $.ui.ddmanager.droppables;
+		for ( var i = 0; i < drop.length; i++ )
+			if ( drop[i] == this )
+				drop.splice(i, 1);
+		
+		this.element
+			.removeClass("ui-droppable ui-droppable-disabled")
+			.removeData("droppable")
+			.unbind(".droppable");
+	},
+	over: function(e) {
+		
+		var draggable = $.ui.ddmanager.current;
+		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+		
+		if (this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {
+			$.ui.plugin.call(this, 'over', [e, this.ui(draggable)]);
+			this.element.triggerHandler("dropover", [e, this.ui(draggable)], this.options.over);
+		}
+		
+	},
+	out: function(e) {
+		
+		var draggable = $.ui.ddmanager.current;
+		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+		
+		if (this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {
+			$.ui.plugin.call(this, 'out', [e, this.ui(draggable)]);
+			this.element.triggerHandler("dropout", [e, this.ui(draggable)], this.options.out);
+		}
+		
+	},
+	drop: function(e,custom) {
+		
+		var draggable = custom || $.ui.ddmanager.current;
+		if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
+		
+		var childrenIntersection = false;
+		this.element.find(".ui-droppable").not(".ui-draggable-dragging").each(function() {
+			var inst = $.data(this, 'droppable');
+			if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
+				childrenIntersection = true; return false;
+			}
+		});
+		if(childrenIntersection) return false;
+		
+		if(this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {
+			$.ui.plugin.call(this, 'drop', [e, this.ui(draggable)]);
+			this.element.triggerHandler("drop", [e, this.ui(draggable)], this.options.drop);
+			return true;
+		}
+		
+		return false;
+		
+	},
+	activate: function(e) {
+		
+		var draggable = $.ui.ddmanager.current;
+		$.ui.plugin.call(this, 'activate', [e, this.ui(draggable)]);
+		if(draggable) this.element.triggerHandler("dropactivate", [e, this.ui(draggable)], this.options.activate);
+		
+	},
+	deactivate: function(e) {
+		
+		var draggable = $.ui.ddmanager.current;
+		$.ui.plugin.call(this, 'deactivate', [e, this.ui(draggable)]);
+		if(draggable) this.element.triggerHandler("dropdeactivate", [e, this.ui(draggable)], this.options.deactivate);
+		
+	}
+});
+
+$.extend($.ui.droppable, {
+	defaults: {
+		disabled: false,
+		tolerance: 'intersect'
+	}
+});
+
+$.ui.intersect = function(draggable, droppable, toleranceMode) {
+	
+	if (!droppable.offset) return false;
+	
+	var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
+		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
+	var l = droppable.offset.left, r = l + droppable.proportions.width,
+		t = droppable.offset.top, b = t + droppable.proportions.height;
+	
+	switch (toleranceMode) {
+		case 'fit':
+			return (l < x1 && x2 < r
+				&& t < y1 && y2 < b);
+			break;
+		case 'intersect':
+			return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
+				&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
+				&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
+				&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
+			break;
+		case 'pointer':
+			return (l < ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left) && ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left) < r
+				&& t < ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top) && ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top) < b);
+			break;
+		case 'touch':
+			return (
+					(y1 >= t && y1 <= b) ||	// Top edge touching
+					(y2 >= t && y2 <= b) ||	// Bottom edge touching
+					(y1 < t && y2 > b)		// Surrounded vertically
+				) && (
+					(x1 >= l && x1 <= r) ||	// Left edge touching
+					(x2 >= l && x2 <= r) ||	// Right edge touching
+					(x1 < l && x2 > r)		// Surrounded horizontally
+				);
+			break;
+		default:
+			return false;
+			break;
+		}
+	
+};
+
+/*
+	This manager tracks offsets of draggables and droppables
+*/
+$.ui.ddmanager = {
+	current: null,
+	droppables: [],
+	prepareOffsets: function(t, e) {
+		
+		var m = $.ui.ddmanager.droppables;
+		var type = e ? e.type : null; // workaround for #2317
+
+		for (var i = 0; i < m.length; i++) {
+			if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element,(t.currentItem || t.element)))) continue;
+			m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
+			m[i].offset = m[i].element.offset();
+			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
+			
+			if(type == "dragstart" || type == "sortactivate") m[i].activate.call(m[i], e); //Activate the droppable if used directly from draggables
+		}
+		
+	},
+	drop: function(draggable, e) {
+		
+		var dropped = false;
+		$.each($.ui.ddmanager.droppables, function() {
+			
+			if(!this.options) return;
+			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
+				dropped = this.drop.call(this, e);
+			
+			if (!this.options.disabled && this.visible && this.options.accept.call(this.element,(draggable.currentItem || draggable.element))) {
+				this.isout = 1; this.isover = 0;
+				this.deactivate.call(this, e);
+			}
+			
+		});
+		return dropped;
+		
+	},
+	drag: function(draggable, e) {
+		
+		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
+		if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, e);
+		
+		//Run through all droppables and check their positions based on specific tolerance options
+
+		$.each($.ui.ddmanager.droppables, function() {
+			
+			if(this.options.disabled || this.greedyChild || !this.visible) return;
+			var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
+			
+			var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
+			if(!c) return;
+			
+			var parentInstance;
+			if (this.options.greedy) {
+				var parent = this.element.parents('.ui-droppable:eq(0)');
+				if (parent.length) {
+					parentInstance = $.data(parent[0], 'droppable');
+					parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
+				}
+			}
+			
+			// we just moved into a greedy child
+			if (parentInstance && c == 'isover') {
+				parentInstance['isover'] = 0;
+				parentInstance['isout'] = 1;
+				parentInstance.out.call(parentInstance, e);
+			}
+			
+			this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
+			this[c == "isover" ? "over" : "out"].call(this, e);
+			
+			// we just moved out of a greedy child
+			if (parentInstance && c == 'isout') {
+				parentInstance['isout'] = 0;
+				parentInstance['isover'] = 1;
+				parentInstance.over.call(parentInstance, e);
+			}
+		});
+		
+	}
+};
+
+/*
+ * Droppable Extensions
+ */
+
+$.ui.plugin.add("droppable", "activeClass", {
+	activate: function(e, ui) {
+		$(this).addClass(ui.options.activeClass);
+	},
+	deactivate: function(e, ui) {
+		$(this).removeClass(ui.options.activeClass);
+	},
+	drop: function(e, ui) {
+		$(this).removeClass(ui.options.activeClass);
+	}
+});
+
+$.ui.plugin.add("droppable", "hoverClass", {
+	over: function(e, ui) {
+		$(this).addClass(ui.options.hoverClass);
+	},
+	out: function(e, ui) {
+		$(this).removeClass(ui.options.hoverClass);
+	},
+	drop: function(e, ui) {
+		$(this).removeClass(ui.options.hoverClass);
+	}
+});
+
+})(jQuery);

Added: branches/print_dev/http/extensions/jquery.contextmenu.r2.js
===================================================================
--- branches/print_dev/http/extensions/jquery.contextmenu.r2.js	                        (rev 0)
+++ branches/print_dev/http/extensions/jquery.contextmenu.r2.js	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,144 @@
+/*
+ * ContextMenu - jQuery plugin for right-click context menus
+ *
+ * Author: Chris Domigan
+ * Contributors: Dan G. Switzer, II
+ * Parts of this plugin are inspired by Joern Zaefferer's Tooltip plugin
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Version: r2
+ * Date: 16 July 2007
+ *
+ * For documentation visit http://www.trendskitchens.co.nz/jquery/contextmenu/
+ *
+ */
+
+(function($) {
+
+ 	var menu, shadow, trigger, content, hash, currentTarget;
+  var defaults = {
+    menuStyle: {
+      listStyle: 'none',
+      padding: '1px',
+      margin: '0px',
+      backgroundColor: '#fff',
+      border: '1px solid #999',
+      width: '100px'
+    },
+    itemStyle: {
+      margin: '0px',
+      color: '#000',
+      display: 'block',
+      cursor: 'default',
+      padding: '3px',
+      border: '1px solid #fff',
+      backgroundColor: 'transparent'
+    },
+    itemHoverStyle: {
+      border: '1px solid #0a246a',
+      backgroundColor: '#b6bdd2'
+    },
+    eventPosX: 'pageX',
+    eventPosY: 'pageY',
+    shadow : true,
+    onContextMenu: null,
+    onShowMenu: null
+ 	};
+
+  $.fn.contextMenu = function(id, options) {
+    if (!menu) {                                      // Create singleton menu
+      menu = $('<div id="jqContextMenu"></div>')
+               .hide()
+               .css({position:'absolute', zIndex:'500'})
+               .appendTo('body')
+               .bind('click', function(e) {
+                 e.stopPropagation();
+               });
+    }
+    if (!shadow) {
+      shadow = $('<div></div>')
+                 .css({backgroundColor:'#000',position:'absolute',opacity:0.2,zIndex:499})
+                 .appendTo('body')
+                 .hide();
+    }
+    hash = hash || [];
+    hash.push({
+      id : id,
+      menuStyle: $.extend({}, defaults.menuStyle, options.menuStyle || {}),
+      itemStyle: $.extend({}, defaults.itemStyle, options.itemStyle || {}),
+      itemHoverStyle: $.extend({}, defaults.itemHoverStyle, options.itemHoverStyle || {}),
+      bindings: options.bindings || {},
+      shadow: options.shadow || options.shadow === false ? options.shadow : defaults.shadow,
+      onContextMenu: options.onContextMenu || defaults.onContextMenu,
+      onShowMenu: options.onShowMenu || defaults.onShowMenu,
+      eventPosX: options.eventPosX || defaults.eventPosX,
+      eventPosY: options.eventPosY || defaults.eventPosY
+    });
+
+    var index = hash.length - 1;
+    $(this).bind('contextmenu', function(e) {
+      // Check if onContextMenu() defined
+      var bShowContext = (!!hash[index].onContextMenu) ? hash[index].onContextMenu(e) : true;
+      if (bShowContext) display(index, this, e, options);
+      return false;
+    });
+    return this;
+  };
+
+  function display(index, trigger, e, options) {
+    var cur = hash[index];
+    content = $('#'+cur.id).find('ul:first').clone(true);
+    content.css(cur.menuStyle).find('li').css(cur.itemStyle).hover(
+      function() {
+        $(this).css(cur.itemHoverStyle);
+      },
+      function(){
+        $(this).css(cur.itemStyle);
+      }
+    ).find('img').css({verticalAlign:'middle',paddingRight:'2px'});
+
+    // Send the content to the menu
+    menu.html(content);
+
+    // if there's an onShowMenu, run it now -- must run after content has been added
+		// if you try to alter the content variable before the menu.html(), IE6 has issues
+		// updating the content
+    if (!!cur.onShowMenu) menu = cur.onShowMenu(e, menu);
+
+    $.each(cur.bindings, function(id, func) {
+      $('#'+id, menu).bind('click', function(e) {
+        hide();
+        func(trigger, currentTarget);
+      });
+    });
+
+    menu.css({'left':e[cur.eventPosX],'top':e[cur.eventPosY]}).show();
+    if (cur.shadow) shadow.css({width:menu.width(),height:menu.height(),left:e.pageX+2,top:e.pageY+2}).show();
+    $(document).one('click', hide);
+  }
+
+  function hide() {
+    menu.hide();
+    shadow.hide();
+  }
+
+  // Apply defaults
+  $.contextMenu = {
+    defaults : function(userDefaults) {
+      $.each(userDefaults, function(i, val) {
+        if (typeof val == 'object' && defaults[i]) {
+          $.extend(defaults[i], val);
+        }
+        else defaults[i] = val;
+      });
+    }
+  };
+
+})(jQuery);
+
+$(function() {
+  $('div.contextMenu').hide();
+});
\ No newline at end of file

Added: branches/print_dev/http/img/OSGeo_logo.png
===================================================================
(Binary files differ)


Property changes on: branches/print_dev/http/img/OSGeo_logo.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/print_dev/http/img/button_digitize/geomClone.png
===================================================================
(Binary files differ)


Property changes on: branches/print_dev/http/img/button_digitize/geomClone.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/print_dev/http/javascripts/mod_addWmsFromFilteredList_button.php
===================================================================
--- branches/print_dev/http/javascripts/mod_addWmsFromFilteredList_button.php	                        (rev 0)
+++ branches/print_dev/http/javascripts/mod_addWmsFromFilteredList_button.php	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,80 @@
+<?php
+# $Id: mod_addWmsFromFilteredList_button.php 3873 2009-04-14 10:36:20Z astrid_emde $
+# http://www.mapbender.org/Add_WMS_from_filtered_list_%28AJAX%29
+# Copyright (C) 2002 CCGIS 
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+require_once(dirname(__FILE__)."/../php/mb_validatePermission.php");
+
+echo "var addWmsFromFilteredListId = '" . $e_id . "';";
+?>
+var addWmsFromFilteredList_title;
+var addWmsFromFilteredListPopup;
+
+eventInit.register(function () {
+	var $addWmsFromFilteredListButton = $("#" + addWmsFromFilteredListId);
+	addWmsFromFilteredList_title = $addWmsFromFilteredListButton.get(0).title;
+	$addWmsFromFilteredListButton.click(function () {
+		var $addWmsFromFilteredListButton = $("#" + addWmsFromFilteredListId);
+		addWmsFromFilteredList_title = $addWmsFromFilteredListButton.get(0).title;
+		addWmsFromFilteredList_showPopup();
+	});
+});
+
+var addWmsFromFilteredList_showPopup = function () {
+	addWmsFromFilteredListPopup = new mb_popup({
+		title:addWmsFromFilteredList_title,
+		url:"../javascripts/mod_addWMSfromfilteredList_ajax.php?<?php 
+		
+	echo session_name() . '=' . session_id() . '&';
+	echo "guiID=" . $gui_id . '&';
+	echo "elementID=" . $e_id;
+	
+		?>",
+		width:720, 
+		height:600,
+		left:300, 
+		top:100
+	});
+	addWmsFromFilteredListPopup.show()
+};
+
+eventLocalize.register(function () {
+	addWmsFromFilteredListPopup.destroy();
+});
+
+eventInit.register(function () {
+	mod_addWmsFromFilteredList_init();
+});
+
+var mod_addWmsFromFilteredList_img = new Image(); 
+mod_addWmsFromFilteredList_img.src = "<?php  echo $e_src;  ?>";
+var mod_addWmsFromFilteredList_img_over = new Image(); 
+mod_addWmsFromFilteredList_img_over.src = "<?php  echo preg_replace("/_off/","_over",$e_src);  ?>";
+
+function mod_addWmsFromFilteredList_init() {
+	var obj = document.getElementById(addWmsFromFilteredListId);
+	obj.src = mod_addWmsFromFilteredList_img.src;
+	obj.onmouseover = new Function("mod_addWmsFromFilteredList_over()");
+	obj.onmouseout = new Function("mod_addWmsFromFilteredList_out()");
+}
+function mod_addWmsFromFilteredList_over(){
+	document.getElementById(addWmsFromFilteredListId).src = mod_addWmsFromFilteredList_img_over.src;
+}
+
+function mod_addWmsFromFilteredList_out(){
+	document.getElementById(addWmsFromFilteredListId).src = mod_addWmsFromFilteredList_img.src;
+}
\ No newline at end of file

Added: branches/print_dev/http/php/mod_customTree.php
===================================================================
--- branches/print_dev/http/php/mod_customTree.php	                        (rev 0)
+++ branches/print_dev/http/php/mod_customTree.php	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,318 @@
+<?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__) . "/../../lib/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 saveTreeOnUnloadOrChange = function (myTree) {
+				if (myTree.hasChanged) {
+					var saveChanges = confirm("You have changed the tree. All changes will be lost. Save changes?");
+
+					if (saveChanges) {
+						Save.updateDatabase(function () {
+						});
+					}
+
+				}
+			};
+
+			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);
+						}
+					}
+
+					myTree.hasChanged = false;
+					
+					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 () {
+						saveTreeOnUnloadOrChange(myTree);
+						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) {
+					if (!applicationId || applicationId == "...") {
+						callback();
+						return;
+					}
+
+					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);
+						myTree.hasChanged = false;
+						callback();
+					});
+				}
+			};
+
+			var Restart = {
+				buttonParameters : {
+					on:"../img/button_blink_red/exit_on.png",
+					over:"../img/button_blink_red/exit_over.png",
+					off:"../img/button_blink_red/exit_off.png",
+					type:"singular"
+				},
+				removeAllFolders: function(){
+					if (!applicationId || applicationId == "...") {
+						return;
+					}
+					
+					var confirmDelete = confirm("You are about to delete your customized folder structure. Proceed?");
+
+					if (confirmDelete) {
+						var queryObj = {
+							"command": "delete",
+							"parameters": {
+								"applicationId": applicationId
+							}
+						};
+						
+						$.post("../php/mod_customTree_server.php", {
+							queryObj: $.toJSON(queryObj)
+						}, function(json, status){
+							myTree = new CustomTree();
+							var root = myTree.root;
+							root.name = "(" + applicationId + ")";
+							
+							addMissingWmsToCustomTree(myTree, applicationId);
+						});
+						
+					}
+				}
+			}
+						
+			$(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);	
+				});
+
+				// restart tool
+				var restartButton = new Button(Restart.buttonParameters);
+				toolbox.add(restartButton);
+				
+				restartButton.registerPush(function () {
+					Restart.removeAllFolders();
+				});
+
+				// dialogue: save changes on unload
+				$(window).unload(function () {
+					saveTreeOnUnloadOrChange(myTree);
+				})
+			});
+			
+		</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/print_dev/http/php/mod_customTree_server.php
===================================================================
--- branches/print_dev/http/php/mod_customTree_server.php	                        (rev 0)
+++ branches/print_dev/http/php/mod_customTree_server.php	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,186 @@
+<?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 'delete': 
+		$applicationId = $queryObj->parameters->applicationId;
+
+		// get all of the users applications
+		$allowedApplicationArray = $user->getApplicationsByPermission(0);
+
+		if (in_array($applicationId, $allowedApplicationArray)) {
+			$sql = "DELETE FROM gui_treegde WHERE fkey_gui_id = $1";
+			$v = array($applicationId);
+			$t = array("s");
+			$res = db_prep_query($sql, $v, $t);
+			$resultObj["success"] = "Deletion successful. " . $sql . " (" . $applicationId . ")";
+		}
+		else {
+			$resultObj["error"] = "Access denied to application " . $applicationId . ".";
+		}
+				
+		break;
+	case 'getApplications':
+		// get all of the users applications
+		$allowedApplicationArray = $user->getApplicationsByPermission(0);
+
+		// 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(0);
+
+		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(0);
+
+		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) {
+					if (is_numeric($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

Added: branches/print_dev/lib/customTreeController.js
===================================================================
--- branches/print_dev/lib/customTreeController.js	                        (rev 0)
+++ branches/print_dev/lib/customTreeController.js	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,279 @@
+var customTreeController = function (myTree, options) {
+//	this.myTree = new CustomTree();
+//	this.myTree.root.name = "My tree";
+
+	var currentlyDraggedNode;
+
+	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 () {
+			that.myTree.hasChanged = true;
+		};
+	};
+	
+	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 () {
+			that.myTree.hasChanged = true;
+		};
+	};
+
+
+	var deleteNode = function (treeNode) {
+		if (treeNode.containsNonFolder()) {
+			alert("This folder contains a WMS. It may not be deleted. Move the WMS before deleting the folder.");
+		}
+		else {
+			treeNode.remove();
+		}
+	};
+
+	var editNode = function ($domNode, treeNode) {
+		var newName = prompt('Name:', treeNode.name);
+		if (newName) {
+			treeNode.setName(newName);
+		}	
+	};
+	
+	var addNode = function ($domNode, treeNode) {
+		var newName = prompt('Name:');
+		if (newName) {
+			var newChild = treeNode.addChild();
+			newChild.setName(newName);
+		}
+	};
+
+	//
+	// 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

Added: branches/print_dev/lib/customTreeModel.js
===================================================================
--- branches/print_dev/lib/customTreeModel.js	                        (rev 0)
+++ branches/print_dev/lib/customTreeModel.js	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,407 @@
+/**
+ * @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.hasChanged = false;
+	
+	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);
+			newNode.isFolder = true;
+			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;	
+	};
+
+	this.containsNonFolder = function () {
+		var foundNonFolder = false;
+		for (var i = 0;  i < this.childNodeList.count(); i++) {
+			var child = this.childNodeList.get(i);
+			if (!child.isFolder) {
+				return true;
+			}
+			else {
+				foundNonFolder = foundNonFolder || child.containsNonFolder();
+			}
+		}
+		return foundNonFolder;	
+	};
+};
\ No newline at end of file

Added: branches/print_dev/resources/db/update/update_2.7.sql
===================================================================
--- branches/print_dev/resources/db/update/update_2.7.sql	                        (rev 0)
+++ branches/print_dev/resources/db/update/update_2.7.sql	2009-05-22 12:10:55 UTC (rev 3957)
@@ -0,0 +1,63 @@
+-- remove event handlers, are now in the script
+UPDATE gui_element SET e_attributes = '' WHERE e_id = 'selArea1';
+UPDATE gui_element SET e_attributes = '' WHERE e_id = 'pan1';
+UPDATE gui_element SET e_attributes = '' WHERE e_id = 'featureInfo1';
+UPDATE gui_element SET e_content = '' WHERE e_id = 'navFrame';
+
+
+-- 
+-- new definition of addWMSfromfilteredList_ajax due to i18n
+UPDATE gui_element set e_attributes = '', e_js_file = 'mod_addWmsFromFilteredList_button.php' where e_id = 'addWMSfromfilteredList_ajax';
+
+
+-- 
+-- polish entries for translations table
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Pan', 'Przesuń');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Display complete map', 'Pokaż calą mapę');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Zoom in', 'Powiększ');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Zoom out', 'Pomniejsz');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Back', 'Wróć');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Forward', 'Do przodu');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Coordinates', 'Współrzędne');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Zoom by rectangle', 'Wybierz fragment mapy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Redraw', 'Załaduj ponownie');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Query', 'Szukaj danych');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Logout', 'Wymelduj');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'WMS preferences', 'Ustawienia WMS');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Adding WMS from filtered list', 'Dodaj WMS z listy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Set map center', 'Zaznacz środek mapy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Help', 'Pomoc');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Show WMS infos', 'Informacje WMS');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Save workspace as web map context document', 'Zapisz widok jako web map context dokument');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Resize Mapsize', 'Zmień rozmiar mapy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Rubber', 'Usuń szkic');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Get Area', 'Oblicz powierzchnię');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Close Polygon', 'Zamknij poligon');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Move back to your GUI list', 'Z powrotem do listy GUI');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Legend', 'Legenda');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Print', 'Drukuj');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Imprint', 'Imprint');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Maps', 'Mapy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Search', 'Szukaj');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Meetingpoint', 'Miejsce spotkań');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Metadatasearch', 'Wyszukiwanie metadanych');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Adding WMS', 'Dodaj WMS');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Adding WMS from List', 'Dodaj WMS z listy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Info', 'Informacja');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Change Projection', 'Zmień układ współrzędnych');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Copyright', 'Copyright');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Digitize', 'Dygitalizacja');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Overview', 'Mapa przeglądowa');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Drag Mapsize', 'Powiększ');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Mapframe', 'Okno mapy');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Navigation Frame', 'Pasek narzędzi');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Scale Select', 'Wybierz skalę');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Scale Text', 'Wpisz skalę');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Scalebar', 'Podziałka');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Set Background', 'Wybierz mapę tematyczną jako tło');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Zoom to Coordinates', 'Powiększ według współrzędnych');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Change Password', 'Zmień hasło');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Load a web map context document', 'Załaduj web map context dokument');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Logo', 'Logo');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Measure distance', 'Zmierz odległość');
+INSERT INTO translations (locale, msgid, msgstr ) VALUES ('pl', 'Set language', 'Wybierz język');
\ No newline at end of file



More information about the Mapbender_commits mailing list