/**
 * EJSL
 * Java Skript Biliothek für Ephisa CMS
 *
 * Klassen:
 * - Controls
 * +-- ajaxSearch
 *
 * - Split
 * +-- hSplit
 *
 * - Menu
 * - Drag
 * - Drop
 * - DragDrop
 * - Ajax
 * +-- common (static)
 * +-- XPath
 * +-- XSL
 * +-- Loade
 *
 * - Helper
 * - Element
 * - CSS
 * - Effects
 * - Effect
 *
 * Erweiterungen
 * - Array
 * - Number
 * - Function
 * - Object
 *
 * Interfaces
 * - CEnum
 *
 * Copyright 2007 by Philipp Serrer
 * All rights reserved
 *
 */
 
var ve=false;
var to=false;
var path = typeof path == "undefined" ? "" : path;

function setPath(s)
{
	path=s;
}

function StatusMenuReset()
{
	if (to!=false) {
		clearTimeout(to);
	}
}

function StatusMenuHide()
{
	if (ve!==false) {
		$('uf_'+ve).style.display="none";
		ve=false;
		document.onclick=function() { };
	}
	StatusMenuReset();
}

function StatusMenuShow(i)
{
	StatusMenuHide();
	ve=i;
	$('uf_'+i).style.display="inline";
	
	startHideMenu();
}

function startHideMenu(n)
{
	if (n) {
		StatusMenuReset();
		document.onclick=function() { to=setTimeout("StatusMenuHide();",100); };
	}
	else
	{
		
		document.onclick=function() {};
		to=setTimeout("startHideMenu(1);",200);
		
	}
}

function toggleHidden(elm)
{
	if (typeof elm == "string") {
		elm=$(elm);
	}
	else if (elm.each)
	{
		elm.each(function(obj) { toggleHidden(obj); });
		return false;
	}
	
	elm.style.display = elm.style.display == "none" ? "" : "none";
	return true;
}

function toggleMenuImage(elm,i1,i2)
{
	if (typeof elm == "string") {
		elm=$(elm);
	}
	
	if (!i1)
		i1="open.jpg";
	if (!i2)
		i2="close.jpg";
	
	if (baseName(elm.src)==i2) {
		elm.src = basePath(elm.src)+i1;
	}
	else
	{
		elm.src = basePath(elm.src)+i2;
	}
}

function basePath(path)
{
	return path.lastIndexOf("/") == -1 ? "" : path.substr(0, path.lastIndexOf("/")+1);
}

function baseName(path)
{
	return path.lastIndexOf("/") == -1 ? path : path.substr(path.lastIndexOf("/")+1);
}


//Prototypen
var SystemHandlers=new Array();

Object.addElements = function(object, elements)
{
  for (element in elements) {
    object[element] = elements[element];
  }
	
  return object;
};

if (!window.Event) {
  var Event = new Object();
}
if (!window.Element) {
  var Element = new Object();
}


var Controls = new Object();
Controls.ajaxSearch = new Object(function(e, cname) { this.elm = e; this.cname = cname; this.init(); });
Controls.message = new Object(function(e, cname) { this.construct(); });
Controls.help = new Object(function(e, text, opts) { this.elm = e; this.text = text; this.init(opts); });

Object.addElements(Controls.help, {
	visible: false
});

Object.addElements(Controls.help.prototype, {
	
	elm: false,
	icon: false,
	text: "",
	style: "alert",
	boxImg: false,
	boxPos: false,
	opts: false,
	
	init: function(opts)
	{
		var e = this.elm;
		
		if (!e) {
			return false;
		}
		
		this.opts = opts;
		
		if (opts) {
			if (opts.icon) {
				this.addIcon();
			}
			
			if (opts.hover) {
				if (opts.hover) {	
					Event.addHandler("mouseover", e, function() {this.showHelp();}.bindEvent(this,this));
					Event.addHandler("mouseout", e, function() {this.hide();}.bindEvent(this,this));
				}
			}
			
			if (opts.style) {
				this.style = opts.style;
			}
			
			if (opts.boxPos) {
				this.boxPos = opts.boxPos;
			}
		}
		
		if (this.style == "box") {
			this.addBox();
		}
		else if (this.style == "message")
		{
		
		}
		
	},
	
	addBox: function()
	{
		var box = Element.newElement("div", { },
			{
				display: "none",
				position: "absolute",
				backgroundColor: "black",
				color: "white",
				padding: "1px 5px",
				cursor: "pointer",
				zIndex: 10000
			});
		
		Element.setStyle(box, this.boxPos == "right" ? "marginLeft": "marginTop", "8px");
		
		box.innerHTML = this.text;		
		var img = this.boxPos == "right" ? "left.gif": "top.gif";
		
		Element.appendFirst(this.boxImg = Element.newElement("img",
			{ src: path + "images/help/" + img },
			{
				position: "absolute",
				marginTop: "-6px"
			}
		), box);
		
		Event.addHandler("click", box, function() { this.hide(); }.bindEvent(this,this));
		
		this.box = box;
		this.elm.parentNode.appendChild(box, this.elm);
	},
	
	addIcon: function()
	{
		var i = Element.newElement("img",
			{
				src: path + "images/help.gif"
			},
			{
				cursor: "pointer",
				verticalAlign: "text-bottom"
			});
		
		Event.addHandler("click", i, function(e) {
			this.showHelp();
		}.bindEvent(this,this));
		
		this.icon = i;
		this.elm.parentNode.appendChild(i, this.elm);
	},
	
	hide: function()
	{
		switch (this.style) {
		case "message":
			break;
			
		case "box":
			Element.setStyle(this.box, {
				display: "none"
			});
		}
		
		if (this.icon) {
			Element.setStyle(this.icon, "display", "");
		}
			
	},
	
	showHelp: function()
	{
		
		if (Controls.help.visible) {
			Controls.help.visible.hide();
		}
		
		Controls.help.visible = this;
		
		switch (this.style) {
		case "alert":
			alert("Hier werden sie geholfen");
			break;
		
		case "message":
			break;
			
		case "box":
			var p = Element.absPosition(this.elm);
			var cp;
			var w = 0;
			var left = 0, top = 0;
			
			if (this.icon) {
				Element.setStyle(this.icon, "display", "none");
			}
			
			if (this.boxPos == "right") {
				left = p[0] + this.elm.offsetWidth;
				top = p[1];
				
				if (this.opts && this.opts.width) {
					w = this.opts.width;
				}
				else
				{
					w = this.elm.parentNode.offsetWidth - (this.elm.offsetLeft /*- this.elm.parentNode.offsetLeft*/) - this.elm.offsetWidth - 25;
				}
				
				if (w < 0) {
					w = 250;
				}
			}
			else
			{
				left = p[0];
				top = p[1] + this.elm.offsetHeight;
				
				w = this.elm.offsetWidth;
			}
			
			cp = this.elm.parentNode;
			
			while (cp != document) {
				var s2 = Element.getStyle2(cp, "position");
				if (s2 == "relative" || s2 == "absolute") {
					var pp = Element.absPosition(cp);
					left = left - pp[0];
					top = top - pp[1];
					break;
				}
				
				cp = cp.parentNode;
			}
			
			if (this.opts && this.opts.marginTop) {
				top += this.opts.marginTop;
			}
			
			if (this.opts && this.opts.marginLeft) {
				left += this.opts.marginLeft;
			}
			
			Element.setStyle(this.box, {
				display: "",
				left: left + "px",
				top: top + "px",
				width: (w-10) + "px"  //-10: padding!
			});
			
			if (this.boxPos == "right") {
				Element.setStyle(this.boxImg, {
					marginLeft: "-10px",
					top: (this.elm.offsetHeight > this.box.offsetHeight ? this.box.offsetHeight : this.elm.offsetHeight) / 2 + 3 + "px"
				});
				
			}
			else
			{
				Element.setStyle(this.boxImg, {
					left: parseInt(this.elm.offsetWidth / 2-5) + "px"
				});
			}
			
			break;
		}
	}
});

