if (!document._commonsIncluded_) {
  document._commonsIncluded_ = true;

  function byId(id) {return document.getElementById(id);}

  function deepCopy(val) {
    if (typeof(val) == 'object' && typeof(val.length) == 'number') {
      var ret = [];
      for (var i = 0; i < val.length; ++i) {
        ret.push(deepCopy(val[i]));
      }
      return ret;
    } else if (typeof(val) == 'object') {
      var ret = {};
      for (var idx in val) {
        ret[idx] = deepCopy(val[idx]);
      }
      return ret;
    } else {
      return val;
    }
  }

  function saveAsJSON(val,indent,strings,namePath) {
    var returnString = false;
    if (!strings) {
      strings = [];
      returnString = true;
    }
    if (val == null) {
      strings.push(indent == null ? "var null;\n\n" : "null");
    } else if (typeof(val) == 'object' && typeof(val.length) != 'number' && indent == null) {
      for (var key in val) {
        strings.push("var " + key + " = ");
        saveAsJSON(val[key],"",strings,key);
        strings.push(";\n\n");
      }
    } else if (typeof(val) == 'object' && typeof(val.length) == 'number') {
      if (val.length == 0) {
        strings.push("[]");
      } else {
        var objStrings = [];
        var totalLength = 0;
        for (var i = 0; i < val.length; ++i) {
          var valStr = saveAsJSON(val[i],indent + "  ",null,namePath+"."+i);
          objStrings.push(valStr);
          totalLength += valStr.length;
        }
        if (totalLength <= 80) {
          strings.push("[" + objStrings.join(",") + "]");
        } else {
          strings.push("[\n" + indent + "  " + objStrings.join(",\n" + indent + "  ") + "\n" + indent + "]");
        }
      }
    } else if (typeof(val) == 'object') {
      strings.push("{\n");
      var isFirst = true;
      for (var key in val) {
        strings.push((isFirst ? "" : ",\n") + indent + "  \"" + key + "\": ");
        isFirst = false;
        saveAsJSON(val[key],indent + "  ",strings,namePath+"."+key);
      }
      strings.push("\n" + indent + "}");
    } else if (typeof(val) == 'number') {
      strings.push(val);
    } else if (typeof(val) == 'string') {
      // Notice: ' intentionally not masked since that is not necessary and would cause trouble to PHP's jason_decode()
      strings.push('"' + val.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/``/g,"\\\"").replace(/`/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t") + '"');
    } else if (typeof(val) == 'boolean') {
      strings.push(val ? "true" : "false");
    } else {
      alert('unknown type: ' + typeof(val) + ' for value ' + val + ' namePath=' + namePath);
    }
  
    if (returnString) {
      return strings.join("");
    } else {
      return strings;
    }
  }
  
  function playSound(sndFile) {
    setTimeout(function() {startPlayingSound(sndFile);}, 100);
    return true;
  }
  function startPlayingSound(sndFile) {
    if (window.sidebar) { // NS
      var sndContainer = document.getElementById("sndContainer");
      if (!sndContainer) {
        sndContainer = document.createElement("div");
        sndContainer.id="sndContainer";
        sndContainer.style.borderWidth = 0;
        sndContainer.style.position = 'absolute';
        sndContainer.style.top = 0;
        sndContainer.style.left = -20;
        sndContainer.style.display = "block";
        sndContainer.style.zIndex = 200;
        document.body.appendChild(sndContainer);
      }
      sndContainer.innerHTML = '<object id="sndembend" type="application/x-shockwave-flash" data="./musicplayer.swf?&song_url=' + sndFile +
       '&autoplay=true&autoload=true" width="17" height="17" alt="Chinesischen Satz vorlesen"> ' +
       '<param name="movie" value="./musicplayer.swf?&song_url=' + sndFile + '&autoplay=true&autoload=true"/> ' +
       '<img src="noflash.gif" width="17" height="17" alt="" /> </object>';
    } else { // IE
      var s = document.getElementById('bgsound');
      if (!s) {
        s = document.createElement("bgsound");
        s.id = "bgsound"; s.loop = 1;
        document.body.appendChild(s);
      }
      s.src = sndFile;
    }
  }

  function escapeForHtmlAttr(str) {
    return str.replace(/\\/g,'\\\\').replace(/&/g,"&amp;").replace(/'/g,'\\\'').replace(/"/g,'&quot;').replace(/</g,"&lt;").replace(/>/g,"&gt").replace(/\n/g,"\\n").replace(/\r/g,"\\r");
  }
  function escapeForHtml(str) {
    return str.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt");
  }
  
  var cookieParsed = null;

  function parseCookie() {
    cookieParsed = {};
    if (document.cookie) {
      var entries = document.cookie.split('; ');
      for (nr in entries) {
        var entr = entries[nr];
        var equalIdx = entr.indexOf('=');
        if (equalIdx == 0 || entr.length == 0) {continue;}
        if (equalIdx < 0) {
          cookieParsed[entr] = "";
        } else {
          cookieParsed[entr.substring(0,equalIdx)] =
            entr.substring(equalIdx+1).replace(/-\./g, ";");
        }
      }
    }
  }

  function getCookieVal(name) {
    if (cookieParsed == null) {parseCookie();}
    var val = cookieParsed[name];
    if (!val) {return '';}
    return val;
  }

  function setCookieVal(name, val) {
    if (cookieParsed == null) {parseCookie();}
    cookieParsed[name] = val;

    var val = cookieParsed[name];
    if (typeof(val) == 'string') {val = val.replace(/;/g, "-.");}
    c = name + '=' + val;

    expdate = new Date();
    expdate.setTime(expdate.getTime() + (10 * 365 * 24 * 60 * 60 * 1000));
    c += "; expires=" + expdate.toGMTString();
 
    document.cookie = c;
  }

  function isSpace(c) {return (c == ' ' || c == '\n' || c == '\r' || c == '\t');}
  function trim(s) {
    while (s.length && isSpace(s.charAt(0))) {s = s.substr(1);}
    while (s.length && isSpace(s.charAt(s.length-1))) {s = s.substr(0,s.length-1);}
    return s;
  }

function basename(val) {
  var slashpos = val.lastIndexOf('/');
  var backslashpos = val.lastIndexOf('\\');
  if (slashpos > backslashpos) {
    return val.substr(slashpos + 1);
  } else if (backslashpos > slashpos) {
    return val.substr(backslashpos + 1);
  } else {
    return val;
  }
}

  // element position in screen coordinates
  function getElemPos (elem) {
	var pos = {left: elem.offsetLeft,
			   top: elem.offsetTop,
			   width: elem.offsetWidth,
			   height: elem.offsetHeight};
	var offsetParent = elem;
	while ((offsetParent = offsetParent.offsetParent) != null) {
	  pos.left += offsetParent.offsetLeft;
	  pos.top += offsetParent.offsetTop;
	  if (offsetParent != document.body) {
	    pos.left -= offsetParent.scrollLeft;
	    pos.top -= offsetParent.scrollTop;
	  }
	}
	pos.right = pos.left + pos.width;
	pos.bottom = pos.top + pos.height;
	return pos;
  }

  function posToStr(pos) {
	var str = 'left=' + pos.left + ' right=' + pos.right + ' width=' + pos.width + '<br/>' +
			  'top=' + pos.top + ' bottom=' + pos.bottom + ' height=' + pos.height + '<br/>';
	return str;
  }

  function ptIsInElem(x,y,elemPos,margin) {
	if (margin == null) {margin = 0;}
	if (x - 1 > elemPos.left - margin && x <= elemPos.right  + margin &&
	    y - 1 > elemPos.top  - margin && y <= elemPos.bottom + margin
	) {
	  return true;
	} else {
	  return false;
	}
  }
  
  function posVerticalOverlap(pos1,pos2) {
    if ( ( ( pos1.left   > pos2.left && pos1.left   < pos2.right  ) ||
           ( pos1.right  > pos2.left && pos1.right  < pos2.right  ) ) &&
         ( ( pos1.top    > pos2.top  && pos1.top < pos2.bottom ) ||
           ( pos1.bottom > pos2.top  && pos1.bottom < pos2.bottom ) )
    ) {
      if (pos2.top - pos1.bottom > pos2.bottom - pos1.top) {
        return pos2.top - pos1.bottom;
      } else {
        return pos2.bottom - pos1.top;
      }
    } else {
      return -1;
    }
  } 
  
  function getClientWindowWidth() {
    if (window.innerWidth){
        return (window.innerWidth - (window.scrollbars.visible ? 17 : 0));                     // Mozilla; -17 for scrollbars
    }

    if (document.documentElement.clientWidth)
        return document.documentElement.clientWidth;    // IE6

    if (document.body.clientWidth)
        return document.body.clientWidth;               // IE DHTML-compliant any other
  }

  function getClientWindowHeight() {
    if (window.innerHeight){
        return (window.innerHeight - (window.scrollbars.visible ? 17 : 0));                     // Mozilla; -17 for scrollbars
    }

    if (document.documentElement.clientHeight)
        return document.documentElement.clientHeight;    // IE6

    if (document.body.clientHeight)
        return document.body.clientHeight;               // IE DHTML-compliant any other
  }


  function copyToClipboard(txt) {
    if (navigator.userAgent.indexOf('MSIE') != -1) {
      if (!window.clipboardData.setData('Text', txt)) {
        alert("Error - text was not copied to clipboard!")
        return false;
      }
    } else if (navigator.userAgent.indexOf('Mozilla') != -1) {
      try {
        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
      } catch(e) {
        alert("Your current Internet Security settings do not allow data copying to clipboard.\r\n" +
          "You can enable it in FireFox by browsing to about:config and then setting\r\n" +
          "signed.applets.codebase_principal_support\r\n" +
          "to the value \"true\"");
        return;
      }
      
      try {
        e=Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard)
      } catch(e) {
        alert("Error - text was not copied to clipboard!");
        }
      
      try {
        b=Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable)
      } catch(e) {
        alert("Error - text was not copied to clipboard!");
      }
      
      b.addDataFlavor("text/unicode");
      o=Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
      o.data=txt;
      b.setTransferData("text/unicode",o,txt.length*2);
      
      try{
      t=Components.interfaces.nsIClipboard
      } catch(e) {
        alert("Error - text was not copied to clipboard!");
      }
      
      e.setData(b,null,t.kGlobalClipboard)
      return true;
    } else {
      alert("Your browser doesn't support the copy to clipboard feature.");
      return false;
    }
  }

  function callFunctionsFromArray(arr) {
    for (var i = 0; i < arr.length; ++i) {
      d = arr[i];
      if (d) { d.fct(d.obj); }
    }
  }
  function callFunctionsFromArrayWithEvt(arr,evt) {
    for (var i = 0; i < arr.length; ++i) {
      d = arr[i];
      if (d) { d.fct(evt,d.obj); }
    }
  }
  // don't use associative array because it does not maintain order
  function setByKey(arr,k,obj) {
    obj.key = k;
    for (var i = 0; i < arr.length; ++i) {
      if (arr[i] && arr[i].key == k) {
        arr[i] = obj;
        return;
      }
    }
    arr.push(obj);
  }

  function getAllChildNodes(node,result) {
    for (var i = 0; i < node.childNodes.length; ++i) {
      result.push(node.childNodes[i]);
      getAllChildNodes(node.childNodes[i],result);
    }
  }

  var mouseX = 0;
  var mouseY = 0;
  var mousemoveHandlers = [];
  var mousedownHandlers = [];
  var mouseupHandlers = [];
  var keypressHandlers = [];
  var keydownHandlers = [];
  var keyupHandlers = [];
  var onloadHandlers = [];
  var mouseIsInitialized = false;
  function mouseinit() {
    if (mouseIsInitialized) {return;}
    mouseIsInitialized = true;
    // Initialisierung der Überwachung der Events
    document.onmousemove = function(evt) {
      mouseX = document.all ? window.event.clientX + document.body.scrollLeft : evt.pageX;
      mouseY = document.all ? window.event.clientY + document.body.scrollTop : evt.pageY;
      return callFunctionsFromArray(mousemoveHandlers);
    };
    document.onmousedown = function() { return callFunctionsFromArray(mousedownHandlers); }
    document.onmouseup = function() { return callFunctionsFromArray(mouseupHandlers); }
    document.onkeypress = function(evt) { return callFunctionsFromArrayWithEvt(keypressHandlers,evt); }
    document.onkeydown = function(evt) { return callFunctionsFromArrayWithEvt(keydownHandlers,evt); }
    document.onkeyup = function(evt) { return callFunctionsFromArrayWithEvt(keyupHandlers,evt); }
    window.onload = function() { return callFunctionsFromArray(onloadHandlers); }
  }
  function registerMouseMoveHandler(k,o,f) {
    mouseinit();
    setByKey(mousemoveHandlers,k,{obj:o,fct:f});
  }
  function unregisterMouseMoveHandler(k) {
    setByKey(mousemoveHandlers,k,null);
  }
  function registerMouseDownHandler(k,o,f) {
    mouseinit();
    setByKey(mousedownHandlers,k,{obj:o,fct:f});
  }
  function unregisterMouseDownHandler(k) {
    setByKey(mousedownHandlers,k,null);
  }
  function registerMouseUpHandler(k,o,f) {
    mouseinit();
    setByKey(mouseupHandlers,k,{obj:o,fct:f});
  }
  function unregisterMouseUpHandler(k) {
    setByKey(mouseupHandlers,k,null);
  }
  function registerKeyPressHandler(k,o,f) {
    mouseinit();
    setByKey(keypressHandlers,k,{obj:o,fct:f});
  }
  function unregisterKeyPressHandler(k) {
    setByKey(keypressHandlers,k,null);
  }
  function registerKeyDownHandler(k,o,f) {
    mouseinit();
    setByKey(keydownHandlers,k,{obj:o,fct:f});
  }
  function unregisterKeyDownHandler(k) {
    setByKey(keydownHandlers,k,null);
  }
  function registerKeyUpHandler(k,o,f) {
    mouseinit();
    setByKey(keyupHandlers,k,{obj:o,fct:f});
  }
  function unregisterKeyUpHandler(k) {
    setByKey(keyupHandlers,k,null);
  }
  function registerOnLoadHandler(k,o,f) {
    mouseinit();
    setByKey(onloadHandlers,k,{obj:o,fct:f});
  }
  function unregisterOnLoadHandler(k) {
    setByKey(onloadHandlers,k,null);
  }

  // tooltip artige Popups. Vorerst nur statischer Modus (HTML fuer Popupinhalt bei Generierung
  // (uebergeben). ToDo: HTLM optional dynamisch mit Callbackfunktion generieren
  var registeredPopups = {};
  var registeredPopup = null;
  var registeredPopupCurrBaseElem = null;
  function showRegisteredPopup(baseElem,registeredId) {
    registerMouseMoveHandler("hideRegisteredPopup",null,hideRegisteredPopup);
    hideRegisteredPopup(true);
    registeredPopupCurrBaseElem = baseElem;
    registeredPopup = document.createElement("div");
    registeredPopup.style.backgroundColor = "#FFFFE0";
    registeredPopup.style.border = "black solid 1px";
    registeredPopup.style.padding = 2;
    registeredPopup.style.paddingLeft = registeredPopup.style.paddingRight = 6;
    registeredPopup.style.position = "absolute";
    registeredPopup.style.zIndex = 101;
    registeredPopup.style.display = "block";
    var spanPos = getElemPos(baseElem);
    registeredPopup.style.left = mouseX + 10;
    registeredPopup.style.top = mouseY + 10;
    registeredPopup.innerHTML = registeredPopups[registeredId];
    document.body.appendChild(registeredPopup);
  }
  function hideRegisteredPopup(force) {
    if (!registeredPopup) {return;}
    if (force || !ptIsInElem(mouseX,mouseY,getElemPos(registeredPopupCurrBaseElem),2)) {
      registeredPopup.style.display = "none";
      document.body.removeChild(registeredPopup);
      registeredPopup = null;
      registeredPopupCurrBaseElem = null;
    } else {
      registeredPopup.style.left = mouseX + 10;
      registeredPopup.style.top = mouseY + 10;
    }
  }
  var popupBaseIdCnt = 0;
  function registerPopup(baseElem,popupHtml) {
    if (!baseElem.id || baseElem.id.length == 0) { baseElem.id = "popupBase" + (++popupBaseIdCnt); }
    registeredPopups[baseElem.id] = popupHtml;
    //baseElem.onmouseover = 'alert("over"); showRegisteredPopup(this,"' + baseElem.id + '");';
    baseElem.onmouseover = function() {showRegisteredPopup(this,baseElem.id);};
  }

} // document._commonsIncluded_

