/**
 * A compact JavaScript-Helper Libary for Cross Browser Scripting
 * Used for twoday
 *
 * Written by Matthias Platzer at http://knallgrau.at
 * (c) 2005
 * inspired by code found at various places in the net
 * especially by HTMLArea by Mihai Bazon http://students.infoiasi.ro/~mishoo
 * and Tim Taylor http://tool-man.org/
 *
 * use it as you need it
 */

var jsLibDebug;
function _gel(id) { return document.getElementById(id); }
String.prototype.lc = String.prototype.toLowerCase;
String.prototype.uc = String.prototype.toUpperCase;
String.prototype.trim = function () {
   return this.replace(/(^\s*)|(\s*$)/g, "");
}

function addEvent(el, evname, func) {
  if (el.attachEvent) el.attachEvent("on" + evname, func);
  else el.addEventListener(evname, func, true);
}

function stopEvent(evt) {
  if (evt.preventDefault) {
    evt.preventDefault();
    evt.stopPropagation();
  } else {
    evt.cancelBubble = true;
    evt.returnValue = false;
  }
}

function removeEvent(el, evname, func) {
	if (el.detachEvent) el.detachEvent("on" + evname, func);
	else el.removeEventListener(evname, func, true);
}

function removeClass(el, className) {
	if (!(el && el.className)) return;

	var cls = el.className.split(" ");
	var ar = new Array();
	for (var i = cls.length; i > 0;) {
		if (cls[--i] != className) {
			ar[ar.length] = cls[i];
		}
	}
	el.className = ar.join(" ");
}

function addClass(el, className) {
	// remove the class first, if already there
	removeClass(el, className);
	el.className += " " + className;
}

function hasClass(el, className) {
	if (!(el && el.className)) return false;

	var cls = el.className.split(" ");
	for (var i = cls.length; i > 0;) {
		if (cls[--i] == className) return true;
	}
	return false;
}

function hitTest (ele1, ele2) {
	if (getAbsOffsetLeft(ele1)+ele1.offsetWidth<getAbsOffsetLeft(ele2)) return false;
	if (getAbsOffsetTop(ele1)+ele1.offsetHeight<getAbsOffsetTop(ele2)) return false;
	if (getAbsOffsetLeft(ele2)+ele2.offsetWidth<getAbsOffsetLeft(ele1)) return false;
	if (getAbsOffsetTop(ele2)+ele2.offsetHeight<getAbsOffsetTop(ele1)) return false;
	return true;
}