Object.addElements(Controls.message.prototype, {
	
	box: false,
	s: false,
	main: false,
	c: false,
	elm: false,
	
	construct: function()
	{
		var s = Helper.getClientSize();
		var pos = "fixed";
		
		if (/MSIE (5\.5|6\.)/.test(navigator.userAgent)) {
			pos = "absolute";
		}
		
		Controls.message.main = document.createElement("div");
		
		Element.setStyle(Controls.message.main, {
			position: pos,
			width: "100%",
			height: "100%",
			left : "0px",
			top : "10px",
			display : "none",
			backgroundColor: "#000",
			zIndex : 100000
		});
		
		var rd = function(e,l) {
			if (l.box) {
				l.setPos();
			}
		}.bindEvent(this,this);
		
		Event.addHandler("resize", window, rd);
		//Event.addHandler("scroll", window, rd);
		
	},
	
	setPos: function()
	{
		var main = Controls.message.main;
		var s = Helper.getClientSize();
		
		Element.setStyle(main, {
			width: s[0] + "px",
			height: (s[1]) + "px"
			
			}
		);
		
		Element.setStyle(this.box,{
			//top: main.offsetHeight / 2 - this.box.clientHeight / 2 + "px"
		});
	},
	
	show: function (message, close, btns, opt)
	{
		var main = Controls.message.main;
		var box = false;
		var msg = this;
		var pos = "fixed";
		
		if (/MSIE (5\.5|6\.)/.test(navigator.userAgent)) {
			pos = "absolute";
		}
		
		if (!this.box) {
			this.box = box = document.createElement("div");
		}
		else
		{
			box = this.box;
		}
		
		$t("body")[0].appendChild(Controls.message.main);
		
		Controls.message.active = this;
		
		Element.setStyle(main, {
			opacity: 0,
			display: "",
			backgroundColor: "#000"
		});
		
		Element.setStyle(box, {
			opacity: 0,
			position: pos,
			border: "1px solid #333",
			backgroundColor: "#efefef",
			zIndex: 999999999,
			padding: "20px 10px 10px 10px"
		});
		
		this.setPos();
		
		if (typeof message == "object") {
			box.appendChild(message);
			this.elm = message;
			
			Element.setStyle(message, "display", "");
			CSS.removeClass(message, "hidden");
			message._msg = this;
		}
		else
		{
			box.innerHTML = message;
		}
		
		var w = "70%";
		if (opt) {
			if (opt.top) {
				Element.setStyle(box, "top", opt.top+"px");
			}
			if (opt.width) {
				w = opts.width+"px";
			}
		}
		Element.setStyle(box, {
			width: w
		});
		
		var s = Helper.getClientSize();
		var l = function() {
			return (s[0] / 2 - box.clientWidth/2)+"px";
		};
		
		Effects._(main, true).hide({duration: 600, from:0, to:0.5});
		Effects._(box, true).hide({duration: 1300, from:0, to:1, update:function() { box.style.left = l(); }});
		
		
		//main.parentNode.appendChild(box);
		Element.appendFirst(box,main.parentNode);
	},
	
	close: function()
	{
		if (this.elm) {
			Element.setStyle(this.elm, "display", "none");
			this.box.parentNode.appendChild(this.elm);
			this.elm = false;
		}
		
		Element.remove(this.box);
		Effects._(Controls.message.main, true).hide({duration: 200, from:0.5, after: function() { Element.setStyle(Controls.message.main, "display", "none"); }.bind(this,this)});
		
		this.box = false;
	}
});

Object.addElements(Controls.ajaxSearch.prototype, {
	
	elm: false,
	ajax: false,
	ul: false,
	count: false,
	list: false,
	menu: false,
	oldVal: false,
	hideC: false,
	hover: false,
	haveFocus: false,
	activeIndex: -1,
	activeText: "",
	
	init: function()
	{
		var e = this.elm;
		
		if (!e) {
			return false;
		}
		
		this.ajax = new AJAX();
		
		//Events
		Event.addHandler("keydown", e, function(e) { if ((e.which || e.keyCode) == 13) Event.stop(e); });
		Event.addHandler("keyup", e, this.keyup.bindEvent(this, e));
		Event.addHandler("mousemove", document, this.move.bindEvent(this, e));
		Event.addHandler("focus", e, this.focus.bindEvent(this, e));
		Event.addHandler("blur", e, this.blur.bindEvent(this, e));
		this.ajax.addAction("ajaxSearch", this.response.bind(this, this));
		
		var menu = Element.newElement("div",
			{ className : "ajaxSearchMenu" },
			{
				display : "none",
				marginTop : (e.offsetHeight + 2 ) + "px",
				width : e.offsetWidth + "px",
				height:  "100px"
			}
		);
		
		//Event.addHandler("mouseenter", menu, this.mouseenter.bindEvent(this, e));
		//Event.addHandler("mouseout", menu, this.mouseout.bindEvent(this, e));
		
		this.menu = menu;
		this.ul = Element.newElement("ul");
		this.count = 0;
		this.list = new Array();
		this.enter = false;
		this.wantHide = false;
		menu.appendChild(this.ul);
		
		e.parentNode.insertBefore(menu, e);
		return true;
	},
	
	focus: function()
	{
		this.haveFocus = true;
	},
	
	blur: function()
	{
		this.haveFocus = false;
	},
	
	isVisible: function()
	{
		return (this.menu.style.display == "");
	},
	
	move: function(e)
	{
		var p = Event.position(e);
		
		if (!Element.hitTest(this.menu, p[0], p[1]) && !Element.hitTest(this.elm, p[0], p[1])) {
			this.hideC = window.setTimeout(function() { this.hide(); }.bind(this, this), 1000);
			this.hover = false;
		}
		else
		{
			if (this.hideC) {
				window.clearTimeout(this.hideC);
				this.hideC = false;
			}
			
			this.hover = true;
		}
	},
	
	show: function()
	{
		var p = Element.absPosition(this.elm);
		
		Element.setStyle(this.menu, {
			display: "",
			left: p[0] + "px",
			top: (p[1] + this.elm.offsetHeight + 2) + "px",
			margin: 0
		});
	},
	
	hide: function(n)
	{
		if (this.hover && !this.haveFocus || n) {
			Element.setStyle(this.menu, "display", "none");
		}
	},
	
	keyup: function(e, elm)
	{
		if (this.oldVal != elm.value && elm.value) {
			this.ajax.get(path + "web/control/ajaxSearch/", { p: this.cname, q : elm.value });
		}
		else if (!elm.value)
		{
			this.hide();
		}
		
		this.oldVal = elm.value;
		
		//Bringt nur was, wenn auch das Menu da ist
		if (this.isVisible()) {
			var key = 0;
			if (e.which) {
				key = e.which;
			}
			else if (e.keyCode)
			{
				key = e.keyCode;
			}
			
			//Runter
			if (key == 40) {
				if (this.activeIndex != -1) {
					CSS.removeClass(this.list[this.activeIndex], "hover"); //deaktivieren
				}
				
				this.activeIndex++;
				if (this.activeIndex >= this.list.length || this.list[this.activeIndex].style.display == "none") {
					this.activeIndex = 0; //War zuweit
				}
			}
			//Hoch
			else if(key == 38)
			{
				if (this.activeIndex != -1) {
					CSS.removeClass(this.list[this.activeIndex], "hover"); //deaktivieren
					
					this.activeIndex--;
					
					if (this.activeIndex == -1) {
						for (i=this.list.length-1; i>=0; i--) {
							if (this.list[i].style.display == "") {
								this.activeIndex = i;
								break;
							}
						}
					}
				}
				else
				{
					for (i=this.list.length-1; i>=0; i--) {
						if (this.list[i].style.display == "") {
							this.activeIndex = i;
							break;
						}
					}
				}
			}
			//Return
			else if (key == 13)
			{
				this.hide(true);
				this.elm.value = this.activeText;
			}
			
			if (this.activeIndex != -1) {
				CSS.addClass(this.list[this.activeIndex], "hover");
			}
			
			this.activeText = this.activeIndex == -1 ? "" : this.list[this.activeIndex].innerHTML;
		}
	},
	
	response: function(t,e,f,xml)
	{
		var xpath = new AJAX.XPath(xml.responseXML);
		var s = xpath.selectNodes("/data/item");
		var from = xpath.selectNode("/data/from");
		var li;
		
		if (!from || from.nodeValue != this.cname) {
			return;
		}
		
		for (var i = 0; i < s.length; i++) {
			var v = "";
			if (typeof s[i].nodeValue == "undefined" || s[i].nodeValue == null) {
				v = s[i].firstChild.nodeValue;
			}
			else
			{
				v = s[i].nodeValue;
			}
			
			if (i >= this.count) {
				//Zu wenige Listen Elemente
				t.count = i+1;
				li = Element.newElement("li");
				Event.addHandler("mouseover", li, function(e, elm) { CSS.addClass(elm, "hover"); }.bindEvent(t, li));
				Event.addHandler("mouseout", li, function(e, elm) { CSS.removeClass(elm, "hover"); }.bindEvent(t, li));
				Event.addHandler("mousedown", li, function(e, elm) { this.elm.value = elm.innerHTML; t.hide(this); }.bindEvent(t, li));
				t.ul.appendChild(li);
				t.list[i] = li;
			}
			else
			{
				li = t.list[i];
			}
			
			//Aktives Element
			if (v == this.activeText) {
				t.activeIndex = i;
				CSS.addClass(li, "hover"); //Markiert
			}
			else
			{
				v.className = "";
			}
			
			li.style.display = "";
			li.innerHTML = v;
		}
		
		//Überflüssige Elemente ausblenden
		for (;i < t.count; i++) {
			t.list[i].style.display = "none";
		}
		
		if (s.length > 0) {
			t.show();
		}
	}
	
});


