/**
 ** SynFlag Menu: DHTML Menu
 ** Copyright: 2007-2009 SynFlag Online Agentur, Marcel Linnenfelser
 ** Author:    Marcel Linnenfelser
 ** License:   LGPL
 ** Version:   0.53b woif
 **
 ** Tested with: Internet Explorer 5, 5.5, 6, 7, Safari 3, Firefox 1.5, 2, Opera 9 
 **
 ** IE 5, 5.5 and 6: border-color transparent is emulated (useful for example if normal state shall 
 ** have no border, but over state shall) -> border.color, itemBorderOverColor
 ** IE std mode and compat mode in IE 6 and 7 is automatically handled (border box sizing) !! From other version => test it!!
 **
 ** 2009/04/06 Fix for IE 7 not displaying the menu until mouseovered: Call hideSubMenus at end of create in Menu.
 **/

if (typeof(synflag) == 'undefined')
    var synflag = {};

    var _d  = document;
    var _ud = 'undefined';
	
	synflag.n = function (id) {
		return _d.getElementById(id);
	}
	
	synflag.onLoadFuncArray = [];
	
	synflag.addOnLoad = function (func) {
	   synflag.onLoadFuncArray.push(func);
	}
	
	synflag.onLoad = function (event) {
    	for (var i = 0; i < synflag.onLoadFuncArray.length; i++) {
	       synflag.onLoadFuncArray[i]();
    	}
	}
	window.onload = synflag.onLoad;

    var _d  = document;
    var _ud = 'undefined';
	
	synflag.n = function (id) {
		return _d.getElementById(id);
	}
	
    synflag.browser = {};
    synflag.browser.initialized = false;
    synflag.browser.sniff = function () {
        var sb = synflag.browser;
        var ua = navigator.userAgent.toLowerCase();
    	if (sb.initialized)
    		return;
	    sb.initialized = true;
	    sb.webkit= false;
	    sb.ie50  = (ua.indexOf('msie 5.0')>-1);
	    sb.ie55  = (ua.indexOf('msie 5.5')>-1);
	    sb.ie5   = (sb.ie50 || sb.ie55)
	    sb.ie6   = (ua.indexOf('msie 6.0')>-1);
	    sb.ie7   = (ua.indexOf('msie 7.0')>-1);
		if (sb.ie5 || ((sb.ie6 || sb.ie7) && _d.compatMode == 'BackCompat'))
			sb.bb = sb.ieBorderBox = true;
		else
			sb.bb = sb.ieBorderBox = false;
	    sb.ie    = (sb.ie5 || sb.ie6 || sb.ie7)
		sb.gecko = (ua.indexOf('gecko')>-1);
		sb.windows = (ua.indexOf('windows')>-1);
		if ((ua.indexOf('mac os x')>-1)) {
			sb.windows = false;
			sb.macosx  = true;
		} else {
			sb.macosx  = false;
		}
		if ((ua.indexOf('applewebkit')>-1)) {
			sb.gecko  = false;
			sb.webkit = true;
		}
    }
    synflag.browser.sniff();
    
    synflag.browser.getViewport = function () {
		if (self.innerWidth) return { width: self.innerWidth, height: self.innerHeight };
		else if (_d.documentElement && _d.documentElement.clientWidth)
			return { width: _d.documentElement.clientWidth, height: _d.documentElement.clientHeight };
		else if (_d.body)	return { width: _d.body.clientWidth, height: _d.body.clientHeight };
		else return { width: 0, height: 0 };
	}

    synflag.browser.getScroll = function () {
		if (window.pageXOffset) return { x: window.pageXOffset, y: window.pageYOffset };
		else if (_d.documentElement && (_d.documentElement.scrollLeft || _d.documentElement.scrollTop))
			return { x: _d.documentElement.scrollLeft, y: _d.documentElement.scrollTop };
		else if (_d.body) return { x: _d.body.scrollLeft, y: _d.body.scrollTop };
		else return { x: 0, y: 0 };
	}

    synflag.widget = {};
    synflag.widget.MenuItem = function (url, text) {
    	
    	this.url  = url;
    	this.text = text;
		this.domNode = null;
    	this.subMenu = null;
    	this.top  = 0;
    	this.left = 0;
    	this.nextSibling = null;
    	this.prevSibling = null;
    	this.root = null;
		this.itemClass = null;
		this.itemOverClass = null;
		this.border  = {};
		this.padding = {};
		this.isSeparator = false;
		this.isSelected = false;
		this.icon = null;
		this.isInitialized = false;
		this.deferredFunctions = [];
    
        this.setIsSeparator = function (bool) {
            this.isSeparator = bool;
        }

        this.setParentMenu = function (parent) {
            this.parent = parent;
            if (parent.icon && parent.icon.image && (!this.icon || !this.icon.image)) {
                if (!this.icon)
                    this.icon = parent.icon;
                else {
                    if (!this.icon.image) {
                        this.icon.image = parent.icon.image;
                        if (!this.icon.overImage)
                            this.icon.overImage = parent.icon.overImage;
                    }
                }
            }
        }

        this.setSelected = function (selected) {
            this.isSelected = selected;
            var _this = this;
            this.deferre(function () {
	            _this.setOver(_this.isSelected);
            });
        }

        this.getFullItemHeight = function () {
        	return this.domNode.offsetHeight;
        }

        this.getPaddingBoxItemHeight = function () {
			var b = this.getBorder();
        	return this.domNode.offsetHeight - (synflag.browser.bb ? 0 : ((b.top ? b.top : 0) + (b.bottom ? b.bottom : 0)));
        }

        this.getContentBoxItemWidth = function () {
			var b = this.getBorder();
			var p = this.getPadding();
        	return this.domNode.offsetWidth - (synflag.browser.bb ? 0 : ((b.left ? b.left : 0) + (b.right ? b.right : 0)))
				 - (synflag.browser.bb ? 0 : ((p.left ? p.left : 0) + (p.right ? p.right : 0)));
        }

        this.getFullItemWidth = function () {
	       	return this.domNode.offsetWidth;
        }
        
        this.getCollapsedItemHeight = function () {
			var b = this.getBorder();
        	return this.getFullItemHeight() 
				- Math.min(b.top, b.bottom);
        }

        this.getCollapsedItemWidth = function () {
			var b = this.getBorder();
        	return this.getFullItemWidth() 
				- Math.min(b.left, b.right);
        }
        
		this.removeIeTransparentBorder = function () {
			var b = this.getBorder();
			var p = this.getPadding();
			var pu = this.parent.unit;
			this.domNode.style.borderWidth = b.top+pu+" "+b.right+pu+" "
            		+b.bottom+pu+" "+b.left+pu;
			this.domNode.style.padding = padding  = p.top+pu+" "+p.right+pu+" "
            		+p.bottom+pu+" "+p.left+pu;;
		}
        
		this.makeIeTransparentBorder = function () {
			var b = this.getBorder();
			var p = this.getPadding();
			var pu = this.parent.unit;
			this.domNode.style.padding = (b.top+p.top)+pu+" "+(b.right+p.right)+pu+" "
            		+(b.bottom+p.bottom)+pu+" "+(b.left+p.left)+pu;
			this.domNode.style.borderWidth = '0px';
		}
		
		this.overItem = function () {
			var _this = this;
			this.deferre(function () {
				_this._overItem();
			});
		}		
		
		this.unoverItem = function () {
			var _this = this;
			this.deferre(function () {
				_this._unoverItem();
			});
		}		
		
		this._overItem = function () {
			this.setOver(true);
		}

		this._unoverItem = function () {
			this.setOver(false);
		}
        
        this.setOver = function (bool) {
			this.isOver = bool;
			var pa = this.parent.arrow;
			var no = this.iconNode;
			var b  = this.getBorder();
			if ((bool || this.isSelected) && !this.isSeparator) {
				if (this.arrow && pa.overImage)
					this.arrow.src = pa.overImage;
				if (no && this.icon.overImage)
					no.src = this.icon.overImage;
				if (b.overColor)
					if ((synflag.browser.ie5 || synflag.browser.ie6) && b.overColor != b.color) {
						if (b.overColor == 'transparent') {
							this.makeIeTransparentBorder();
						} else if (b.color == 'transparent') {
							this.removeIeTransparentBorder();
						}
						this.domNode.style.borderColor = b.overColor;
					} else {
	      				this.domNode.style.borderColor = b.overColor;
					}
   	            this.domNode.className = ( this.itemOverClass == null ? this.parent.itemOverClass : this.itemOverClass );
			} else {
				if (this.arrow)
					this.arrow.src = pa.image;
				if (no)
					no.src = this.icon.image;
				if (b.color)
					if ((synflag.browser.ie5 || synflag.browser.ie6) && b.overColor != b.color) {
						if (b.color == 'transparent') {
							this.makeIeTransparentBorder();
						} else if (b.overColor == 'transparent') {
							this.removeIeTransparentBorder();
						}
						this.domNode.style.borderColor = b.color;
					} else {
   						this.domNode.style.borderColor = b.color;
					}
               this.domNode.className = ( this.itemClass == null     ? this.parent.itemClass     : this.itemClass );
			}
        }

        this.setRoot = function (root) {
            this.root = root;
        	if (this.subMenu != null) {
        		this.subMenu.setRoot(root);
        	}            
        }

        this.setNextSibling = function (next) {
            this.nextSibling = next;
        }

        this.setPrevSibling = function (prev) {
            this.prevSibling = prev;
        }
        
        this.getBorder = function () {
            var b  = this.border;
            var pb = this.parent.itemBorder;
            return { 
				top: 	(typeof b.top    != _ud?b.top:pb.top),
				right: 	(typeof b.right  != _ud?b.right:pb.right),
				bottom: (typeof b.bottom != _ud?b.bottom:pb.bottom),
				left: 	(typeof b.left   != _ud?b.left:pb.left),
				style: 	(typeof b.style  != _ud?b.style:pb.style),
				color:  (typeof b.color  != _ud?b.color:pb.color),
				overColor: (typeof this.itemBorderOverColor != _ud?this.itemBorderOverColor:this.parent.itemBorderOverColor)
			};
        }
        
        this.getPadding = function () {
            var p  = this.padding;
            var pp = this.parent.itemPadding;
            return { 
				top: 	(typeof p.top    != _ud?p.top:pp.top),
				right: 	(typeof p.right  != _ud?p.right:pp.right),
				bottom: (typeof p.bottom != _ud?p.bottom:pp.bottom),
				left: 	(typeof p.left   != _ud?p.left:pp.left)
			};
        }
        
        this.updatePosition = function () {
   			this.top = this.parent.padding.top;
   			this.left = this.parent.padding.left;
   			var ps = this.prevSibling;
   			var p  = this.parent;
        	if (p.orientation == 'vertical') {
        		if (ps != null) {
        			if (p.borderCollapse) {
        				this.top = ps.top + p.itemSpacing + ps.getCollapsedItemHeight();
        			} else {
        				this.top = ps.top + p.itemSpacing + ps.getFullItemHeight();
        			}
        		}
        	} else {
        		if (ps != null) {
        			if (p.borderCollapse) {
        				this.left = ps.left + p.itemSpacing + ps.getCollapsedItemWidth();
        			} else {
        				this.left = ps.left + p.itemSpacing + ps.getFullItemWidth();
        			}
        		}
        	}
            with (this.domNode.style) {
				position = "absolute";
            	top      = this.top+p.unit;
            	left     = this.left+p.unit;
			}
        }

        this.deferre = function (func) {
        	if (this.isInitialized) {
        		func();
        	} else {
        		this.deferredFunctions.push(func);
        	}
        }
        
        this.callDeferred = function () {
        	for (var i = 0; i < this.deferredFunctions.length; i++) {
        		this.deferredFunctions[i]();
        	}
        }

        this.create = function () {
			this.create_hlp();
          	this.callDeferred();
          	this.isInitialized = true;
			return;
			// why isn't that fuck working in FF?
/*			if (!this.icon || !this.icon.image) {
				this.create_hlp();
				return;
			}
			var img = new Image();
			var _this = this;
			img.onload = function () {
				_this.icon.width  = this.width;
				_this.icon.height = this.height;
				_this.create_hlp();
				alert(_this.domNode);
			}
			img.src = this.icon.image;*/
		}
		
        this.create_hlp = function () {
            this.domNode = _d.createElement("div");
            var dn = this.domNode;
            dn.domNode = _d.createElement("div");
			dn.appendChild(dn.domNode);
            var _this = this;
            dn.onmouseover = function (e) {
            	// handle only once
            	if (!_this.root.eventHandled && !_this.isOver) {
	            	window.clearTimeout(_this.root.timer);
            		_this.root.eventHandled = true;
    	        	_this.parent.hideChildrensSubMenus();
	            	_this.setOver(true);
    	        	var item = _this;
    	        	while (item.parent.parent != null) {
    	        		item = item.parent.parent;
    	        		item.setOver(true);
    	        	}
        	    	if (_this.subMenu != null) {
	        	    	_this.subMenu.setVisible(true);
					}
	        	}
            };
            dn.onmouseout = function (e) {
            	// delete here, all mouseout fired in a row before next mouse over
            	delete _this.root.eventHandled;
            };
	        dn.domNode.innerHTML = text;
			// to force keeping the width (multiline if to long)
	        dn.domNode.style.whiteSpace = 'normal';
			if (this.parent.width) {
				dn.domNode.style.width = this.parent.width+'px';
			}
			this.updatePosition();
            if (this.url != null && !this.isSeparator)
	            dn.onclick = function (e) {
    	        	window.location.href = _this.url;
        	    }
        	var pu = this.parent.unit;
        	var b  = this.getBorder();
        	var p  = this.getPadding();
            with (dn.style) {
            	if (this.parent.width > 0)
		           	width    = this.parent.width+pu;
            	if (this.parent.height > 0)
	            	height   = this.parent.height+pu;
            	borderWidth = b.top+pu+" "+b.right+pu+" "
            		+b.bottom+pu+" "+b.left+pu;
				if (b.style)
                	borderStyle = b.style;
				if (b.color)
                    borderColor = b.color;
            	padding  = p.top+pu+" "+p.right+pu+" "
            		+p.bottom+pu+" "+p.left+pu;
            	overflow = 'visible';
            	if (this.parent.orientation == 'horizontal') {
            		cssFloat = 'left';
            	}
            	if (!synflag.browser.ie5 && !this.isSeparator)
            	   cursor = 'pointer';
            }
			this.setOver(false);
          	this.parent.domNode.appendChild(dn);
          	var a;
			// arrow
			if (this.hasSubMenu() && (a = this.parent.arrow) != null && a.image) {
				var div        = _d.createElement('div');
				this.arrow     = _d.createElement('img');
				div.appendChild(this.arrow);
				this.arrow.src = a.image;
				with (div.style) {
					position = 'absolute';
					width    = a.width + 'px';
					right    = a.padding.right + 'px';
					if (a.padding.top)
						top    = a.padding.top    + 'px';
					else if (a.padding.bottom)
						bottom = a.padding.bottom + 'px';
					else {
						top    = "50%";
						marginTop = '-' + Math.ceil(a.height/2) + 'px';
					}
				}
				dn.appendChild(div);
			}
			// icon
			if (this.icon != null && this.icon.image) {
			    var ic = this.icon;
				var div2      = _d.createElement('div');
				this.iconNode = _d.createElement('img');
				div2.appendChild(this.iconNode);
				this.iconNode.src = ic.image;
				var pa = this.parent.icon;
				with (div2.style) {
					position = 'absolute';
					if (pa.paddingLeft)
						left     = pa.paddingLeft + 'px';
					else
						left     = '5px';
					if (ic.padding && ic.padding.top)
						top    = ic.padding.top    + 'px';
					else if (ic.padding && ic.padding.bottom)
						bottom = ic.padding.bottom + 'px';
					else {
						top    = "50%";
						marginTop = '-' + Math.ceil(pa.height/2) + 'px';
					}
				}
				dn.appendChild(div2);
			}
			
          	if (this.subMenu != null)
	          	this.subMenu.create();
        }
        
        this.setSubMenu = function (s) {
            this.subMenu = s;
        	var sm = s;
        	sm.setParent(this);
        	sm.setRoot(this.root);
        }
		
        this.hasSubMenu = function () {
        	return (this.subMenu != null);
        }
		
		var b = this.border;
		var p = this.padding;
		if (arguments[2]) {
			var c  = arguments[2];
			var cb = c.border;
			var cp = c.padding;
			if (c.itemClass)
				this.itemClass = c.itemClass;
			if (c.itemOverClass)
				this.itemOverClass = c.itemOverClass;
			if (c.itemBorderOverColor)
				this.itemBorderOverColor = c.itemBorderOverColor;
			if (c.icon && c.icon.image)
				this.icon = c.icon;
			if (cb) {
				if (typeof cb.top != _ud)
					b.top = cb.top;				
				if (typeof cb.right != _ud)
					b.right = cb.right;				
				if (typeof cb.bottom != _ud)
					b.bottom = cb.bottom;				
				if (typeof cb.left != _ud)
					b.left = cb.left;				
				if (typeof cb.color != _ud)
					b.color = cb.color;				
				if (typeof cb.style != _ud)
					b.style = cb.style;	
			}
			if (cp) {
				if (typeof cp.top != _ud)
					p.top = cp.top;				
				if (typeof cp.right != _ud)
					p.right = cp.right;				
				if (typeof cp.bottom != _ud)
					p.bottom = cp.bottom;				
				if (typeof cp.left != _ud)
					p.left = cp.left;				
			}
		}
     };

    synflag.widget.Menu = function (config) {

        this.items  = [];
        this.parent = null;
        // top and left: relative values; if parent == null relative to page, else relative to automatic position
        this.top    = 0;
        this.left   = 0;
        this.width  = 0;
        this.height = 0;
        this.unit   = "px";
        this.alwaysVisible = false;
        this.visible = false;
        this.root   = this;
        this.itemClass     = "";
        this.itemOverClass = "";
        this.orientation = "vertical";
        this.containerClass = "";
        this.itemSpacing = 0;
		this.arrangeWidth = null;
		this.arrow = null;
		this.icon = null;

        this.setParent = function (parent) {
            this.parent = parent;
        }

        this.setRoot = function (root) {
            this.root = root;
        	for (var i = 0; i < this.items.length; i++) {
        		this.items[i].setRoot(root);
        	}            
        }

        this.prepareBorder = function (b) {
        	if (typeof b == 'string' || typeof b == 'number') {
        		return {top: b, left: b, bottom: b, right: b, style: 'solid', color: 'black'};
        	} else if (typeof b == 'object') {
        		if (!b.top)
        			b.top    = 0;
        		if (!b.left)
        			b.left   = 0;
        		if (!b.right)
        			b.right  = 0;
        		if (!b.bottom)
        			b.bottom = 0;
        		if (!b.style)
        			b.style  = 'solid';
        		if (!b.color)
        			b.color  = 'black';
        		return b;
        	}
        	return {top: 0, left: 0, bottom: 0, right: 0, style: 'solid', color: 'black'};
        }
        
        this.getFullItemHeight = function (item) {
        	return item.getFullItemHeight();
        }

        this.getFullItemWidth = function (item) {
	       	return item.getFullItemWidth();
        }
        
        this.getCollapsedItemHeight = function (item) {
        	return item.getCollapsedItemHeight();
        }

        this.getCollapsedItemWidth = function (item) {
        	return item.getCollapsedItemWidth();
        }
        
		/**
		 * 
		 * @param {Object} url 			Target URL of the menu item
		 * @param {Object} text			Text/HTML of the menu item
		 * @param {Object} arguments[2] Configuration Object with item specific options
		 * 								(border with color, padding)
		 */
        this.addItem = function (url, text) {
			var item;
			if (arguments[2])
	            item = new synflag.widget.MenuItem(url, text, arguments[2]);
			else
	            item = new synflag.widget.MenuItem(url, text);
            item.setParentMenu(this);
            item.setRoot(this.root);
            // ie 5.0 does not support Array.push, wtf
            this.items[this.items.length] = item;
            if (this.items.length > 1) {
            	var item1 = this.items[this.items.length-2];
            	var item2 = this.items[this.items.length-1];
            	item2.setPrevSibling(item1);
            	item1.setNextSibling(item2);
            }
			// smalltalk style concat of method calls
            return this;
        }
		
        this.addSeparator = function (text) {
			var item;
			if (arguments[1])
	            item = new synflag.widget.MenuItem(null, text, arguments[1]);
			else
	            item = new synflag.widget.MenuItem(null, text);
            item.setParentMenu(this);
            item.setRoot(this.root);
			item.setIsSeparator(true);
            // ie 5.0 does not support Array.push, wtf
            this.items[this.items.length] = item;
            if (this.items.length > 1) {
            	var item1 = this.items[this.items.length-2];
            	var item2 = this.items[this.items.length-1];
            	item2.setPrevSibling(item1);
            	item1.setNextSibling(item2);
            }
			// smalltalk style concat of method calls
            return this;
        }		
        
        this.getOffsetTop = function (node) {
        	var offset = node.offsetTop;
        	while (node.offsetParent != null) {
        		node = node.offsetParent;
        		offset += node.offsetTop;
        	}
        	return offset;
        }

        this.getOffsetLeft = function (node) {
        	var offset = node.offsetLeft;
        	while (node.offsetParent != null) {
        		node = node.offsetParent;
        		offset += node.offsetLeft;
        	}
        	return offset;
        }
        
        this.unselectChildren = function () {
        	for (var i = 0; i < this.items.length; i++) {
        		this.items[i].setOver(false);
        	}
        }

        // Get the maximum real width of all child menu items, if no width is given
        this.getMaxOffsetWidth = function () {
			if (this.maxOffsetWidth)
				return this.maxOffsetWidth;
        	var max = 0;
			var maxSub = 0;
			var dn;
        	for (var i = 0; i < this.items.length; i++) {
        	    dn = this.items[i].domNode;
        		if (dn.offsetWidth > max)
        			max = dn.offsetWidth;
        		if (this.items[i].hasSubMenu() && dn.offsetWidth > maxSub)
					maxSub = dn.offsetWidth;
        	}
			if (this.arrow == null) {
				this.maxOffsetWidth = max;
			} else {
				this.maxOffsetWidth = Math.max(max, maxSub + this.arrow.width + this.arrow.padding.left + this.arrow.padding.right);
			}
			return this.maxOffsetWidth;
        }

        this.getMaxOffsetHeight = function () {
        	var max = 0;
        	for (var i = 0; i < this.items.length; i++) {
        		if (this.items[i].domNode.offsetHeight > max)
        			max = this.items[i].domNode.offsetHeight;
        	}
        	return max;
        }
        
        // Make all child menu items have the same width or height (depending on orientation)
        this.equalizeItems = function () {
			var p, b, maxused = false;
        	var itm;
        	if (this.orientation == 'vertical') {
        		var max = this.getMaxOffsetWidth();
				if (this.maxwidth) {
					b = this.itemBorder;
					p = this.itemPadding;
					if (max > this.maxwidth + p.left + p.right + b.left + b.right) {
						max = this.maxwidth + p.left + p.right + b.left + b.right;
						maxused = true;
					}
				}
        		for (var i = 0; i < this.items.length; i++) {
        		    itm = this.items[i];
					p = itm.getPadding();
					b = itm.getBorder();
       				itm.domNode.style.width = 
						(synflag.browser.bb ? max : max - p.left - p.right - b.left - b.right) + this.unit;
					if (maxused) {
						var a = this.arrow.padding;
						itm.domNode.domNode.style.width      = (max - p.left - p.right - b.left - b.right 
							- (a.right?a.right:0) - (a.width?a.width:0) - (a.left?a.left:0)) + "px";
					}
	        	}
				if (maxused)
	        		for (var i = 0; i < this.items.length; i++) {
						this.items[i].updatePosition();
					}
        	} else {
        		var max = this.getMaxOffsetHeight();
        		for (var i = 0; i < this.items.length; i++) {
        		    itm = this.items[i];
					p = itm.getPadding();
					b = itm.getBorder();
       				itm.domNode.style.height = 
						(synflag.browser.bb ? max : max - p.top - p.bottom - b.top - b.bottom) + this.unit;
	        	}
        	}
        }

		// FIXME: calculate height from items getBorder method
        this.getCompleteItemHeight = function () {
         	var h   = 0;
        	var its = this.items;
       		for (var i = 0; i < its.length; i++) {
   				h += its[i].domNode.offsetHeight;
        	}
        	h += (its.length - 1) * this.itemSpacing;
        	h += (synflag.browser.bb?this.border.top + this.border.bottom:0);
        	h -= (this.skipLastItemBorder?this.itemBorder.bottom:0);
        	h += this.padding.top + this.padding.bottom;
        	h += (this.borderCollapse ? -1 * (its.length-1) * Math.min(this.itemBorder.top, this.itemBorder.bottom) : 0);
        	// FIXME: prevent h < 0 in the first place
        	if (h < 0) { // IE stops processing, if negative height or width is set, while zero width or height is working
        		return 0;
                }
        	return h;
        }

        this.getCompleteItemWidth = function () {
			if (this.arrangeWidth == null)
				return this.getSummarizedItemWidth();
			else
				return this.arrangeWidth;
        }
		
		// FIXME: calculate width from items getBorder method
		this.getSummarizedItemWidth = function () {
        	var w   = 0;
        	var its = this.items;
       		for (var i = 0; i < its.length; i++) {
   				w += its[i].domNode.offsetWidth;
        	}
        	// spacing between items
        	w += (its.length - 1) * this.itemSpacing;
        	// ie5 border-box
        	w += (synflag.browser.bb?this.border.left + this.border.right:0);
        	// 
        	w -= (this.skipLastItemBorder?this.itemBorder.right:0);
        	w += this.padding.left + this.padding.right;
           	w += (this.borderCollapse ? -1 * (its.length-1) * Math.min(this.itemBorder.left, this.itemBorder.right) : 0);
        	return w;
        }

		// FIXME: use getBorder and getPadding of item
		this.updateDimensions = function () {
		    var p = this.padding;
            if (this.orientation == 'vertical') {
            	this.width  = this.items[0].domNode.offsetWidth + p.left + p.right + (synflag.browser.bb?this.border.left + this.border.right:0);
	           	this.height = this.getCompleteItemHeight(); 
           	} else {
            	this.width    = this.getCompleteItemWidth();
   	        	this.height   = this.items[0].domNode.offsetHeight + p.top + p.bottom + (synflag.browser.bb?this.border.top + this.border.bottom:0);
            }
		}
		
        this.create = function () {
			if (!this.arrow || !this.arrow.image) {
				this.create_hlp();
				return;
			}
			var img = new Image();
			var _this = this;
			img.onload = function () {
				_this.arrow.width  = this.width;
				_this.arrow.height = this.height;
				_this.create_hlp();
			}
			img.src = this.arrow.image;
		}

        this.create_hlp = function () {
            this.domNode = _d.createElement("div");
            var dn = this.domNode;
            dn.style.visibility = 'hidden';
			if (this.parentDomNodeId)
				synflag.n(this.parentDomNodeId).appendChild(dn);
			else
	            _d.body.appendChild(dn);
            for (var i = 0; i < this.items.length; i++) {
                this.items[i].create();
            }
            this.equalizeItems();
			this.rearrange();
            var _this = this;
            // if root menu
            if (this.parent == null) {
            	this.alwaysVisible = true;
            }
            dn.onmouseover = function (e) {
            	window.clearTimeout(_this.root.timer);
	           	_this.visible = true;
   	        	var item = _this.items[0];
   	        	while (item != null && item.parent.parent != null) {
   	        		item = item.parent.parent;
   	        		item.setOver(true);
   	        	}
            };
            dn.onmouseout = function (e) {
	           	_this.visible = false;
	           	var _t = _this;
            	window.clearTimeout(_this.root.timer);
            	_this.root.timer = window.setTimeout(function () { _t.root.setVisible(false); }, 500);
            };
            if (this.containerClass)
            	dn.className = this.containerClass;
            with (dn.style) {
//            	whiteSpace = 'nowrap';
				position = "absolute";
            	top      = (this.parent == null ? 0 : this.getOffsetTop(this.parent.domNode)) +this.top+this.unit;
            	left     = (this.parent == null ? 0 : this.getOffsetLeft(this.parent.domNode))+this.left+this.unit;
            	if (this.alwaysVisible == true) {
            		display = 'block';
            	} else {
            		display = 'none';
            	}
            	padding  = '0';
				this.updateDimensions();
	           	width       = this.width + this.unit;
   		       	height      = this.height + this.unit;
            	borderWidth = this.border.top+this.unit+" "+this.border.right+this.unit+" "
            		+this.border.bottom+this.unit+" "+this.border.left+this.unit;
            	borderStyle = this.border.style;
            	borderColor = this.border.color;
            	overflow = 'visible';
				zIndex = 900;
            }
			if (this.skipLastItemBorder) {
				if (this.orientation == 'vertical')
					dn.lastChild.style.borderBottomWidth = 0;
				else
					dn.lastChild.style.borderRightWidth = 0;
			}
            dn.style.visibility = 'visible';
            // IE 7 fix 2009/04/06
           	this.hideChildrensSubMenus();
        }
        
        this.getLastItem = function () {
        	if (this.items.length > 0)
	        	return this.items[this.items.length-1];
	        else
	        	return null;
        }

        this.getFirstItem = function () {
        	if (this.items.length > 0)
	        	return this.items[0];
	        else
	        	return null;
        }

        this.getItem = function (index) {
        	if (this.items.length > index)
	        	return this.items[index];
	        else
	        	return null;
        }

        // FIXME: use synflag.browser.bb for width and height? See iframe version
        this.setVisible = function (bool) {
        	if (this.alwaysVisible && !bool) {
				this.hideChildrensSubMenus();
        		return;
        	}
			this.visible = bool;
			if (bool) {
           		with (this.domNode.style) {
            		top      = 0 + this.unit;
	            	left     = 0 + this.unit;
					display = 'block';
					visibility = 'hidden';
					// ! after setting top & left and before setting width & height
		            this.equalizeItems();
					this.updateDimensions();
	            	width  = this.width  + this.unit;
	            	height = this.height + this.unit;
					zIndex = 900;
				}

				var t = 0, l = 0;
           			t = (this.parent == null ? 0 : 
            			(this.getOffsetTop(this.parent.domNode) + (this.parent.parent.orientation == 'horizontal' ? this.parent.domNode.offsetHeight : 0))) 
            		    + this.top;
            		l = (this.parent == null ? 0 : 
	            		(this.getOffsetLeft(this.parent.domNode) + (this.parent.parent.orientation == 'vertical' ? this.parent.domNode.offsetWidth : 0)))
	            		+ this.left;


            	var size   = synflag.browser.getViewport();
				var scroll = synflag.browser.getScroll();
				size.width  += scroll.x;
				size.height += scroll.y;
            	if (t + this.height > size.height - 10)
            		t  = size.height - this.height - (synflag.browser.ie?7:27);
            	if (l + this.width > size.width - 10) {
					l = this.getOffsetLeft(this.parent.parent.domNode) - this.domNode.offsetWidth;
	           		if (l < 10)
            			l = size.width - this.width - 10;
            	}
            	// Fixes for unreachability of submenus, if relocated because of small viewport
            	// set to t only if not smaller than 5 (small than 0 can not be reached through scrolling)
            	this.domNode.style.top  = (this != this.root && t < 5?5:t) + this.unit;
            	// set to l only if not smaller than 5 (small than 0 can not be reached through scrolling)
            	this.domNode.style.left = (this != this.root && l < 5?5:l) + this.unit;
				if (this.skipLastItemBorder) {
					if (this.orientation == 'vertical')
						this.domNode.lastChild.style.borderBottomWidth = 0;
					else
						this.domNode.lastChild.style.borderRightWidth = 0;
				}
				this.domNode.style.visibility = 'visible';
			} else {
			    if (this.domNode)
    				this.domNode.style.display = 'none';
			}
    		this.hideChildrensSubMenus();
        }
		
		this.rearrange = function () {
			if (this.arrangeWidth == null)
				return;
			var numSpaces = this.items.length-1;
			var arrangeSpace = this.arrangeWidth - this.getSummarizedItemWidth();
			var exactSpacing = arrangeSpace / numSpaces;
			var floorSpacing = Math.floor(exactSpacing);
			var e = arrangeSpace - (numSpaces * floorSpacing);
			this.itemSpacing = floorSpacing;
			for (var i = 1; i < this.items.length; i++) {
				if (i == this.items.length - e)
					this.itemSpacing++;
				this.items[i].updatePosition();
			}
		}
        
        this.hideChildrensSubMenus = function () {
        	for (var i = 0; i < this.items.length; i++) {
        		if (this.items[i].subMenu != null) {
        			this.items[i].subMenu.setVisible(false);
        		}
        		this.items[i].unoverItem();
        	}
        }
        
        this.moveTo = function (x, y) {
        	if (x != null) {
	        	this.left = x;
    	    	this.domNode.style.left = x + this.unit;
    	   	}
    	   	if (y != null) {
        		this.top  = y;
        		this.domNode.style.top  = y + this.unit;
        	}
        }
        
        if (config.top) {
            this.top = config.top;
            this.topCallback = function (page) { return this.top; };
        }
        if (config.topCallback) {
            this.topCallback = config.topCallback;
        }
        if (config.left) {
            this.left = config.left;
            this.leftCallback = function (page) { return this.left; };
        }
        if (config.orientation) {
            this.orientation = config.orientation;
        }
        if (config.leftCallback) {
            this.leftCallback = config.leftCallback;
        }
        if (config.width) {
            this.width = config.width;
        }
        if (config.height) {
            this.height = config.height;
        }
        if (config.maxwidth) {
            this.maxwidth = config.maxwidth;
        }
        // borders: border-width; style: border-style; color: border-color; => 4 values possible for each
        if (config.border) {
            this.border = this.prepareBorder(config.border);
        } else {
        	this.border = {top: 0, left: 0, bottom: 0, right: 0, style: 'solid', color: 'black'};
        }
        if (config.padding) {
            this.padding = this.prepareBorder(config.padding);
        } else {
        	this.padding = {top: 0, left: 0, bottom: 0, right: 0 };
        }
        if (config.itemBorder) {
            this.itemBorder = this.prepareBorder(config.itemBorder);
        } else {
        	this.itemBorder = {top: 0, left: 0, bottom: 0, right: 0, style: 'solid', color: 'black'};
        }
		if (config.itemBorderOverColor) {
			this.itemBorderOverColor = config.itemBorderOverColor;
		}
        if (config.itemPadding) {
            this.itemPadding = this.prepareBorder(config.itemPadding);
        } else {
        	this.itemPadding = {top: 0, left: 0, bottom: 0, right: 0 };
        }
        if (config.containerClass) {
            this.containerClass  = config.containerClass;
        }
        if (config.itemClass) {
            this.itemClass  = config.itemClass;
        }
        if (config.itemOverClass) {
            this.itemOverClass  = config.itemOverClass;
        }
        if (config.borderCollapse) {
            this.borderCollapse  = config.borderCollapse;
        } else {
            this.borderCollapse  = false;
        }
        if (config.skipLastItemBorder) {
            this.skipLastItemBorder  = config.skipLastItemBorder;
        } else {
            this.skipLastItemBorder  = false;
        }
        if (config.itemSpacing) {
            this.itemSpacing  = config.itemSpacing;
        }
        if (config.arrangeWidth) {
            this.arrangeWidth    = config.arrangeWidth;
        }
        if (config.parentDomNodeId) {
            this.parentDomNodeId    = config.parentDomNodeId;
        }
        if (config.icon) {
            this.icon    = config.icon;
        }
        if (config.arrow) {
            this.arrow   = config.arrow;
        }
                
    };