function isUnderMouse (evt, ele) {
  evt = evt ? evt : window.event;
  var sl = (window.pageXOffset ? window.pageXOffset : (document.documentElement && document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft);
  var st = (window.pageYOffset ? window.pageYOffset : (document.documentElement && document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop);

	var x = (evt.clientX + sl);
	var y = (evt.clientY + st);
	if (x<getAbsOffsetLeft(ele)) return false;
	if (y<getAbsOffsetTop(ele)) return false;
	if (x>getAbsOffsetLeft(ele)+ele.offsetWidth) return false;
	if (y>getAbsOffsetTop(ele)+ele.offsetHeight) return false;
	return true;
}

function getAbsOffsetTop(ele) {
  var offset = 0;
  var st = (window.pageYOffset ? window.pageYOffset : (document.documentElement && document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop);
  do { offset += ele.offsetTop; if (window.getComputedStyle && window.getComputedStyle(ele, "").getPropertyValue("position")=="fixed") { offset+=st }; ele = ele.offsetParent; } while (ele!=null)
  return offset;
}

function getAbsOffsetLeft(ele) {
  var offset = 0;
  var sl = (window.pageXOffset ? window.pageXOffset : (document.documentElement && document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft);
  do { offset += ele.offsetLeft; if (window.getComputedStyle && window.getComputedStyle(ele, "").getPropertyValue("position")=="fixed") { offset+=sl }; ele = ele.offsetParent; } while (ele!=null)
  return offset;
}


// Array functions
Array.contains = function(arr, el) {
  for (var i=0; i<arr.length; i++) {
    if (arr[i] == el) return i;
  }
  return false;
}

// Cookie Functions
function ClientCookie() {
	if (document.cookie.length) { this.cookies = ' ' + document.cookie; }
}

ClientCookie.prototype.setCookie = function (key, value) {
	document.cookie = key + "=" + escape(value);
}

ClientCookie.prototype.getCookie = function (key) {
	if (this.cookies) {
		var start = this.cookies.indexOf(' ' + key + '=');
		if (start == -1) { return null; }
		var end = this.cookies.indexOf(";", start);
		if (end == -1) { end = this.cookies.length; }
		end -= start;
		var cookie = this.cookies.substr(start,end);
		return unescape(cookie.substr(cookie.indexOf('=') + 1, cookie.length - cookie.indexOf('=') + 1));
	}
	else { return null; }
}

// html dom functions

function getChildren(item, nodeName, className) {
  if (item == null) return [];
  var result = [];
  for (var c = 0; c<item.childNodes.length; c++) {
    if ((nodeName == "*" && item.childNodes[c].nodeType == 1) || item.childNodes[c].nodeName.lc() == nodeName.lc()) {
      if (!className || hasClass(item.childNodes[c], className)) result.push(item.childNodes[c]);
    }
  }
  return result;
}

function getParentElement(item, nodeName, className) {
  if (item == null) return null;
  var parent = item.parentNode;
  while (parent != null) {
    if ((nodeName == "*" && parent.nodeType == 1) || parent.nodeName.lc() == nodeName.lc()) {
      if (!className || hasClass(parent, className)) return parent;
    }
    parent = parent.parentNode;
  }
  return null;
}

function getNextElement(item, nodeName, className) {
  if (item == null) return null;
  var next = item.nextSibling;
  while (next != null) {
    if ((nodeName == "*" && next.nodeType == 1) || next.nodeName.lc() == nodeName.lc()) {
      if (!className || hasClass(next, className)) return next;
    }
    next = next.nextSibling;
  }
  return null;
}

function getPreviousElement(item, nodeName, className) {
  var previous = item.previousSibling;
  while (previous != null) {
    if ((nodeName == "*" && previous.nodeType == 1) || previous.nodeName.lc() == nodeName.lc()) {
      if (!className || hasClass(previous, className)) return previous;
    }
    previous = previous.previousSibling;
  }
  return null;
}

function moveBefore(item1, item2) {
  var parent = item1.parentNode;
  parent.removeChild(item1);
  parent.insertBefore(item1, item2);
}

function moveAfter(item1, item2) {
  var parent = item1.parentNode;
  parent.removeChild(item1);
  parent.insertBefore(item1, item2 ? item2.nextSibling : null);
}

function newXmlRequest() {
  var r = null;
  try {
    r = new ActiveXObject("Msxml2.XMLHTTP");
    if (r) return r;
  } catch(a) {}

  try {
    r = new ActiveXObject("Microsoft.XMLHTTP");
    if (r) return r;
  } catch(b) {}

	try {
	  r = new XMLHttpRequest();
    if (r) return r;
  } catch(c) {}

  return r;
}

/**
 * Sends an AJAX request, after collecting all data from the orignal HTML tag
 * (form, or link) and writes the response to an ajaxContainer
 * (= parent div with class="ajaxContainer").
 * @example
 * <div class="ajaxContainer">
 * <form action="login" method="post" onsubmit="ajaxRequest(event, this)">
 *   <input name="username" /><input type="submit" value="go" />
 * </form>
 * <a href="register" onsubmit="ajaxRequest(event, this)">or do register</a>
 * </div>
 * @paramm evt  Event object
 * @paramm ele  form, submit or link
 * @paramm param (optional)
 *          .container      optional target element for response
 *                          may also be a function which is used as callFunction
 *          .callFunction   optional Function to be called onload
 *          .action         URL for request (must be comnined with .method)
 *          .method         GET|POST
 *          .data           named array of values to be send
 *          .body           alternative body (works just with method=POST)
 *          .isBodyUrlEncoded  specifies Content-Type in combination with .body
 */
function ajaxRequest(evt, ele, param) {
   evt = evt ? evt : window.event;
   if (!param) param = {};
   var container = param.container ? param.container : getParentElement(ele, "div", "ajaxContainer");

   var req = newXmlRequest();
   // check if ajax is supported
   if (req == null) return true;
   req.onreadystatechange = function() {
      // check if XMLHttpRequest is complete
      if (req.readyState == 4) {
				 if (jsLibDebug) alert("req.status:"+req.status);
         if (container) {
            if (req.status == 200) {
							 if (jsLibDebug) alert("req.responseText"+req.responseText);
               container.innerHTML = req.responseText;
            } else {
               container.innerHTML = "<div class=\"ajax-error\">";
               container.innerHTML += "Ein Fehler ist aufgetreten: " + req.statusText + " ";
               container.innerHTML = "</div>";
            }
         }
         if (param.callFunction) {
            param.callFunction(req);
         }
      }
   };

   var data = {};
   var body = null;
   var link;
   var form;
	 if (param.method != null && param.action != null) {
      var method = param.method;
      var action = param.action;

   } else if (ele && ele.tagName.lc() == "a") {
      // link
      link = ele;
      var method = "GET";
      var action = ele.getAttribute("href");

   } else {
      // submit a form
      form = (ele.tagName.lc() == "form") ? ele : getParentElement(ele, "form");
      var method = form.getAttribute("method").uc();
      var action = form.getAttribute("action");
	 }
	 if (param.data) {
		  data = param.data;
	 } else if (form) {
      // collect form data
      for (var i=0; i < form.elements.length; i++) {
         switch(form.elements[i].type) {
            case "text":
            case "hidden":
            case "password":
            case "textarea":
            case "select-one":
               data[form.elements[i].name] = form.elements[i].value;
               break;
            case "checkbox":
            case "radio":
               if (form.elements[i].checked) {
                  data[form.elements[i].name] = form.elements[i].value;
               }
               break;
            case "select-multiple":
               var options = form.elements[i].options;
               for (var j=0; j<options.length; j++) {
                  if (options[j].selected) {
                     data[form.elements[i].name] = options[j].value;
                  }
               }
               break;
         }
      }
   }

   var query = "";
   for (var i in data) {
      if (i == "toJSONString") continue;
      query += "&" + encodeURIComponent(i) + "=" + encodeURIComponent(data[i]);
   }

   if (container) {
      container.innerHTML = "<div class=\"ajax-waiting\">Daten werden gesendet ...</div>";
   }

   req.open(method, action, true);
   req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
	 if (param.body) {
      body = param.body;
			if (param.isBodyUrlEncoded)
         req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	 } else if (method.uc() == "POST") {
      body = query.substr(1);
      req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
   } else {
      action += query;
   }

   if (jsLibDebug == true) {
      alert("req.open("+method+", "+action+")");
      alert("body:" + body);
   }

   req.send(body);

   return false;
}


/**
 * Helper functions for showing/hidding form sections contained in divs
 * @example
 * <p><span id="prefsFontsToggle"></span></p>
 * <div id="prefsFonts">...</div>
 * <script type="text/javascript">
 * activateVisibilityToggle ("prefsFonts", {inactiveText: "[+] Details anzeigen", activeText: "[-] Details ausblenden"}, false);
 * </script>
*/
function VT(id, param) {
  this.id = id;
  this.reverse = (param.reverse === true);
  delete param.reverse;
  this.param = param;
  this.div = _gel(id);
  this.tgl = _gel(id + "Toggle");
  switch (this.tgl.nodeName.lc()) {
    case "input": this.type = "input"; break;
    case "select": this.type = "select"; break;
    default: this.type = "span";
  }

  switch (this.type) {
  case "input":
    addEvent(this.tgl, "click", function (evt) { var ele = evt.srcElement ? evt.srcElement : evt.target; var id = ele.getAttribute("for") ? ele.getAttribute("for") : ele.id; tV(id.substring(0, id.indexOf("Toggle"))); });
    break;
  case "select":
    addEvent(this.tgl, "change", function (evt) { var ele = evt.srcElement ? evt.srcElement : evt.target; tV(ele.id.substring(0, ele.id.indexOf("Toggle"))); });
    break;
  default:
    this.vC = "";
    this.vC += '<a href="javascript:tV(\'' + id + '\')" class="minus">' + param.activeText + '</a>';
    this.invC = "";
    this.invC += '<a href="javascript:tV(\'' + id + '\')" class="plus">' + param.inactiveText + '</a>';
    break;
  }
}

VT.prototype.toggle = function() {
  switch (this.type) {
  case "input":
    if (this.tgl.checked == !this.reverse) this.show();
    else this.hide();
    break;
  case "select":
    if ( ((","+this.param.activeOptionValue+",").indexOf(","+this.tgl.options[this.tgl.selectedIndex].value+",")!=-1)  == !this.reverse ) this.show();
    else this.hide();
    break;
  default:
     if ((this.div.style.display == "none") == !this.reverse) this.show();
     else this.hide();
     break;
  }
}

VT.prototype.show = function() {
  this.div.style.display = "block";
  if (this.type=="span") this.tgl.innerHTML = this.vC;
}

VT.prototype.hide = function() {
  this.div.style.display = "none";
  if (this.type=="span") this.tgl.innerHTML = this.invC;
}

var vTs = {};
function activateVisibilityToggle(id, param, visible) {
  var vT = new VT(id, param);
  vTs[id] = vT;
  if (vT.type=="input") vT.tgl.checked = (visible == !vT.reverse);
  if (vT.type=="select" && vT.param.activeOptionValue.indexOf(",")==-1) {
     for (var i=0; i<vT.tgl.options.length; i++) {
        if ((vT.tgl.options[i].value == vT.param.activeOptionValue) == !vT.reverse) vT.tgl.selectedIndex = i;
     }
  }
  if (visible) vT.show();
  else vT.hide();
}

function tV(id) {
  vTs[id].toggle();
}

// ToolTip Helper
var ttDiv = null;
var ttHiddenElements = [];
// add class styles for
// .tooltip-div {}
// .tooltip-trigger {}
function initToolTips() {
  if (_gel("ttDiv")) {
	  ttDiv = _gel("ttDiv");
  } else {
    ttDiv = document.createElement("div");
    document.body.appendChild(ttDiv);
  }
  ttDiv.id = "ttDiv";
  ttDiv.className = "tooltip-div";
  ttDiv.style.position = "absolute";
  ttDiv.style.display = "none";
  ttDiv.style.zIndex = 100;

  var elements = document.body.getElementsByTagName("*");
  for (var i = 0; i < elements.length; i++) {
    var ele = elements[i];
    if (hasClass(ele, "tooltip")) {
      var trigger = getChildren(ele,"*","tooltip-trigger")[0];
      var text = getChildren(ele,"*","tooltip-text")[0];
      if (text == null) text = _gel(ele.id + "-text");
      text.style.display = "none";
      addEvent(trigger, "mouseover", function (evt) {
        var sl = (window.pageXOffset ? window.pageXOffset : (document.documentElement && document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft);
        var st = (window.pageYOffset ? window.pageYOffset : (document.documentElement && document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop);
        var x = (evt.clientX + sl);
        var y = (evt.clientY + st);
        var windowWidth = (_gel("main") && document.body.offsetWidth == 0)
          ? (_gel("main").offsetWidth + getAbsOffsetLeft(_gel("main")))
          : (document.body.scrollWidth>document.body.offsetWidth)?document.body.scrollWidth:document.body.offsetWidth;
        var windowHeight = _gel("main")
          ? (_gel("main").offsetHeight + getAbsOffsetTop(_gel("main")))
          : (document.body.scrollHeight>document.body.offsetHeiht)?document.body.scrollHeight:document.body.offsetHeight;
        var ele = evt.srcElement ? evt.srcElement : evt.target;
        var p = getParentElement(ele, "*", "tooltip");
        var text = getChildren(p,"*","tooltip-text")[0];
        if (text == null) text = _gel(p.id + "-text");
        if (getChildren(ttDiv, "div", "tooltip-div-content").length > 0) {
          getChildren(ttDiv, "div", "tooltip-div-content")[0].innerHTML = text.innerHTML;
        } else {
          ttDiv.innerHTML = text.innerHTML;
        }
        ttDiv.style.display = "block";
        if (x + ttDiv.offsetWidth > windowWidth - 20) x = windowWidth - 20 - ttDiv.offsetWidth;
        if (y + ttDiv.offsetHeight + 20 > windowHeight) y = windowHeight - ttDiv.offsetHeight - 30;
        ttDiv.style.left = (x+20)+"px";
        ttDiv.style.top = (y+10)+"px";
        var selects = (document.all) ? document.getElementsByTagName("select") : [];
        for (var i=0;i<selects.length;i++) {
          if (hitTest (ttDiv, selects[i])) {
            selects[i].style.visibility = "hidden";
            ttHiddenElements.push(selects[i]);
          }
        }
      });
      addEvent(trigger, "mouseout", function (evt) {
        for (var i=ttHiddenElements.length-1;i>=0;i--) {
          ttHiddenElements[i].style.visibility = "visible";
        }
        ttDiv.style.display = "none";
      });
    }
  }
}
addEvent(window, "load", initToolTips);

var userAgent = navigator.userAgent.toLowerCase();
var isIE     = ((userAgent.indexOf("msie") != -1) && (userAgent.indexOf("opera") == -1));
var isOpera  = (userAgent.indexOf("opera") != -1);
var isMac     = (userAgent.indexOf("mac") != -1);
var isMacIE = (isIE && isMac);
var isWinIE = (isIE && !isMac);
var isSafari = (userAgent.indexOf("safari") != -1);
var isGecko  = (navigator.product == "Gecko" && !isSafari);

var KEY_TAB = 9;
var KEY_REFRESH = 116; //F5
var KEY_ENTER= 13;
var TAB_INDENT = 2;
var KEY_SPACE = 32;