var Split = new Object();
Split.hSplit = new Object(function(e) { this.elm = e ? e : false; });

Object.addElements(Split.hSplit.prototype, {
	
	elm: false,
	
	init: function(left, right)
	{
		//ToDo
	},
	
	update: function(s)
	{
		var e = this.elm;
		var hsplit = $C("hsplit", e).first();
		var panels = $C("panel", e);
		var status;
		
		if (typeof s != "undefined") {
			status = e._hsplit_status = s;
			e._hsplit_next = s==0 ? 1 : 0;
		}
		else
		{
			if (typeof e._hsplit_status == "undefined")
			{
				e._hsplit_status = 0;
				e._hsplit_next = 1;
				status = e._hsplit_next;
			}
			else
			{
				status = e._hsplit_next;
			}
			
			if (e._hsplit_next == 1 && e._hsplit_status == 0) {
				e._hsplit_next = 0;
			}
			else if (e._hsplit_next == 0 && e._hsplit_status == 1)
			{
				e._hsplit_next = -1;
			}
			else if (e._hsplit_next == 0 && e._hsplit_status == -1)
			{
				e._hsplit_next = 1;
			}
			else
			{
				e._hsplit_next = 0;
			}
		}
		
		if (e._hsplit_next < status) {
			hsplit.style.backgroundImage = "url(images/right.gif)";
		}
		else
		{
			hsplit.style.backgroundImage = "url(images/left.gif)";
		}
		
		//Position des Splitters
		hsplit.style.marginLeft = (status == 0 ? e.offsetWidth / 2 - 3 : (status == -1 ? e.offsetWidth - 9 : 0)) + "px";
	
		//Breite der Panels
		panels.each(function(obj,idx) {
			if (status == 0) {
				obj.style.width = e.offsetWidth / 2 - 8 + "px";
				obj.style.display = "";
			}
			else
			{
				if (idx == 0 && status == -1 || idx == status) {
					obj.style.width = e.offsetWidth - 9 + "px";
					obj.style.display = "";
				}
				else
				{
					obj.style.display="none";
				}
			}
		});
		
		e._hsplit_status = status;
	}
});

var Switcher = new Object();

Object.addElements(Switcher, {
	
	data: false,
	
	s: function(elm,n) {
		
		if (!n) {
			n = "_main";
		}
		
		if (!this.data) {
			this.data = new Object;
		}
		
		if (this.data[n] == elm)
			return;
		
		if (this.data[n]) {
			var h = this.data[n];
			Effects._(h,true).hide({duration: 100, after: function()
			{
				Effects._(elm,true).hide({from: 0, to:1, duration: 200});
				Element.setStyle(h, "display", "none");
				Element.setStyle(elm, "display", "");
			}});
		}
		else
		{
			Element.setStyle(elm, "display", "");			
		}
		
		this.data[n] = elm;
	}
	
});

var Menu = new Object(function() { });

Object.addElements(Menu.prototype, {
	
	hi: false,
	menu: false,
	init: false,
	enter: false,
	
	onhide: false,
	
	show: function(elm,display)
	{
		var mnu = this;
		if (!this.init) {
			this.init = true;
			Event.addHandler("click", document, function (event) { mnu.hide(event); }.bindEvent(this));
			Event.addHandler("mousemove", document, function (event) { mnu.hide(event,1500); }.bindEvent(this));
		}
		
		if (typeof elm == "string") {
			elm = $(elm);
		}
		
		if (this.menu && this.menu != elm) {
			this.menu.style.display = "none";
		}
		
		if (display)
			elm.style.display=display;
		else
			elm.style.display="";
		
		elm.style.zIndex = "1000000000";
		
		this.enter = false;
		this.menu = elm;
	},
	
	hide: function(e,timeout)
	{
		var mnu = this;
		if (!this.menu) {
			return false;
		}
		
		if (e) {
			if (Element.hitTest(this.menu, Event.x(e), Event.y(e))) {
				window.clearTimeout(this.hi);
				this.enter = true;
				this.hi = false;
				return false;
			}
		}
		
		if (!this.enter)
		{
			return false;
		}
		
		if (timeout) {
			if (!this.hi) {
				this.hi = window.setTimeout(function() { mnu.hide(); },timeout);
			}
			return true;
		}
		else
		{
			this.menu.style.display = "none";
		}
		
		this.menu = false;
		this.enter = false;
		
		if (this.onhide) {
			this.onhide(this);
		}

		return true;
	}
	
});


var Drag = new Object();
var Drop = new Object();
var DragDrop = new Object();

Object.addElements(DragDrop,
	{
		Draggabels: new Array(),
		Droppabels: new Array(),
		ActiveElement: false,
		pos: false,
		lastPos: false,
		
		init: function()
		{
			Event.addHandler("mousemove",document,this.onmousemove.bindEvent(this));
			Event.addHandler("mouseup",document,this.onmouseup.bindEvent(this));
		},
		
		onmousemove: function(event)
		{
			if (!this.ActiveElement || Helper.equals(Event.position(event), this.lastPos))
				return false;
				
			var opts = this.ActiveElement;
			var elm = opts.elm;
			var p = this.pos;
			
			
			this.lastPos = Event.position(event);
			
			if (!p) {
				var ro = Element.realOffset(elm);
				p = Element.absPosition(elm);
				p = [Math.abs(p[0] - Event.x(event) - ro[0]) , Math.abs(p[1] - Event.y(event) /*+ ro[1]*/)];
				this.pos=p;
			}
			
			
			if (opts.ghost && elm._clone) {
				elm = elm._clone;
			}
			
			elm.style.top=(Event.y(event)-p[1])+"px";
			elm.style.left=(Event.x(event)-p[0])+"px";
			
			return false;
		},
		
		onmouseup: function(event)
		{
			if (Drop.ActiveElement && Drop.ActiveElement.ondrop) {
				Drop.ActiveElement.ondrop(event, this.ActiveElement);
			}
			
			if (Drag.ActiveElement && Drag.ActiveElement.ondrop) {	
				Drag.ActiveElement.ondrop(event, this.ActiveElement);
			}
			
			if (this.ActiveElement.ghost) {
				Element.remove(this.ActiveElement.elm._clone);
				this.ActiveElement.elm._clone=null;
			}
			
			this.ActiveElement = Drop.ActiveElement = Drag.ActiveElement = false;
			this.pos=false;
			
			return;
		},
		
		draggingElement: function()
		{
			return (this.ActiveElement ? (this.ActiveElement.ghost ? this.ActiveElement.elm._clone : this.ActiveElement.elm) : alert(false));
		}
	}
);

Object.addElements(Drag,
	{

		addElement: function(id)
		{
			var elm;
			var opts = {
				ghost: true,
				dragging: true,
				ondrag: false,
				ondrop: false,
				snap: false
			};

			if (!id)
				return false;
			else if (typeof id == "string")
				elm = $(id);
			else
				elm = id;
			
			Object.addElements(opts, arguments[1] || {} );
			opts.elm = elm;
			
			DragDrop.Draggabels.push(opts);
			DragDrop.init();
			//elm.style.position="absolute";
			elm.style.zindex=1000;
			
			var cb = function(event) { Drag.onmousedown(event,opts); return false; }.bindEvent(this);
			
			elm.onmousedown = cb;
			//Event.addHandler("mousedown",elm, cb);
			
			Event.addHandler("click",elm, function(event) { return false; }.bindEvent(this));
			return true;
		},
		
		onmousedown: function(event,opts)
		{
			var elm = opts.elm;
			var _clone = false;
			
			if (opts.ondrag && !opts.ondrag(event, opts))
				return;
			
			DragDrop.ActiveElement = opts;
			
			if (opts.dragging) {
				if (opts.ghost) {
					_clone = elm.cloneNode(true);
					Element.setOpacity(_clone, 0.7);
					
					elm._clone = _clone;
					//elm.parentNode.insertBefore(_clone,elm);
					document.body.appendChild(_clone);
					if (!elm.style.width) {
						_clone.style.width = (elm.offsetWidth - parseInt(elm.style.paddingLeft) - parseInt(elm.style.paddingRight)) + "px";
					}
				}
				else
				{
					_clone = elm;
					elm._oldPosition = elm.style.position;
				}
				
				_clone.style.position = "absolute";
				_clone.style.zIndex = 1000000;
				
				DragDrop.onmousemove(event);
			}
			
			return false;
		}
		
	}
);

