[Mapbender-commits] r3711 - in trunk/mapbender: http/extensions
http/html http/php lib resources/db/update
svn_mapbender at osgeo.org
svn_mapbender at osgeo.org
Fri Mar 13 12:26:06 EDT 2009
Author: christoph
Date: 2009-03-13 12:26:06 -0400 (Fri, 13 Mar 2009)
New Revision: 3711
Added:
trunk/mapbender/http/extensions/jquery-ui-personalized-1.5.2.js
trunk/mapbender/http/extensions/jquery.contextmenu.r2.js
trunk/mapbender/http/php/mod_customTree.php
trunk/mapbender/http/php/mod_customTree_server.php
trunk/mapbender/lib/customTreeController.js
trunk/mapbender/lib/customTreeModel.js
Modified:
trunk/mapbender/http/html/mod_treefolder2.php
trunk/mapbender/http/html/mod_treefolderPlain.php
trunk/mapbender/resources/db/update/update_2.6.sql
Log:
http://trac.osgeo.org/mapbender/ticket/389
Added: trunk/mapbender/http/extensions/jquery-ui-personalized-1.5.2.js
===================================================================
--- trunk/mapbender/http/extensions/jquery-ui-personalized-1.5.2.js (rev 0)
+++ trunk/mapbender/http/extensions/jquery-ui-personalized-1.5.2.js 2009-03-13 16:26:06 UTC (rev 3711)
@@ -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: trunk/mapbender/http/extensions/jquery.contextmenu.r2.js
===================================================================
--- trunk/mapbender/http/extensions/jquery.contextmenu.r2.js (rev 0)
+++ trunk/mapbender/http/extensions/jquery.contextmenu.r2.js 2009-03-13 16:26:06 UTC (rev 3711)
@@ -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
Modified: trunk/mapbender/http/html/mod_treefolder2.php
===================================================================
--- trunk/mapbender/http/html/mod_treefolder2.php 2009-03-13 15:41:23 UTC (rev 3710)
+++ trunk/mapbender/http/html/mod_treefolder2.php 2009-03-13 16:26:06 UTC (rev 3711)
@@ -75,13 +75,83 @@
var errors = 0;
var state=Array();
var treeState = "";
-var arrNodes =
-[
- ['root_id', ['Layer','javascript:_foo()']
+<?php
+//load structure
+$sql = "SELECT * FROM gui_treegde WHERE fkey_gui_id = $1 AND NOT lft = 1 ORDER BY lft;";
+$v = array($_SESSION["mb_user_gui"]);
+$t = array("s");
+$res = db_prep_query($sql, $v, $t);
+//init tree converting arrays
+$nr = array(); //array for nested sets numbers
+$str = array(); //array for js array elements
+$categories = array(); //array for wms folders
+$path = array(); //stack for actual path elements
+$rights = array(); //stack for rights of open elements
+
+//build javascript data array for jsTree
+while($row = db_fetch_array($res)){
+ //push javascript array elements to a single array with lefts and rights
+ $left = "['folder_".$row['id']."', ['".$row['my_layer_title']."', 'javascript:_foo()'],[";
+ $right = "]],";
+ array_push($nr, $row['lft']);
+ array_push($str, $left);
+ array_push($nr, $row['rgt']);
+ array_push($str, $right);
+
+ //finish all nodes that have no further childs
+ while(count($rights) > 0 && $rights[count($rights)-1]<$row['lft']){
+ array_pop($rights);
+ array_pop($path);
+ }
+
+ //set path for each wms that is referenced in this folder
+ array_push($rights, $row['rgt']);
+ array_push($path, "folder_".$row['id']);
+ if($row['wms_id']!=""){
+ foreach(explode(",",$row['wms_id']) as $wms){
+ array_push($categories, "'wms_".$wms."':\"root_id|".implode("|", $path)."\"");
+ }
+ }
+}
+//if we have a configured structure output it
+if(count($str)>0){
+ //order js array elements
+ array_multisort($nr, $str);
+
+ //output javascript vars
+ $arrNodesStr = "[['root_id', ['Layer','javascript:_foo()'],[".implode("",$str)."]]];";
+ $arrNodesStr = str_replace(array("[]", ",]"),array("","]"),$arrNodesStr);
+ echo "var arrNodesStr = \"".$arrNodesStr."\";\n";
+ echo "var categories = {".implode(",", $categories)."};\n";
+}
+else{
+//if there is no structure take default
+?>
+var arrNodesStr = "[['root_id', ['Layer','javascript:_foo()']]];";
+var categories = {};
+<?php
+}
+?>
+/*var arrNodesStr = "[['root_id', ['Layer','javascript:_foo()'], [['test1',['Einfach so','javascript:_foo()']],['test2',['Schönes Wetter','javascript:_foo()']],['test3',['Sonstiges','javascript:_foo()']]]]];"
+
+var categories = {"wms_407":arrNodes[0][0]+"|test1","wms_911":arrNodes[0][0]+"|test2", "wms_914":arrNodes[0][0]+"|test2"};
+var arrNodes = [
+ String: node id,
+ [
+ String: title,
+ String: href,
+ String: target,
+ String: image,
+ String: tooltip,
+ Folder definition: node context menu,
+ String: controls
+ ],
+ Folder definition: sub folder
]
-];
-function _foo(){}
+*/
+var arrNodes = eval(arrNodesStr);
+function _foo(){selectedMap=-1;selectedWMS=-1;selectedLayer=-1}
// some defaults
try{if (reverse){}}catch(e){reverse = 'false';}
@@ -153,21 +223,21 @@
var scale = parseInt(parent.mb_mapObj[selectedMap].getScale());
if(scale < parseInt(parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].gui_layer_minscale) && parseInt(parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].gui_layer_minscale) != 0){
if(selectedLayer==0)
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id, '#999999');
else
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].layer_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].layer_id, '#999999');
}
else if(scale > parseInt(parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].gui_layer_maxscale) && parseInt(parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].gui_layer_maxscale) != 0){
if(selectedLayer==0)
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id, '#999999');
else
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].layer_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].layer_id, '#999999');
}
else{
if(selectedLayer==0)
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id, '');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id, '');
else
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].layer_id, '');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[selectedMap].wms[selectedWMS].wms_id+"|"+parent.mb_mapObj[selectedMap].wms[selectedWMS].objLayer[selectedLayer].layer_id, '');
}
selectedMap=i;
@@ -184,26 +254,26 @@
for(var iii=1; iii<parent.mb_mapObj[i].wms[ii].objLayer.length; iii++){
if(scale < parseInt(parent.mb_mapObj[i].wms[ii].objLayer[iii].gui_layer_minscale) && parseInt(parent.mb_mapObj[i].wms[ii].objLayer[iii].gui_layer_minscale) != 0){
if(iii==0)
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id, '#999999');
else
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id, '#999999');
}
else if(scale > parseInt(parent.mb_mapObj[i].wms[ii].objLayer[iii].gui_layer_maxscale) && parseInt(parent.mb_mapObj[i].wms[ii].objLayer[iii].gui_layer_maxscale) != 0){
if(iii==0)
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id, '#999999');
else
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id, '#999999');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id, '#999999');
}
else{
if(iii==0)
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id, '');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id, '');
else
- setNodeColor(arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id, '');
+ setNodeColor(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id, '');
}
}
}
}
- }
+ }
}
function updateCheckState(){
@@ -215,7 +285,7 @@
for(var ii=0; ii<parent.mb_mapObj[i].wms.length; ii++){
for(var iii=1; iii<parent.mb_mapObj[i].wms[ii].objLayer.length; iii++){
if(!parent.mb_mapObj[i].wms[ii].objLayer[iii].has_childs){
- path = arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id;
+ path = arrNodes[0][0]+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id+"|"+parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_id;
checkNode(path, 0, parent.mb_mapObj[i].wms[ii].objLayer[iii].gui_layer_visible=='1', false);
if(ficheckbox == 'true')
checkNode(path, 1, parent.mb_mapObj[i].wms[ii].objLayer[iii].gui_layer_querylayer=='1', false);
@@ -250,7 +320,7 @@
selectedWMS=-1;
selectedLayer=-1;
init=false;
- arrNodes = [['root_id', ['Layer','javascript:_foo()']]];
+ arrNodes = eval(arrNodesStr)
initArray();
if(showstatus=='true'||alerterror=='true')
init_mapcheck();
@@ -277,7 +347,7 @@
state[wms]=-1;
errors++;
if(showstatus=='true')
- setNodeImage(arrNodes[0][0]+"|"+parent.mb_mapObj[map].wms[wms].wms_id, "error_folder.png");
+ setNodeImage(arrNodes[0][0]+"|wms_"+parent.mb_mapObj[map].wms[wms].wms_id, "error_folder.png");
}
function checkComplete(wms, map, img, first){
@@ -321,7 +391,7 @@
for(var wms=0;wms<parent.mb_mapObj[ind].wms.length;wms++){
var wmsimgid="map_"+wms;
if(parent.frames[mod_treeGDE_map].document.getElementById(wmsimgid)){
- checkComplete(wms, wmsimgid, arrNodes[0][0]+'|'+parent.mb_mapObj[ind].wms[wms].wms_id, true);
+ checkComplete(wms, wmsimgid, arrNodes[0][0]+'|wms_'+parent.mb_mapObj[ind].wms[wms].wms_id, true);
}
}
}
@@ -401,7 +471,7 @@
if(l!=0)
selectNode(String(lid));
else
- selectNode(String(parent.mb_mapObj[j].wms[k].wms_id));
+ selectNode("wms_"+String(parent.mb_mapObj[j].wms[k].wms_id));
}
}
}
@@ -433,7 +503,7 @@
if(l!=0)
selectNode(String(lid));
else
- selectNode(String(parent.mb_mapObj[j].wms[k].wms_id));
+ selectNode("wms_"+String(parent.mb_mapObj[j].wms[k].wms_id));
}
}
}
@@ -485,12 +555,14 @@
function handleSelectedWMS(path){
if(lock_update)return;
var t = path.split("|");
+ var wms_id = t[t.length-1].substr(4);
var reset_lock=!lock_check;
var ind = parent.getMapObjIndexByName(mod_treeGDE_map);
- var layername = parent.mb_mapObj[ind].wms[parent.getWMSIndexById(mod_treeGDE_map,t[t.length-1])].objLayer[0].layer_name;
+ var wms = parent.getWMSIndexById(mod_treeGDE_map,wms_id);
+ var layername = parent.mb_mapObj[ind].wms[wms].objLayer[0].layer_name;
var bChk = IsChecked(path, 0);
- handleSelectedLayer(mod_treeGDE_map,t[t.length-1],layername,"visible",bChk?"1":"0");
- handleSelectedLayer(mod_treeGDE_map,t[t.length-1],layername,"querylayer",bChk?"1":"0");
+ parent.mb_mapObj[ind].wms[wms].handleLayer(layername,"visible",bChk?"1":"0");
+ parent.mb_mapObj[ind].wms[wms].handleLayer(layername,"querylayer",bChk?"1":"0");
lock_check=true;
checkChildren(path, 0, bChk);
if(ficheckbox)checkChildren(path, 1, bChk);
@@ -498,8 +570,8 @@
setTimeout('setNodeImage("'+path+'", "error_folder.png");', 100);
if(reset_lock)
{
- parent.mb_restateLayers(mod_treeGDE_map,t[t.length-1]);
- parent.setSingleMapRequest(mod_treeGDE_map,t[t.length-1]);
+ parent.mb_restateLayers(mod_treeGDE_map,wms_id);
+ parent.setSingleMapRequest(mod_treeGDE_map,wms_id);
lock_check=false;
}
}
@@ -512,10 +584,14 @@
// enableCheckbox(path, 0, true);
checkChildren(path, box, bChk);
if(reset_lock){
+ //find wms id from path
var t = path.split("|");
- parent.mb_restateLayers(mod_treeGDE_map,t[1]);
+ for(var i=1;t[i].indexOf("wms_")!=0;i++){}
+ var wms_id = t[i].substr(4);
+ //set maprequest
+ parent.mb_restateLayers(mod_treeGDE_map,wms_id);
if(box==0)
- parent.setSingleMapRequest(mod_treeGDE_map,t[1]);
+ parent.setSingleMapRequest(mod_treeGDE_map,wms_id);
lock_check=false;
}
}
@@ -533,6 +609,12 @@
if(parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_parent == ""){
if(!temp.gui_layer_selectable == '1' && !temp.gui_layer_queryable == '1')
continue;
+ parentNode = arrNodes[0][0];
+ if(eval("categories.wms_"+parent.mb_mapObj[i].wms[ii].wms_id) !== undefined)
+ parentNode = eval("categories.wms_"+parent.mb_mapObj[i].wms[ii].wms_id);
+ else
+ eval("categories['wms_"+parent.mb_mapObj[i].wms[ii].wms_id+"'] = parentNode");
+
var c_menu="[";
if(reverse=="true"){
if(menu.indexOf("wms_down")!=-1 && ii!=parent.mb_mapObj[i].wms.length-1)c_menu+="menu_move_up,";
@@ -549,10 +631,10 @@
if(menu.indexOf("hide")!=-1)c_menu+="menu_hide";
c_menu+="]";
controls='';
- if(switchwms=='true')controls='<INPUT type="checkbox" title="' + msgObj.tooltipHandleWms + '" checked onclick="handleSelectedWMS(\''+arrNodes[0][0]+'|'+parent.mb_mapObj[i].wms[ii].wms_id+'\');" />';
+ if(switchwms=='true')controls='<INPUT type="checkbox" title="' + msgObj.tooltipHandleWms + '" checked onclick="handleSelectedWMS(\''+parentNode+'|wms_'+parent.mb_mapObj[i].wms[ii].wms_id+'\');" />';
if(wmsbuttons == 'true'&&metadatalink == 'true')controls+='<a href="'+'javascript:openwindow(\''+ defaultMetadataUrl + '&id='+temp.layer_uid+'\');'+'"><img src="'+imagedir+'/info.png" /></a>';
- addNode(arrNodes[0][0],[parent.mb_mapObj[i].wms[ii].wms_id,[temp.layer_title,((metadatalink=='true'&&wmsbuttons != 'true')?('javascript:openwindow(\"'+ defaultMetadataUrl + '&id='+temp.layer_uid+'\");'):"javascript:select("+i+","+ii+","+iii+");"),,,temp.layer_title,eval(c_menu),controls,[i,ii,iii]]],false,false,reverse=="true");
- parentObj = arrNodes[0][0]+"|"+parent.mb_mapObj[i].wms[ii].wms_id;
+ addNode(parentNode,["wms_"+parent.mb_mapObj[i].wms[ii].wms_id,[temp.layer_title,((metadatalink=='true'&&wmsbuttons != 'true')?('javascript:openwindow(\"'+ defaultMetadataUrl + '&id='+temp.layer_uid+'\");'):"javascript:select("+i+","+ii+","+iii+");"),,,temp.layer_title,eval(c_menu),controls,[i,ii,iii]]],false,false,reverse=="true");
+ parentObj = parentNode+"|wms_"+parent.mb_mapObj[i].wms[ii].wms_id;
}
if(parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_parent && (handlesublayer=="true"||parent.mb_mapObj[i].wms[ii].objLayer[iii].layer_parent=="0")){
var parentLayer = "";
@@ -583,7 +665,7 @@
// if(menu.indexOf("info_switch")!=-1)c_menu+="menu_info_switch,";
if(menu.indexOf("hide")!=-1)c_menu+="menu_hide";
c_menu+="]";
-
+
controls = [];
controls.push('<input type="checkbox" title="' + msgObj.tooltipLayerVisible + '" ');
if(temp.layer_name=="")
@@ -604,8 +686,8 @@
if(temp.gui_layer_queryable!='1')
controls.push('disabled ');
controls.push("onclick=\"handleSelectedLayer('"+mod_treeGDE_map+"','"+parent.mb_mapObj[i].wms[ii].wms_id+"','"+temp.layer_name+"','querylayer',this.checked?1:0);");
- controls.push("handleSelection('"+parentObj+parentLayer+"|"+temp.layer_id+"', 1);\" />");
- }
+ controls.push("handleSelection('"+parentObj+parentLayer+"|"+temp.layer_id+"', 1);\" />");
+ }
if(wmsbuttons == 'true'&&metadatalink == 'true'){
controls.push('<a href="javascript:openwindow(\''+ defaultMetadataUrl + '&id='+temp.layer_uid+'\');"><img src="'+imagedir+'/info.png" /></a>');
}
@@ -647,18 +729,18 @@
}
}
}
-//-->
+//-->
</SCRIPT>
</HEAD>
<BODY VLINK="#000000" ALINK="#000000" LINK="#000000" BGCOLOR="#ffffff" TEXT="#000000"
MARGINHEIGHT="0" MARGINWIDTH="0" LEFTMARGIN="0" TOPMARGIN="0">
<SCRIPT language="JavaScript" type="text/javascript">
if(wmsbuttons=='true'){
- document.writeln("<div>");
+ document.writeln("<div>");
document.writeln('<a href="javascript:move_up()"><img title="'+msgObj.tooltipMoveSelectionUp+'" src="'+imagedir+'/move_up.png" alt="move up" style="position:relative;top:0px;left:0px;"/></a>');
document.writeln('<a href="javascript:move_down()"><img title="'+msgObj.tooltipMoveSelectionDown+'" src="'+imagedir+'/move_down.png" alt="move down" style="position:relative;top:0px;left:-3px"/></a>');
document.writeln('<a href="javascript:remove_wms()"><img title="'+msgObj.tooltipRemoveWms+'" src="'+imagedir+'/delete_wms.png" alt="remove wms" style="position:relative;top:0px;left:-6px"/></a>');
- document.writeln("</div>");
+ document.writeln("</div>");
}
</SCRIPT>
<DIV id="treeContainer"></DIV>
Modified: trunk/mapbender/http/html/mod_treefolderPlain.php
===================================================================
--- trunk/mapbender/http/html/mod_treefolderPlain.php 2009-03-13 15:41:23 UTC (rev 3710)
+++ trunk/mapbender/http/html/mod_treefolderPlain.php 2009-03-13 16:26:06 UTC (rev 3711)
@@ -55,7 +55,7 @@
var treeState = "";
<?php
//load structure
-$sql = "SELECT * FROM gui_treegde WHERE fkey_gui_id = $1 ORDER BY lft;";
+$sql = "SELECT * FROM gui_treegde WHERE fkey_gui_id = $1 AND NOT lft = 1 ORDER BY lft;";
$v = array($_SESSION["mb_user_gui"]);
$t = array("s");
$res = db_prep_query($sql, $v, $t);
@@ -98,7 +98,9 @@
array_multisort($nr, $str);
//output javascript vars
- echo "var arrNodesStr = \"[['root_id', ['Layer','javascript:_foo()'],[".implode("",$str)."]]];\";\n";
+ $arrNodesStr = "[['root_id', ['Layer','javascript:_foo()'],[".implode("",$str)."]]];";
+ $arrNodesStr = str_replace(array("[]", ",]"),array("","]"),$arrNodesStr);
+ echo "var arrNodesStr = \"".$arrNodesStr."\";\n";
echo "var categories = {".implode(",", $categories)."};\n";
}
else{
Added: trunk/mapbender/http/php/mod_customTree.php
===================================================================
--- trunk/mapbender/http/php/mod_customTree.php (rev 0)
+++ trunk/mapbender/http/php/mod_customTree.php 2009-03-13 16:26:06 UTC (rev 3711)
@@ -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: trunk/mapbender/http/php/mod_customTree_server.php
===================================================================
--- trunk/mapbender/http/php/mod_customTree_server.php (rev 0)
+++ trunk/mapbender/http/php/mod_customTree_server.php 2009-03-13 16:26:06 UTC (rev 3711)
@@ -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: trunk/mapbender/lib/customTreeController.js
===================================================================
--- trunk/mapbender/lib/customTreeController.js (rev 0)
+++ trunk/mapbender/lib/customTreeController.js 2009-03-13 16:26:06 UTC (rev 3711)
@@ -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: trunk/mapbender/lib/customTreeModel.js
===================================================================
--- trunk/mapbender/lib/customTreeModel.js (rev 0)
+++ trunk/mapbender/lib/customTreeModel.js 2009-03-13 16:26:06 UTC (rev 3711)
@@ -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
Modified: trunk/mapbender/resources/db/update/update_2.6.sql
===================================================================
--- trunk/mapbender/resources/db/update/update_2.6.sql 2009-03-13 15:41:23 UTC (rev 3710)
+++ trunk/mapbender/resources/db/update/update_2.6.sql 2009-03-13 16:26:06 UTC (rev 3711)
@@ -498,3 +498,8 @@
Update gui_element_vars set var_value =
'de,en,bg,gr,nl,it,fr,es,pt'
where fkey_gui_id = 'gui' AND fkey_e_id = 'switchLocale_noreload';
+
+
+-- custimsable tree in admin1
+INSERT INTO gui_element(fkey_gui_id, e_id, e_pos, e_public, e_comment, e_title, e_element, e_src, e_attributes, e_left, e_top, e_width, e_height, e_z_index, e_more_styles, e_content, e_closetag, e_js_file, e_mb_mod, e_target, e_requires, e_url) VALUES('admin1','Customize Tree',0002,1,'Create a set of nested folders that contain the applications WMS','Customize Tree','a','','href = \\\"../php/mod_customTree.php?sessionID\\\" target=\\\"AdminFrame\\\"',10,975,250,20,NULL ,'font-family: Arial, Helvetica, sans-serif; font-size : 12px; text-decoration : none; color: #808080;','CUSTOMIZE TREE','a','','','','AdminFrame','');
+
More information about the Mapbender_commits
mailing list