Object.addElements(Drop,
	{
		ActiveElement: false,
		refElm: false,
		
		addElement: function(elm)
		{
			if (typeof elm == "string")
				elm = $(elm);
			
			if (!elm)
				return false;
			
			var opts = {
				ondrop: false,
				highlight: true
			};
			
			Object.addElements(opts, arguments[1] || {} );
			opts.elm = elm;
				
			DragDrop.Droppabels.push(opts);
			
			Event.addHandler("mousemove", document, function(event) { Drop.onmousemove(event,elm); }.bindEvent(this));
			//Event.addHandler("mouseout", elm, function(event) { Drop.onmouseout(event,elm); }.bindEvent(this));
			return true;
		},
		
		onmousemove: function(event, elm)
		{
			var found = false;
			var out = false;
			
			if (!DragDrop.ActiveElement)
				return;
				
			DragDrop.Droppabels.each(function(opts,idx)
			{
				var elm = opts.elm;
				
				if (Element.hitTest(elm, Event.x(event), Event.y(event))) {
					
					if (Drop.ActiveElement.elm != elm) {
						if (Drop.ActiveElement.elm) {
							out = Drop.ActiveElement;
						}
						
						if (opts.highlight)
							Effects._(elm).blink({swap: true});
						
						Drop.ActiveElement = opts;
						
						if (opts.onmove) {
							opts.onmove(elm, opts);
						}
						
						if (DragDrop.ActiveElement.snap)
							elm.appendChild(DragDrop.draggingElement());
					}
					
					if (DragDrop.ActiveElement.snap) {
						this.refElm = Element.insertRelative(DragDrop.draggingElement(), elm, Event.x(event), Event.y(event), this.refElm);
						DragDrop.draggingElement().style.position = "";
					}
					
					found = true;
				}
			});
			
			if (!found) {
				if (Drop.ActiveElement && Drop.ActiveElement.onmouseout) {
					out = Drop.ActiveElement;
				}
				
				this.ActiveElement = false;
				DragDrop.draggingElement().style.position = "absolute";
			}
			
			if (out && out.onmouseout) {
				out.onmouseout(elm, Drop.ActiveElement);
			}
		}
		
	}
);

var AJAX = new Object(function() { });
AJAX.XPath = new Object(function(xmldoc) { this.xdoc = xmldoc; });
AJAX.XSL = new Object(function() { });
AJAX.Loader = new Object(function(elm,gfx) { this.init(elm,gfx); });
AJAX.common = new Object();

Object.addElements(AJAX.common,
	{
		
		callbacks: new Array(),
		xmlObj: new Array(),
		
		addXMLObj: function(obj)
		{
			this.xmlObj.push(obj);
		},
		
		response: function()
		{
			//this.xml=AJAX.xml;
			//this.callbacks=AJAX.callbacks;
			
			AJAX.common.xmlObj.each(function(ref) {
			
				if (ref.readyState == 4) {
					if (ref.status==200) {
						var xmldoc = ref.responseXML.documentElement;
						var xpath = new AJAX.XPath(xmldoc);
						var action = xpath.selectNode("/data/action");				
						var call = [];
						
						if (action.length == 0 && AJAX.common.callbacks[0]) {
							call = AJAX.common.callbacks[0];
						}
						else if (action.length != 0 && action)
						{
							action = action.nodeValue;
	
							if (AJAX.common.callbacks[action]) {
								call = AJAX.common.callbacks[action];
							}
						}
						
						call.each(function(fnc) {
							fnc(xmldoc, ref, action);
						});
						
					}
					else
					{
						this._error();
					}
					
					AJAX.common.xmlObj = AJAX.common.xmlObj.without(ref);
				}
			});
			
		},
		
		requestCount: function()
		{
			return AJAX.common.xmlObj.length;
		},
		
		addAction: function(action, callback)
		{
			if (!this.callbacks) {
				this.callbacks = new Array();
			}
			
			if (this.callbacks[action] != undefined) {
				if (this.callbacks[action] != callback) {
					if (!this.callbacks[action].isIn(callback)) {
						this.callbacks[action].push(callback);
					}					
				}
			}
			else
			{
				this.callbacks[action] = [callback];
			}
		},
		
		handleEvent: function(action, callback)
		{
			this.addAction();
		}
		
	}
);

Object.addElements(AJAX.prototype, 
	{
		xml: false,
		callbacks: new Array(),
		
		_error: function()
		{
			var text;
			//Wenn der Status nicht 200 ist(also Fehler) eine Fehlermeldung ausgeben
			//404 ist "Seite nicht gefunden"
			if (this.xml.status==404) {
				text="404: Seite nicht vorhanden";
			}
			else
			{
				text="Fehler " + this.xml.status + ": " + this.xml.statusText;
			}
			
			alert("Fehler beim Empfangen:\n\n"+text);	//Fehlermeldung ausgeben
		},
		
		xpath: function()
		{
			return new AJAX.XPath(this.xml.responseXML);
		},
		
		init: function()
		{
			this.xml = this.loadXML();
			
			if (this.xml.overrideMimeType)
			{
				this.xml.overrideMimeType('text/xml');	//Mime Type überschreiben mit XML
			}
			
			//Eventhandler läuft über AJAX.common Objekt
			this.xml.onreadystatechange = AJAX.common.response; // this._response.bind(this, this);
			AJAX.common.addXMLObj(this.xml);
		},
		
		addAction: function(action, callback)
		{
			AJAX.common.addAction(action, callback.bind(this, this));
		},
		
		handleEvent: function(action, callback)
		{
			AJAX.common.addAction(action, callback.bind(this, this));
		},
		
		loadXML: function()
		{
			var tmp = false;
	
			try {
				if (window.ActiveXObject)
				{	
					try
					{
						tmp = new ActiveXObject("Msxml2.XMLHTTP");
					}
					catch (e)
					{
						tmp = new ActiveXObject("Microsoft.XMLHTTP");
					}
				}
				else if (window.XMLHttpRequest)
				{
					tmp = new XMLHttpRequest();
				}
				else
				{
					//alert("Ajax wird nicht unterstützt");
					var tmp=false;
				}
			}
			catch (e)
			{
				alert("Ajax konnte nicht geladen werden");
				tmp=false;
			}
			
			return tmp;
		},
		
		createParamList: function(data)
		{
			var tmp = "";
			
			if (!data)
				return tmp;
			
			for (obj in data) {
				//Nur Strings
				if (typeof data[obj] == "string") {
					if (tmp != "") {
						tmp += "&";
					}
					
					tmp += obj+"="+encodeURIComponent(data[obj]);
				}
			}
			
			return tmp;
		},
		
		post: function(uri,data)
		{
			var tmp = this.createParamList(data);
			
			this.init();
			this.xml.open('POST', uri, true);
			
			this.xml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			this.xml.setRequestHeader("Content-length", tmp.length);
			
			//Daten senden
			this.xml.send(tmp);
			
			return true;
		},
		
		get: function(uri,data)
		{
			if (data)
				uri += "?" + this.createParamList(data);

			this.init();
			this.xml.open('GET', uri, true);
			this.xml.send(null);
		}
	}
);


Object.addElements(AJAX.XSL.prototype, {
	
	xsl: false,
	
	load: function(file)
	{
		var xsl;
		
		try {
			
			if (window.ActiveXObject) {
				xsl = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
			}
			else if (window.XSLTProcessor)
			{
				xsl = document.implementation.createDocument("","",null);
			}
			
			xsl.async = false;
			xsl.load(file);
			
			this.xsl = xsl;
			
			return this;
		}
		catch (e)
		{
			return false;
		}
	},
	
	transform: function(xmldoc, append)
	{
		var processor;
		var i;
		var elm;
		var tmp;
		
		if (!this.xsl) {
			return false;
		}
		
		try {
			
			if (window.ActiveXObject) {
				var elm;
				var tpl = new ActiveXObject("Msxml2.XSLTemplate");
				tpl.stylesheet = this.xsl;
				
				processor = tpl.createProcessor();
				processor.input = xmldoc;
				
				processor.transform();
				
				if (append) {
					tmp = processor.output;
					
					//Hack, für den Fall, das ein <tr>..</tr> Tag eingefügt werden soll...
					if (tmp.substr(0,3) == "<tr") {
						tmp = "<table>" + tmp + "</table>";
						elm = Element.newElement("div");
						elm.innerHTML = tmp;
						
						for (i=0; i < elm.firstChild.childNodes.length; i++) {
							append.appendChild(elm.firstChild.childNodes.item(i));
						}
					}
					else
					{
						append.innerHTML += processor.output;
					}
					
					
					return true;
				}
				else
				{
					return Element.newElement("div", { innerHTML: processor.output });
				}
			}
			else if (window.XSLTProcessor)
			{
				xsl = document.implementation.createDocument("","",null);
				
				processor = new XSLTProcessor();
				processor.importStylesheet(this.xsl);
				
				if (append) {
					append.appendChild(processor.transformToFragment(xmldoc, document));
					return true;
				}
				else
				{
					return processor.transformToFragment(xmldoc, document);
				}
			}
			
		}
		catch (e)
		{
			return false;
		}
	}
	
});



Object.addElements(AJAX.XPath.prototype, {
	
	xdoc: false,
	
	selectNodes: function(n,d)
	{
		var ret = new Array();
		var xeval;
		var res;
		var doc = this.xdoc;
		
		if (!doc && !d) {
			return false;
		}
		else if (d)
		{
			doc = d;
		}
		
		try {
			if (window.ActiveXObject) {
				ret = doc.selectNodes(n);
			}
			else if(window.XPathEvaluator)
			{
				
				xeval = new XPathEvaluator();
				res = xeval.evaluate(n, doc, null, XPathResult.ORDER_NODE_ITERATOR_TYPE, null);

				ret = $A(res);
			}
			
			return ret;
		}
		catch (e)
		{
			return ret;
		}
		
	},
	
	selectNode: function(n,d)
	{
		var ret = new Array();
		var xeval;
		var res;
		var doc = this.xdoc;
				
		if (typeof doc != "object" && typeof d != "object") {
			return false;
		}
		else if (d)
		{
			doc = d;
		}
		
		
		try {
			if (window.ActiveXObject) {
				ret = doc.selectSingleNode(n);
			}
			else if(window.XPathEvaluator)
			{
				
				xeval = new XPathEvaluator();
				res = xeval.evaluate(n, doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

				ret = res.singleNodeValue;
			}
			
			if (ret) {
				return ret.firstChild;
			}
			else
			{
				return false;
			}
		}
		catch (e)
		{
			return ret;
		}
		
	},
	
	selectNodeValue: function(n,d)
	{
		var value = this.selectNode(n,d);
		
		return value ? value.nodeValue : "";
	}
	
});

Object.addElements(AJAX.Loader.prototype, {
	
	gfx: "../images/round.gif",
	img: false,
	shadow: false,
	elm: false,
	
	init: function(elm, gfx)
	{
		if (!elm) {
			this.elm = false;
		}
		else
		{
			this.elm = elm;
		}
		
		if (!gfx) {
			this.gfx = "../images/round.gif";
		}
		else
		{
			this.gfx = gfx;
		}
		
		Event.addHandler("resize", window, function(e,l) {
			if (l.bshow == true) {
				l.show();
			}
		}.bindEvent(this,this));
		
		this.img = Element.newElement("img",{ src: this.gfx}, { border:"0", position: "absolute", display: "none" });
		this.shadow = Element.newElement("div",false, { backgroundColor:"#000", opacity: .55, position: "absolute", display:"none" });
	},
	
	getShadow: function()
	{
		return this.shadow;
	},
	
	show: function(elm)
	{		
		if (!elm) {
			if (this.elm) {
				elm = this.elm;
			}
			else
			{
				return false;
			}
		}
		
		var p = Element.absPosition(elm);
		
		if (this.shadow) {
			document.body.appendChild(this.shadow);
			
			
			Element.setStyle(this.shadow, {
				display: "block",
				
				width: elm.offsetWidth + "px",
				height: elm.offsetHeight + "px",
				
				left: p[0] + "px",
				top: p[1] + "px"
				});
		}

		if (this.img) {
			document.body.appendChild(this.img);
			
			Element.setStyle(this.img, {
				display: "",
				
				left: (p[0] + (elm.offsetWidth/2 - this.img.offsetWidth/2) ) + "px",
				top: (p[1] + (elm.offsetHeight/2 - this.img.offsetHeight/2) ) + "px"
				});
		}
		
		this.bshow = true;
	},
	
	hide: function()
	{
		
		if (this.img) {
			Element.setStyle(this.img, "display", "none");
		}
		
		if (this.shadow) {
			Element.setStyle(this.shadow, "display", "none");
		}
		
		this.bshow = false;
	},
	
	getLoadGrafic: function()
	{
		return this.gfx;
	},
	
	setLoadGrafic: function(gfx)
	{
		this.gfx = gfx;
	}
	
});


var Helper = new Object();

Object.addElements(Helper,
	{
		setFilter: function(elm, filter, value)
		{			
			this.removeFilter(elm, filter);
			elm.style.filter += " " + filter + "(" + value + ")";
		},
		
		removeFilter: function(elm, filter)
		{
			if (!elm.style.filter)
				return false;
			
			var rg = new RegExp(filter+"\\([^\\)]*\\)","gi");
			var f = elm.style.filter.replace(rg,'');
			
			if (!f) {
				elm.style.filter = null;
			}
			else
			{
				elm.style.filter = f;
			}
		},
		
		getClientSize: function()
		{
			var h=600,w=800;
			
			if (window.innerHeight)
			{
				h = window.innerHeight - 2;
				w = window.innerWidth - 20;
			}
			else if (document.documentElement) 
			{
				h = document.documentElement.clientHeight;
				w = document.documentElement.clientWidth;
			}
			
			return [w,h];
		},
		
		isArray: function(data)
		{
			return typeof data == "object" && data.constructor == Array;
		},
		
		isUndef: function(data)
		{
			return typeof data == "undefined";
		},
		
		equals: function(s, d)
		{
			if (typeof s != typeof d) {
				return false;
			}
			else
			{
				if (typeof s == "object") {
					if (this.isArray(s) && this.isArray(d)) {
						if (s.length != d.length)
							return false;
						
						for (var i = 0; i < s.length; i++)
							if (s[i] !== d[i])
								return false;
						
						return true;
					}
				}
			}
			
			return s == d;
		}
	}
);


var Element = new Object();

Object.addElements(Element,
	{
		
		append: function(elm, parent)
		{
			parent.appendChild(elm);
			return elm;
		},
		
		insertBefore: function(elm, rel)
		{
			rel.parentNode.insertBefore(elm, rel);
			return elm;
		},
		
		insertAfter: function(elm, rel)
		{
			if (rel.nextSibling) {
				Element.insertBefore(elm, rel.nextSibling);
			}
			else
			{
				Element.append(elm, rel.parentNode);
			}
			
			return elm;
		},
		
		appendFirst: function(elm, parent)
		{
			if (!parent) {
				return null;
			}

			if (parent.childNodes.length == 0) {
				Element.append(elm, parent);
			}
			else
			{
				Element.insertBefore(elm, parent.childNodes[0]);
			}
			
			return elm;
		},
		
		text: function(text)
		{
			return document.createTextNode(text);
		},
		
		newElement: function(elm, props, style)
		{
			var e = document.createElement(elm);
			
			if (props) {
				for (it in props) {
					if (typeof props[it] == "string" || typeof props[it] == "number")
						e[it] = props[it];
				}
			}
			
			if (style) {
				this.setStyle(e, style);
			}
			
			return e;
		},
		
		newMenu: function(list) {
			var alist;
			
			for (var i = 0; i < list.length; i++) {
				alist.push(this.newElement("a",list[i]));
			}
			
			return Element.createList(alist);;
		},
		
		createList: function(list)
		{
			var ul = document.createElement("ul");
			var li;
			var a;
			
			for (var i = 0; i < list.length; i++) {
				li = document.createElement("li");
				if (typeof list[i] == "object") {
					li.appendChild(list[i]);
				}
				else
				{
					li.appendChild(Element.text(list[i]));
				}
				
				ul.appendChild(li);
			}
			
			return ul;
		},
		
		realOffset: function(elm) {
			if (!elm.parentNode)
				return [elm.scrollLeft || 0, elm.scrollTop || 0];
			
		    var ro = this.realOffset(elm.parentNode);
		    return [elm.scrollLeft+ro[0], elm.scrollTop+ro[1]];
		},
		
		absPosition: function(elm)
		{
			if (!elm.offsetParent)
				return [elm.offsetLeft || 0, elm.offsetTop || 0];
			
			var pp = this.absPosition(elm.offsetParent);
			return [elm.offsetLeft+pp[0], elm.offsetTop+pp[1]];
		},
		
		insertRelative: function(elm, parent, x, y, r)
		{
			//$("b").innerHTML=(x + "," + y) + "<br />";
			for (var i = 0; i < parent.childNodes.length; i++)
			{
				if (this.hitTest(parent.childNodes[i], x, y))
				{
					var node = parent.childNodes[i];
					var p = this.absPosition(node);
					
					
					//$("b").innerHTML += ( + (node.offsetWidth / 2)) + ":";
					if (x < p[0] + node.offsetWidth / 2) {
						if (r == node)
							return node;
						
						parent.insertBefore(elm, node);
					}
					else
					{
						node = node.nextSibling;
						if (node == null) {
							parent.appendChild(elm);
						}
						else
						{
							if (node == r)
								return r;
							parent.insertBefore(elm, node);
						}
					}
					
					return node;
				}
			}
						
			return null;
		},
		
		hitTest: function(elm, x, y)
		{
			var p = this.absPosition(elm);
			
			return (x >= p[0] && x <= (p[0] + elm.offsetWidth) && y >= p[1] && y <= (p[1] + elm.offsetHeight));
		},
		
		remove: function(elm)
		{
			if (!elm || !elm.parentNode)
				return;
				
			if (elm._alpha_clone) {
				Element.remove(elm._alpha_clone);
			}
			
			elm.parentNode.removeChild(elm);
			return elm;
		},
		
		//Werden gebraucht, da der IE und FF für manche Styles verschiedene Namen haben
		setStyle: function(elm, style, value)
		{
			if (typeof style == "object") {
				for (it in style) {
					if (typeof style[it] == "string" || typeof style[it] == "number") {
						this.setStyle(elm, it, style[it]);
					}
				}
				return elm;
			}
			
			switch (style)
			{
			case "float":
				if(/MSIE/.test(navigator.userAgent))
					elm.style["styleFloat"] = value;
				else
					elm.style["cssFloat"] = value;
				break;
			
			case "opacity":
				this.setOpacity(elm,value);
				break;
			
			case "display":
				if (value == "none" && elm._alpha_clone) {
					
					elm._alpha_clone.style.visibility = "visible";
					elm._alpha_clone.style.display = "none";
				}
			
			default:
				elm.style[style]=value;
			}
			
			return elm;
		},
		
		getStyle: function(elm, style)
		{
			switch (style)
			{
			case "float":
				if(/MSIE/.test(navigator.userAgent))
					return elm.style["styleFloat"];
				else
					return elm.style["cssFloat"];
				break;
			
			case "opacity":
				return elm.__opacity;
				break;
			
			default:
				return elm.style[style];
			}
		},
		
		getStyle2: function (elm, style){
			var ret;
			
			if(elm.currentStyle) {
				style = style.replace(/\-(\w)/g, function (m, p) { return p.toUpperCase(); });
				ret = elm.currentStyle[style];
			}
			else if(window.getComputedStyle)
			{
				ret = window.getComputedStyle(elm, "").getPropertyValue(style);
			}
			
			return ret;
		},

		
		setOpacity: function(elm,value)
		{
			elm.__opacity = value;
			if (value == 1) {
				if(/MSIE/.test(navigator.userAgent)) {
					Helper.removeFilter(elm, "alpha");
					
					if (elm.nodeName != "div" && elm.style.display != "block") {
						
						if (elm._alpha_clone && typeof elm._alpha_pos != "undefined") {
							elm.style.position = elm._alpha_pos ? elm._alpha_pos : "";
							elm._alpha_pos = null;
							elm.parentNode.insertBefore(elm, elm._alpha_clone);
							elm._alpha_clone.style.display = "none";
							elm._alpha_clone.style.position = "absolute";
							elm.style.visibility = "visible";
						}
					}
				}
				else
				{
					elm.style.opacity=null;
				}
			}
			else
			{
				value = value < 0.0001 ? 0 : value;
				
				if(/MSIE/.test(navigator.userAgent)) {
					Helper.setFilter(elm, "alpha", "opacity="+(value*100));
					
					//Transparenz geht nur mit hasLayout Elementen...
					if (elm.currentStyle && elm.currentStyle.hasLayout) {
						return;
					}
					else if (elm.nodeName == "div" || elm.style.display == "block")
					{
						if (!elm.style.height && !elm.style.width && elm.style.position != "absolute") {
							elm.style.height = "1%";
						}
					}
					else
					{
						var c;
						
						if (!elm.parentNode) {
							return;
						}
						
						if (elm._alpha_clone) {
							c = elm._alpha_clone;
						}
						else
						{
							c = elm.cloneNode(true);
						}
						
						if (elm.nextSibling) {
							elm.parentNode.insertBefore(c, elm.nextSibling);
						}
						else
						{
							elm.parentNode.appendChild(c);
						}
						
						if (typeof elm._alpha_pos == "undefined") {
							elm._alpha_pos = elm.style.position;
						}
						
						elm.style.position = "absolute";
						c.id = "";
						c.style.display = "";
						c.style.visibility = "hidden";
						elm._alpha_clone = c;
					}
				}
				else
				{
					elm.style.opacity=value;
				}
			}
		},
		
		getOpacity: function(elm)
		{
			if (elm.style.opacity)
			{
				return elm.style.opacity;
			}
			else if(elm.style.filter) //Internet Explorer
			{
				var m = elm.style.filter.match(/alpha\(opacity=(.*)\)/i);
				return m[1] ? parseFloat(m[1] / 100) : 1.0;
			}
			
			return 1.0;
		}
	}
);

var CSS = new Object();

Object.addElements(CSS,
	{
		getClasses: function(element)
		{
			return element.className.split(" ");
		},
		
		classExists: function(element,className)
		{
			var classes=false;
			
			if (typeof element.className != 'undefined') {
				element=element.className.split(" ");
			}
			
			if (typeof element == 'string')
			{
				classes=element.split(" ");
			}
			else if (typeof element == 'object')
			{
				classes=element;
			}
			else
			{
				return false;
			}
			
			return classes.isIn(className);
		},
		
		//Klasse hinzufügen
		addClass: function(element,className)
		{			
			if (typeof element.className == 'undefined') {
				return false;
			}
			
			if (!this.classExists(element,className)) {				
				if (element.className=="") {
					element.className=className;
				}
				else
				{
					element.className+=" "+className;
				}
			}
			
			return element;
		},
		
		//Klasse rauswerfen
		removeClass: function(element,className)
		{
			if (typeof element.className == 'undefined') {
				return false;
			}
			
			if (this.classExists(element,className)) {
				element.className=element.className.split(" ").without(className).concatString(" ");
			}
			
			return element;
		}
	}
);

//Effekte
var runningQueue = new Array();


var Effects = {
	_: function(elm,s) {
		var f=false;
		var e=false;
		
		if (!elm)
			return false;
		
		if (typeof s != "undefined" && s) {
			e = new Effect();
			e.elm = elm;
			e.opts = {};
		}
				
		e = elm._effect;
		
		if (e)
			return e;
		
		e = new Effect();
		e.elm = elm;
		e.opts = {};
		
		elm._effect = e;
				
		return e;
	},
	
	clearQueue: function(elm)
	{
		elm.queue = new Array();
	},
	
	getOpts: function(elm)
	{
		return elm._effect.opts;
	}
};


var Effect = new Object(function() { });

Object.addElements(Effect.prototype, {
	elm:false,
	interval:false,
	startTime:0,
	id:0,
	bStart:false,
	
	queue:new Array(),
	
	opts: false,
	
	jump: function(opts)
	{
		var from;
		
		opts=this.prepare(opts);
		
		if (typeof opts.from == "object" && typeof opts.from.length!="undefined" && opts.from.length>=2) {
			from=opts.from;
		}
		else
		{
			from=new Array(parseInt(this.elm.style.marginTop ? this.elm.style.marginTop : 0),parseInt(this.elm.style.marginBottom ? this.elm.style.marginBottom : 0));
		}
		
		this.elm._effect.queue.push({
			effect:this.jump_.bind(this),
			from:from,
			to:parseInt(opts.to),
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update
		});


		if (opts.start) {
			this.start();
		}
		
		return this;
	},
	
	fnc: function(cb, opts)
	{
		opts = this.prepare(opts,true);
		
		this.elm._effect.queue.push({
			effect:cb.bind(this),
			opts:opts,
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update,
			from:opts.from,
			to:opts.to
		});

		if (opts.start) {
			this.start();
		}
		
		return this;
	},
	
	blink: function(opts)
	{
		opts.blink=true;
		opts.from=this.elm.style.backgroundColor ? this.prepareColor(this.elm.style.backgroundColor) : "ffffff";

		this.opts.startColor = this.prepareColor(this.elm.style.backgroundColor);
		
		if (!opts.to)
			opts.to="ffff99";
		if (!opts.duration)
			opts.duration=500;
			
		if (opts.swap) {
			var tmp = opts.to;
			opts.to = opts.from;
			opts.from = tmp;
			opts.blink=false;
		}
		
		return this.changeColor(opts);
	},
	
	changeColor: function(opts)
	{
		
		opts=this.prepare(opts);
		
		this.elm._effect.queue.push({
			effect:this.changeColor_.bind(this),
			from:this.prepareColor(opts.from),
			to:this.prepareColor(opts.to),
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update,
			blink:opts.blink
		});


		if (opts.start) {
			this.start();
		}
		
		return this;
	},
	
	hide: function(opts)
	{
		
		if (!opts) {
			opts = {};
		}
		
		if (typeof opts.to == "undefined") {
			opts.to=0;
		}
		if (typeof opts.from == "undefined") {
			opts.from=1;
		} 
		
		opts=this.prepare(opts);
		
		this.elm._effect.queue.push({
			effect: this.opacity_.bind(this),
			from: opts.from,
			to: opts.to,
			duration: opts.duration,
			obj: this.elm,
			after: opts.after,
			before: opts.before,
			update:opts.update
		});


		if (opts.start) {
			this.start();
		}
		
		return this;
	},
	
	resize: function(opts)
	{
		var from,to;
		
		opts=this.prepare(opts);
		if (!opts)
			return false;
		
		from=opts.from.split("x");
		to=opts.to.split("x");
		
		if (isNaN(from[0])) from[0] = 0;
		if (isNaN(from[1])) from[1] = 0;
		
		if (from.length<2 || to.length<2) {
			return false;
		}
		
		this.elm._effect.queue.push({
			effect:this.resizeX_.bind(this),
			from:parseInt(from[0]),
			to:parseInt(to[0]),
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update
		});
		
		this.elm._effect.queue.push({
			effect:this.resizeY_.bind(this),
			from:parseInt(from[1]),
			to:parseInt(to[1]),
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update
		});
		
		if (opts.start) {
			this.start();
		}
		
		return this;
	},
	
	move: function(opts)
	{
		var from,to;
		
		opts=this.prepare(opts);
		if (!opts)
			return false;
		
		from=opts.from.split("x");
		to=opts.to.split("x");
		
		if (from.length<2 || to.length<2) {
			return false;
		}
		
		this.elm._effect.queue.push({
			effect:this.moveX_.bind(this),
			from:parseInt(from[0]),
			to:parseInt(to[0]),
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update
		});
		
		this.elm._effect.queue.push({
			effect:this.moveY_.bind(this),
			from:parseInt(from[1]),
			to:parseInt(to[1]),
			duration:opts.duration,
			obj:this.elm,
			after:opts.after,
			before:opts.before,
			update:opts.update
		});
		
		if (opts.start) {
			this.start();
		}
		
		return this;
	},
	
	prepare: function(opts,skipFrom)
	{
		if (typeof skipFrom == "undefined" || !skipFrom) {
			if (typeof opts.from == 'undefined' &&
					typeof opts.to == 'undefined') {
				return false;			
			}
		}
		
		if (typeof opts.duration == 'undefined') {
			opts.duration = 1000;
		}
		
		if (typeof opts.start == 'undefined') {
			opts.start = true;
		}
		
		return opts;
	},
	
	
	prepareColor: function(color)
	{
		
		if (typeof color == "number")
			return color;
		
		if (color.substr(0,1)=="#")
			color=color.substr(1);
		
		
		if (color.substr(0,4)=="rgb(") {
			color=color.substr(4,color.length-5);
			color=color.split(",");
			color=parseInt(color[0]).fH()+parseInt(color[1]).fH()+parseInt(color[2]).fH();
		}
		
		//Farbwert?
		if (isNaN("0x"+color)) {
			return false;
		}
		
		if (color.length==3)
			color=color.substr(0,1).repeat(2)+color.substr(1,1).repeat(2)+color.substr(2,1).repeat(2);
		else if(color.length!=6)
			return false;
			
		return parseInt("0x"+color);
	},
	
	
	start: function()
	{
		//Start...
		if (this.bStart==true) {
			return;
		}
		
		this.startTime = new Date().getTime();
		
		this.queue.each(function (obj,idx) {
			if (typeof obj.before == "function") {
				obj.before(obj);
				obj.before = false;
			}
		});
				
		this.bStart=true;
		this.interval = setInterval(this.loop.bind(this),40);
	},
	
	stop: function()
	{
		this.bStart=false;
		clearInterval(this.interval);
		
		if (typeof this.opts.startColor != "undefined" && this.opts.startColor != null) {
			if (this.opts.startColor === false) {
				this.elm.style.backgroundColor = "";
			}
			else
			{
				this.elm.style.backgroundColor = this.opts.startColor;
			}
		}
		
		this.opts.startColor = null;
	},
	
	loop: function()
	{
		var now = new Date().getTime();
		var fC = 0, time = this.startTime;
		
		this.elm._effect.queue.each(function (obj,idx) {
			var pos=(now-time) / (obj.duration);
			
			if (obj.finished) {
				fC++;
				return
			}

			if (now>time+obj.duration) {
				fC++;
				obj.effect(1,obj);
				obj.finished=true;
				
				if (typeof obj.after == "function") {
					obj.after(obj);
				}
				return;
			}
			
			obj.effect(pos,obj);
			if (typeof obj.update == "function") {
				obj.update(obj);
			}
			
		}.bind(this));
		
		if (fC>=this.queue.length) {
			this.stop();
			this.queue.each(function (obj,idx) {
				if (!obj.finished) {
					obj.effect(1,obj);
				}
			});
			
			this.elm._effect.queue = new Array();
			
			Effects.clearQueue(this.elm);
			
			runningQueue = runningQueue.without(this);
		}
	},
	
	clearQueue: function()
	{
		this.elm._effect.queue = new Array();
		Effects.clearQueue(this.elm);
	},
	
	changeColor_: function(pos,obj)
	{
		if (obj.blink)
			pos=Math.sin(pos*Math.PI/2).toFixed(2);

		obj.obj.style.backgroundColor="#"+( (obj.from >> 16 & 0xff) + parseInt( ( (obj.to >> 16 & 0xff)-(obj.from >> 16 & 0xff) )*pos)).toColorPart()+
								((obj.from >> 8 & 0xff)+parseInt(((obj.to >> 8 & 0xff)-(obj.from >> 8 & 0xff))*pos)).toColorPart()+
								((obj.from >> 0 & 0xff)+parseInt(((obj.to >> 0 & 0xff)-(obj.from >> 0 & 0xff))*pos)).toColorPart();
	},
	
	opacity_: function(pos,obj)
	{
		Element.setStyle(obj.obj, "opacity", obj.from+(obj.to-obj.from)*pos);
	},
	
	jump_: function(pos,obj)
	{
		obj.obj.style.marginBottom=parseInt(obj.from[1]+(obj.to+obj.from[0])*Math.sin(pos*Math.PI).toFixed(2))+"px";
		obj.obj.style.marginTop=parseInt(obj.from[0]-(obj.to+obj.from[0])*Math.sin(pos*Math.PI).toFixed(2))+"px";
	},
	
	resizeX_: function(pos,obj)
	{
		obj.obj.style.width=parseInt(obj.from+(obj.to-obj.from)*pos)+"px";
	},
	
	resizeY_: function(pos,obj)
	{
		obj.obj.style.height=parseInt(obj.from+(obj.to-obj.from)*pos)+"px";
	},
	
	moveX_: function(pos,obj)
	{
		obj.obj.style.left=parseInt(obj.from+(obj.to-obj.from)*pos)+"px";
	},
	
	moveY_: function(pos,obj)
	{
		obj.obj.style.top=parseInt(obj.from+(obj.to-obj.from)*pos)+"px";
	}
	
});


// Funktionshandler
Object.addElements(Event,
	{
		addHandler: function(name,element,callback)
		{
			if (element.attachEvent) {
				element.attachEvent("on"+name,callback);
			}
			else if (element.addEventListener)
			{
				element.addEventListener(name,callback,false);
			}
		},
		
		element: function(e)
		{
			return e.target ? e.target : e.srcElement;
		},
		
		stop: function(e)
		{
			if (e.preventDefault) {
				e.preventDefault();
				e.stopPropagation();
			}
			else
			{
				e.returnValue = false;
				e.cancelBubble = true;
			}
		},
		
		removeHandler: function(name, element, callback)
		{
			if (element.removeEventListener) {
				element.removeEventListener(name, callback, false);
			}
			else if (element.detachEvent)
			{
				element.detachEvent(name, callback);
			}
		},
		
		x: function(event)
		{
			return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
		},
		
		y: function(event)
		{
			return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
		},
		
		position: function(event)
		{
			return [this.x(event), this.y(event)];
		},
		
		xp: function(event)
		{
			return event.offsetX ? event.offsetX : event.layerX;
		},
		
		yp: function(event)
		{
			return event.offsetY ? event.offsetY : event.layerY;
		}
		
	}
);


//Auflistungen - Enumerationen
var CEnum = {
	
	//Alle Elemente durchlaufen
	each: function(iterator) {
		var l=0;
		
		if (typeof this.length == 'function')
		{
			l=this.length();
		} 
		else if (typeof this.length == 'number')
		{
			l=this.length;
		}
		else
		{
			return false;
		}
		
		for (var i=0; i<l; i++) {
			if (iterator(this[i],i) === false) {
				return;
			}
		}
	},
	
	//Ist ein Wert vorhanden?
	isIn: function(data) {
		for (var i=0; i<this.length; i++) {
			if (this[i]==data) {
				return true;
			}
		}
		return false;
	},
	
	//Alle Ergebnisse in Array Speichern
	all: function(iterator) {
		var ret = new Array();
		var val;
		
		this.each(function(obj,idx) {
			val=iterator(obj,idx);
			if (val!=null)
				ret.push(iterator(obj,idx));
		});
		
		return ret;
	},
	
	//Größtes Element
	max: function() {
		var max;
		
		if (this.length==0)
			return false;
		else
			max=this[0];
		
		this.each(function (obj,idx) { max=obj>max?obj:max; });
		
		return max;
	},
	
	//Kleinstes Element
	min: function() {
		var min;
		
		if (this.length==0)
			return false;
		else
			min=this[0];
		
		this.each(function (obj,idx) { min=obj<min?obj:min; });
		
		return min;
	},
	
	//Erstes Element
	first: function() {
		if (this.length==0)
			return false;
		else
			return this[0];
	},
	
	//Letztes Element
	last: function() {
		if (this.length==0)
			return false;
		else
			return this[this.length-1];
	},
	
	//Nur Elemente anhängen bei denen iterator true zurückgibt
	which: function(iterator) {
		var ret=new Array();
		
		this.each(function (obj,idx) { if (iterator(obj,idx)) ret.push(obj); });
		
		return ret;
	},
	
	//Solange bis iterator false zurückgibt Elemente anhängen
	until: function(iterator) {
		var ret=Array();
		var fbreak=false;
		
		this.each(function (obj,idx)
		{
			if (!fbreak && iterator(obj,idx))
				ret.push(obj);
			else
				fbreak=true;
		});
		
		return ret;
	},
	
	//Alle Elemente, auser
	without: function(data) {
		var ret=new Array();
		
		this.each(function (obj) { if (obj!=data) ret.push(obj); });
		
		return ret;
	},
	
	//Alle Elemente > number
	gt: function(number) {
		var ret=new Array();
		
		this.each(function (obj,idx) { if (typeof obj == 'number' && obj>number) ret.push(obj); });
		
		return ret;
	},
	
	//Alle Elemente < number
	lt: function(number) {
		var ret=new Array();
		
		this.each(function (obj,idx) { if (typeof obj == 'number' && obj<number) ret.push(obj); });
		
		return ret;
	},
	
	//Alle Elemente mit value Eigenschaft durchsuchen und schauen ob etwas darin steht
	areEmpty: function() {
		var ret=new Array();
		
		this.each(function (obj,idx) { if (typeof obj.value != 'undefined' && !obj.value) ret.push(obj);});
		
		return ret;
	},
	
	//unterstützt die getAttribute Funktion und besitzt ein bestimmtes Attribut (evtl. auch mit dem Wert(value)
	withAttribute: function(attribute,value) {
		var ret=new Array();
		var found=false;
		var args = arguments;
		
		this.each(function (obj,idx) {
			
			if (obj.getAttribute) {
				if (obj.getAttribute(attribute)!=null) {
					if (args.length == 2) {
						if (!value || value==obj.getAttribute(attribute)) {
							ret.push(obj);
						}
					}
					else
					{
						found=false;
						
						for (var i=1; i<args.length; i++) {
							if (args[i]==obj.getAttribute(attribute)) {
								found=true;
								break;
							}
						}
						if (found) {
							ret.push(obj);
						}
					}
				}
			}
			
		});
		
		return ret;
	},
	
	subarray: function (start,length) {
		var ret=new Array();
		
		if (typeof start == 'undefined') { 
			start=0;
		}
		
		if (typeof length == 'undefined') {
			if (start<0) {
				length=start;
			}
			else
			{
				length=this.length-start;
			}
		}
		
		for (var i=start;i<start+Math.abs(length); i++) {
			if (typeof this[i] != 'undefined') {  
				ret.push(this[i]);
			}
		}
		
		return ret;
	},
	
	//Alle Elemente die toString unterstützen oder Strings sind aneinander reihen
	concatString: function(separator,iterator) {
		var ret="";
		
		this.each(function (obj,idx) {
			if (idx>0 && typeof separator != 'undefined') {
				ret+=separator;
			}
			
			if (typeof obj == 'string') {
				if (iterator) {
					if (iterator(obj,idx))
						ret+=obj;
				}
				else
				{
					ret+=obj;
				}
			} else if (obj.toString) {
				if (iterator) {
					if (iterator(obj,idx))
						ret+=obj.toString();
				}
				else
				{
					ret+=obj.toString();
				}
			}
		});
		
		return ret;
	}
};

//Array Enumeration hinzufügen
Object.addElements(Array.prototype,CEnum);

Object.addElements(String.prototype, {
	repeat: function(count) {
		var ret=String();
		var str=this;
		
		count.times(function() {
			ret=ret+str;
		});
		
		return ret;
	},
	
	strip: function(len)
	{
		if (!len) {
			len = 20;
		}
		
		if (this.length > len) {
			return this.substr(0,len-3) + "...";
		}
		
		return this;
	}
});

Object.addElements(Number.prototype, {
	times: function(iterator) {
		for (var i=0; i<this; i++) {
			iterator(i+1);
		}
	},
	
	toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },
	
	fH: function(l) {		
		return this.f(l,16);
	},
	
	fD: function(l) {		
		return this.f(l,10);
	},
	
	fO: function(l) {		
		return this.f(l,8);
	},
	
	fB: function(l) {		
		return this.f(l,2);
	},
	
	f: function(l,b) {
		if (!b) {
			b=10;
		}
		
		var ret=this.toString(b);

		for (var i=0; i < l; i++) {
			if (this < Math.pow(b,i))
				ret="0"+ret;
		}
		
		return ret;
	}
	
});

//Element bzw. Elemente mit der Id/s zurückgeben
function $() {
	if (arguments.length == 1)
		return document.getElementById(arguments[0]);
		
	var elms=new Array();
	
	for (var i=0; i<arguments.length; i++)
		elms[i]=$(arguments[i]);
	
	return elms;
}

//Alle Element mit einem bestimmten Namen zurückgeben
function $$()
{
	var elms;
	var ret=new Array();
	
	for (var i=0; i<arguments.length; i++) {
		elms=document.getElementsByName(arguments[i]);
		
		for (var i=0; i<elms.length; i++)
			ret[i]=elms[i];
	}
	
	return ret;
}

//ALle Elemente mit einem bestimmten Tag zurückgeben
function $t()
{
	var p = document;
	
	if (arguments.length == 1) {
		return collectionToArray(document.getElementsByTagName(arguments[0]));
	}
	else if(arguments.length >= 2)
	{
		if (typeof arguments[0] == "object") {
			arguments = collectionToArray(arguments);
			p = arguments.shift();
			if (arguments.length == 1) {
				return collectionToArray(p.getElementsByTagName(arguments[0]));
			}
		}
	}
	
	var elms=new Array();
	
	for (var i=0; i<arguments.length; i++) {
		
		elms = elms.concat($t(p, arguments[i]));
	}
	
	return elms;
}


function $p(o,c) {
	if (c && typeof c == "number" && c!=0) {
		return $p(o.parentNode, c-1);
	}
	return o.parentNode;
}

var $C = document.getElementsByClassName = function(className,parent) {
	return collectionToArray((typeof parent != 'undefined' ? parent : document).getElementsByTagName("*")).all(function (obj) {
		return (CSS.classExists(obj,className) ? obj : null);
	});
};

var collectionToArray = $A = function(collection)
{
	var ret=new Array();
	var it;

	if (collection.length) {
		
		for (var i=0; i<collection.length; i++) {
			ret.push(collection[i]);
		}
	}
	else if (collection.iterateNext) {
		while (it = collection.iterateNext()) {
			ret.push(it);
		}

}
	else
	{
		for (elm in collection) {
			ret[elm]=collection[elm];
			ret.push(collection[elm]);
		}
	}
	
	return ret;
};


Object.addElements(Function.prototype,
	{
		bind: function() {
			var __method = this, args = $A(arguments), object = args.shift();
			
			return function() {
				return __method.apply(object, args.concat($A(arguments)));
			};
		},
		
		bindEvent: function() {
			var __method = this, args = $A(arguments), object = args.shift();
			
			return function(event) {
				return __method.apply(object, [event || window.event].concat(args));
			};
		}
	}
);


function styleSheets()
{
	var styles=collectionToArray(document.styleSheets);
	
	styles.each(function (obj,idx) {

		obj.getRules=function () {		
			return collectionToArray(typeof this.cssRules != 'undefined' ? this.cssRules : this.rules);
		};
	});
	
	return styles;
}

//Array Enumeration hinzufügen
Object.addElements(Object.prototype,
	{
		toArray: function() {
			if (this.length) {
				
				var array=new Array();
			
				for (var i=0;i<this.length;i++) {
					array[i]=this[i];
				}
				
				return array;
			}
			return false;
		}
	}
);

function addOnLoadHandler(handler)
{
	Event.addHandler("load",window,handler);
}
