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

  function byId(id) {return document.getElementById(id);}
  function byName(name) {
    els=document.getElementsByName(name);
    if (els.length==0) {return null;}
    if (els.length>1) {throw 'More than one element with name '+name;}
    return els[0];
  }
  var N=null,T=true,F=false;
  function isStr(v) {return typeof(v)=='string';}
  function el(v) {if (isStr(v)) {return byId(v);} else {return v;}};
  function log(s) {logConsole.log(s);}

  function addEvt(obj,type,f) {
    obj=el(obj); if (obj.addEventListener) {obj.addEventListener(type,f,F);}
    else if (obj.attachEvent) {var k='e'+type+f; obj[k]=f; obj[type+f]=function() {obj[k](window.event);}; obj.attachEvent('on'+type,obj[type+f]);}
  }
  function rmEvt(obj,type,f) {
    obj=el(obj); if (obj.removeEventListener) {obj.removeEventListener(type,f,F);} 
    else if (obj.detachEvent) {obj.detachEvent("on"+type,obj[type+f]); obj[type+f]=N; obj['e'+type+f]=N;}
  }
  function setStyles(el,styles) {
    sOrig=styles;
    if (typeof(styles)=='string') {
      var comps=styles.split(';'); styles = {};
      for (var i = 0; i < comps.length; ++i) {
        var comps2=comps[i].split(':'); var k=comps2[0]; var val=comps2[1];
        if (k==null || k.length==0) {continue;}
        var comps3=k.split('-'); k=comps3[0]; for (var ii=1;ii<comps3.length;++ii) {k+=comps3[ii].charAt(0).toUpperCase()+comps3[ii].substr(1);}
        styles[k]=val;
      }
    }
    try {for (var k in styles) {if (k && k.length > 0) {el.style[k] = styles[k]};}} catch (e) {alert('unsupported style: >'+k+'< in >'+sOrig+'<');}
  }
  function setVBorders(el,borderStyle) {setStyles(el,{'borderBottom':borderStyle,'borderTop':borderStyle});}
  function configureElem(el,opt) {
    if (opt.styles) {setStyles(el,opt.styles);} 
    if (opt.attr) {for (var k in opt.attr) {el[k]=opt.attr[k];}}
    if ('x' in opt && 'y' in opt) {setPos(el,opt.x,opt.y);}
  }
  function addElem(el,styles,opt) {
    if (typeof(el)=="string") {el=document.createElement(el);}
    if (opt==null) {opt={};} opt['styles']=styles; configureElem(el,opt);
    if (opt['parent']) {opt['parent'].appendChild(el);} else {document.body.appendChild(el);}
    return el;
  }
  function addElemTo(el,parentEl,styles,opt) {if (opt==null) {opt={};} opt['parent']=parentEl; return addElem(el,styles,opt);}
  function createElem(tag,styles,attr,opt) {
    var el=document.createElement(tag); 
    if (opt==null) {opt={};} opt['attr']=attr; opt['styles']=styles;
    configureElem(el,opt); return el;
  }
  function addPosElem(el,x,y,styles,opt) {if (opt==null) {opt={};} opt['x']=x; opt['y']=y; return addElem(el,styles,opt);}
  function createPosElem(tag,x,y,styles,attr,opt) {
    if (opt==null) {opt={};} opt['x']=x; opt['y']=y;
    return createElem(tag,styles,attr,opt);
  }
  function removeElem(el,parent) {if (el) {nn(parent,document.body).removeChild(el);} return null;}
  function html2elem(s) {
    dummy=document.createElement("div");
    if (startsWith(s,"<tr")) {dummy.innerHTML="<table>"+s+"</table>"; return dummy.firstChild.firstChild.firstChild;}
    dummy.innerHTML=s; return dummy.firstChild;
  }

  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 (isObj(val) && typeof(val.length)!='number' && indent==null) {
      for (var k in val) {strings.push('var '+k+' = ');saveAsJSON(val[k],"",strings,k);strings.push(";\n\n");}
    } else if (isObj(val) && typeof(val.length)=='number') {
      if (val.length==0) {strings.push("[]");} else {
        var objStrings=[],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 (isObj(val)) {
      strings.push("{\n"); var isFirst=true;
      for (var k in val) {strings.push((isFirst?'':",\n")+indent+'  "'+k+'": '); isFirst=false; saveAsJSON(val[k],indent+'  ',strings,namePath+'.'+k);}
      strings.push("\n"+indent+'}');
    } 
    else if (typeof(val)=='number') {strings.push(val);} 
    else if (isStr(val)) {
      // 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 saveAsBD(val,indent,strings,namePath) {
    var returnString=false; if (typeof(strings)=='undefined' || strings==null) {strings=[]; returnString=true;}
    if (typeof(indent)=='undefined') {
      if (!(isObj(val) && typeof(val.length)!='number')) {alert('saveAsBD: invalid data');}
      var objStrings=[];
      for (var k in val) { objStrings.push(k + "=" + saveAsBD(val[k],"",null,k)); }
      strings.push(objStrings.join("\r\n"));
    } else if (typeof(val) == 'object' && typeof(val.length) == 'number') {
      var objStrings = [];
      for (var i = 0; i < val.length; ++i) {
        var valStr = indent+i+"="+saveAsBD(val[i],indent + " ",null,namePath+"."+i);
        objStrings.push(valStr);
      }
      if (objStrings.length==0) {strings.push("{}");}
      else {strings.push("{\r\n" + indent + " " + objStrings.join("\r\n" + indent + " ") + "\r\n" + indent + "}");}
    } else if (typeof(val) == 'object') {
      var objStrings = [];
      for (var k in val) {
        var valStr = indent+k+"="+saveAsBD(val[k],indent + " ",null,namePath+"."+k);
        objStrings.push(valStr);
      }
      if (objStrings.length==0) {strings.push("{}");}
      else {strings.push("{\r\n" + indent + " " + objStrings.join("\r\n" + indent + " ") + "\r\n" + indent + "}");}
    } else if (typeof(val) == 'number') {
      strings.push(val);
    } else if (typeof(val) == 'string') {
      if (val.indexOf("\r\n") >= 0 || trim(val) == "{") {
        strings.push('"<{'+val+'}>"');
      } else {
        strings.push(val);
      }
    } 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;}
  }

  // ToDo: verlaesslichere Implementierung suchen
  function isIE() {return (navigator.userAgent.indexOf('MSIE') != -1);}
  function ieVrs() {s=navigator.userAgent; i1=s.indexOf('MSIE '); if (i1>=0) {i1+=5; i2=s.indexOf('.',i1); return s.substr(i1,i2-i1);}}
  function isMozilla() {return (navigator.userAgent.indexOf('Mozilla')!=-1);}

  var detectableWithVB=false,pluginFound=false,javascriptVersion1_1=false;
  // if the browser can do it, use replace to preserve back button
  function goURL(daURL) {if(javascriptVersion1_1) {window.location.replace(daURL);} else {window.location = daURL;} return;}
  function redirectCheck(pluginFound,redirectURL,redirectIfFound) {
    if (redirectURL && ((pluginFound&&redirectIfFound) || (!pluginFound&&!redirectIfFound)) ) {goURL(redirectURL); return pluginFound;} else {return pluginFound;}
  }
  function canDetectPlugins() {return detectableWithVB || n0(navigator.plugins);}
  function detectFlash(redirectURL, redirectIfFound) {
    pluginFound=detectPlugin('Shockwave','Flash'); if(!pluginFound && detectableWithVB) {pluginFound=detectActiveXControl('ShockwaveFlash.ShockwaveFlash.1');}
    return redirectCheck(pluginFound,redirectURL,redirectIfFound);
  }
  function detectDirector(redirectURL, redirectIfFound) { 
    pluginFound = detectPlugin('Shockwave','Director'); if(!pluginFound && detectableWithVB) { pluginFound = detectActiveXControl('SWCtl.SWCtl.1'); }
    return redirectCheck(pluginFound,redirectURL,redirectIfFound);
  }
  function detectQuickTime(redirectURL,redirectIfFound) {
    pluginFound = detectPlugin('QuickTime');
    if(!pluginFound && detectableWithVB) {pluginFound=detectQuickTimeActiveXControl();}
    return redirectCheck(pluginFound,redirectURL,redirectIfFound);
  }
  function detectReal(redirectURL,redirectIfFound) {
    pluginFound = detectPlugin('RealPlayer');
    if (!pluginFound && detectableWithVB) {
      pluginFound=(detectActiveXControl('rmocx.RealPlayer G2 Control') ||
      detectActiveXControl('RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)') ||
      detectActiveXControl('RealVideo.RealVideo(tm) ActiveX Control (32-bit)'));
    }
    return redirectCheck(pluginFound,redirectURL,redirectIfFound);
  }
  function detectWindowsMedia(redirectURL, redirectIfFound) {
    pluginFound=detectPlugin('Windows Media'); if(!pluginFound && detectableWithVB) {pluginFound = detectActiveXControl('MediaPlayer.MediaPlayer.1');}
    return redirectCheck(pluginFound,redirectURL,redirectIfFound);
  }
  function detectPlugin() {
    var dpa=detectPlugin.arguments, pluginFound = false; var np=navigator.plugins; if (l0(np)) {return false;}
    var pluginsArrayLength = navigator.plugins.length;
    for (i=0;i<np.length;++i) {
      p=np[i]; var numFound=0; for (ii=0; ii<dpa.length; ii++) {if ((p.name.indexOf(dpa[ii]) >= 0) || (p.description.indexOf(dpa[ii]) >= 0)) {numFound++;}}
      if (numFound==dpa.length) {pluginFound=true; break;}
    }
    return pluginFound;
  }
  if (isIE() && (navigator.userAgent.indexOf('Win') != -1)) { // VBScript for MSIE (ToDo: Check if this crap can be removed with demise of IE 6)
    var lines=[
      '<script language="VBscript">',
      'detectableWithVB = False',
      'If ScriptEngineMajorVersion >= 2 then',
      '  detectableWithVB = True',
      'End If',
      'Function detectActiveXControl(activeXControlName)',
      '  on error resume next',
      '  detectActiveXControl = False',
      '  If detectableWithVB Then',
      '     detectActiveXControl = IsObject(CreateObject(activeXControlName))',
      '  End If',
      'End Function',
      'Function detectQuickTimeActiveXControl()',
      '  on error resume next',
      '  detectQuickTimeActiveXControl=False',
      '  If detectableWithVB Then',
      '    detectQuickTimeActiveXControl=False',
      '    hasQuickTimeChecker = false',
      '    Set hasQuickTimeChecker = CreateObject("QuickTimeCheckObject.QuickTimeCheck.1")',
      '    If IsObject(hasQuickTimeChecker) Then',
      '      If hasQuickTimeChecker.IsQuickTimeAvailable(0) Then ',
      '        detectQuickTimeActiveXControl = True',
      '      End If',
      '    End If',
      '  End If',
      'End Function',
      '</scr'+'ipt>'];
      document.writeln(lines.join("\r\n"));
  }

  function playSound(sndFile,callingObj,xOffs,yOffs,musicplayerRelDir) {
    setTimeout(function() {startPlayingSound(sndFile,callingObj,xOffs,yOffs,musicplayerRelDir);}, 100);
    return true;
  }
  function startPlayingSound(sndFile,callingObj,xOffs,yOffs,musicplayerRelDir) {
    if (detectFlash()) {
      if (!(sc=byId("sndContainer"))) {sc=addElem('div','borderWidth:0;position:absolute;display:block;zIndex:200;',{attr:{'id':'sndContainer'}});}
      if (callingObj) {var pos=elemPos(callingObj); setPos(sc,pos.left+xOffs,pos.top+yOffs);} else {setPos(sc,-20,0);}
      if (musicplayerRelDir==null) {musicplayerRelDir=".";}
      sc.innerHTML = '<object id="sndembend" type="application/x-shockwave-flash" data="'+
        musicplayerRelDir+'/musicplayer.swf?&song_url=' + sndFile +
       '&autoplay=true&autoload=true" width="17" height="17"> ' +
       '<param name="movie" value="'+musicplayerRelDir+'/musicplayer.swf?&song_url=' + sndFile + '&autoplay=true&autoload=true"/> ' +
       '<img src="noflash.gif" width="17" height="17" alt="" /> </object>';
    } else { // fallback, works only in IE
      if (!(sc=byId('bgSound'))) {sc=addElem('bgsound','',{attr:{'id':'bgsound','loop':1}});}
      sc.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) {return;}
    iter (document.cookie.split('; '),function(c) {
      var eqIdx=c.indexOf('='); if (eqIdx==0 || l0(c)) {return;}
      if (eqIdx<0) {cookieParsed[c]='';} else {cookieParsed[c.substring(0,eqIdx)]=c.substring(eqIdx+1).replace(/-\./g,";");}
    });
  }
  function getCookieVal(name) {if (cookieParsed==null) {parseCookie();} var val=cookieParsed[name]; return nn(val,'');}
  function cookie(name) {return getCookieVal(name);}
  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 setCookie(name,val) {return setCookieVal(name,val);}

  function nn(c,fallback) {return c?c:fallback;}
  function nnStr(c,fallback) {return isStr(c)&&n0(c) ? c : fallback;}
  function isSpace(c) {return (c==' ' || c=='\n' || c=='\r' || c=='\t');}
  function ltrim(s) {while (s.length && isSpace(s.charAt(0))) {s=s.substr(1);} return s;}
  function rtrim(s) {while (s.length && isSpace(s.charAt(s.length-1))) {s=s.substr(0,s.length-1);} return s;}
  function trim(s) {return rtrim(ltrim(s));}
  function len(v) {if (isArr(v) || typeof(v)=='string') {return v.length;} if (isObj(v)) {return vals(v).length;} return 0;}
  function l0(v) {return len(v)==0;}
  function n0(v) {return len(v)>0;}
  function noMp3(s) {return (l0(s) || s=='IGNORE');}
  function basename(v) {v=v.replace('\\','/'); var p=v.lastIndexOf('/'); return p>=0?v.substr(p+1):v;}
  function lc(s) {return l0(s)?s:s.toLowerCase();}
  function uc(s) {return l0(s)?s:s.toUpperCase();}
  function startsWith(s,b) {return l0(s)?false:s.substr(0,b.length)==b;}
  function endsWith(s,b) {return s.length<b.length?false:s.substr(s.length-b.length)==b;}
  function arrEq(a,b) {
    if (len(a)!=len(b)) {return F;}
    var r=T; iter(a,function(v,k) {if (a[k]!=b[k]) {r=F;}}); return r; 
  }

  var msgEl=null;
  function showMsg(s) {if (msgEl==null) {msgEl=addPosElem('div',3,3,'position:fixed;zIndex:255;background-color:#A0A0FF;');} msgEl.innerHTML=s;}

  function setPos(elem,x,y,w,h) {
    if (x<0) {log('x='+x); elem.style.right=(-x)+'px';} else {elem.style.left=x+'px';}
    if (y<0) {log('y='+y); elem.style.bottom=(-y)+'px';} else {elem.style.top=y+'px';}
    if (w) {elem.style.width=w+'px';}; if (h) {elem.style.height=h+'px';}
  }
  function elemPos(elem) { // element position in screen coordinates
    if (!elem) {throw "elemPos(): elem not defined";}
    var r={left:elem.offsetLeft,top:elem.offsetTop,width:elem.offsetWidth,height:elem.offsetHeight}; var op=elem;
    while ((op=op.offsetParent)!=null) {r.left+=op.offsetLeft; r.top+=op.offsetTop; if (op!=document.body) {r.left-=op.scrollLeft; r.top-=op.scrollTop;}}
    r.right=r.left+r.width; r.bottom=r.top+r.height; return r;
  }
  function posToStr(p) {return 'left='+p.left+' right='+p.right+' width='+p.width+'<br/>'+'top='+p.top+' bottom='+p.bottom+' height=' +p.height+'<br/>';}
  function ptIsInElem(x,y,pos,margin) {var mg=margin==null?0:margin; return (x-1>pos.left-mg && x<=pos.right+mg && y-1>pos.top-mg && y<=pos.bottom+mg);}
  function ptIsOnPage(x,y) {return isBetween(y,document.body.scrollTop,document.body.scrollTop+getClientWindowHeight()) &&
      isBetween(x,document.body.scrollLeft,document.body.scrollLeft+getClientWindowWidth());}
    
  function classes(el) {return el.className ? el.className.split(' ') : [];}
  function hasClass(el,cls) {return has(classes(el),cls);}
  function addClass(el,cls) {if (!hasClass(el,cls)) {el.className+=' '+cls;}}
  function removeClass(el,cls) {cs=map(classes(el),function(v) {return v==cls?'':v;}); el.className=cs.join(" ");}

  function isArr(v) {return v!=null && v instanceof Array;}
  // function isArr(v) {return Object.prototype.toString.call(v)=='[object Array]';}
  function isStr(v) {return typeof(v)=='string';}
  function isObj(v) {return typeof(v)=='object';}
  function iter(m,f) {
    if (isArr(m) || m instanceof HTMLCollection) {for (var i=0;i<m.length;++i) {f(m[i],i,i);}} 
    else {var i=0; for (var k in m) {f(m[k],k,i++);}}
  }
  function last(m) {if (isArr(m)) {return m[m.length-1];} else {var r=null; iter(m,function (v) {r=v}); return r;}}
  function str(v) {if (typeof(v)=='object') {var r=''; iter(v,function(v2,k2) {r+=k2+"="+v2+"; ";}); return r;} else {return v.toString();}}
  function x(s,sep) {if (sep==N) {sep=',';} return s.split(sep);}
  function X(s,sep) {r1=x(s,sep); r=[]; for (var i=0;i<r1.length;++i) {var v=trim(r1[i]); if (n0(v)) {r.push(v);}} return r;}
  function s2m(s,entrySep,kvSep) {
    if (entrySep==N) {entrySep=';';} if (kvSep==N) {kvSep='=';} var r={};
    iter(X(s,entrySep),function(e) {var kv=e.split(kvSep,2); var k=trim(kv[0]); var v=(kv.length<2?T:trim(kv[1])); r[k]=v;}); return r;
  }
  function map(m,f) {var r=[]; for (var k in m) {r.push(f(m[k],k));} return r;}
  function kmap(m,f) {var r={}; for (var k in m) {r[k]=f(m[k],k);} return r;}
  function flt(m,f) {var r=[]; for (var k in m) {if (f(m[k],k)) {r.push(m[k]);}} return r;}
  function kflt(m,f) {var r={}; for (var k in m) {if (f(m[k],k)) {r[k]=m[k];}} return r;}
  function krmEmpty(m) {return kflt(m,function(v) {return v && ( (typeof(v)!='string' && typeof(v)!='array') || v.length>0 );});}
  function rmEmpty(m) {return flt(m,function(v) {return v && ( (typeof(v)!='string' && typeof(v)!='array') || v.length>0 );});}
  function oneTrue(m,f) {r=false; for (var k in m) {if (f(m[k],k)) {r=true;}} return r;}
  function allTrue(m,f) {r=true; for (var k in m) {if (!f(m[k],k)) {r=false;}} return r;}
  function oneFalse(m,f) {return !allTrue(m,f);}
  function allFalse(m,f) {return !oneTrue(m,f);}
  function idx(s,v) {return s.indexOf(v);}
  function has(m,v) {if (isStr(m)) {return idx(m,v)>=0;} else if (isObj(m)) {return oneTrue(m,function(v2) {return v==v2;})} else {throw "unsupported type for has()";}}
  function keys(m) {var r=[]; for (var k in m) {r.push(k);} return r;}
  function vals(m) {var r=[]; for (var k in m) {r.push(m[k]);} return r;}
  function chars(s) {var r=[]; for (var i=0;i<s.length;++i) {r.push(s.charAt(i));} return r;}
  // Clone-Problem: Unterscheidung Containment vrs. Aggregation in JS nicht moeglich, auch Referenzen werden tief kopiert (!Zyklen=Endlosrekursion!)
  function cloneArr(m) {var r=[]; for (var i=0;i<m.length;++i) {v=m[i]; if (isObj(v)) {v=clone(v);} r[i]=v;} return r;}
  function cloneObj(m) {var r=[]; for (var k in m) {v=m[k]; if (isObj(v)) {v=clone(v);} r[k]=v;} return r;}
  function clone(m) {if (typeof(m)!='object') {return m;} if (isArr(m)) {return cloneArr(m);} return cloneObj(m);}
  function shuffle(a) {for (var j,x,i=a.length; i>0; j=rndInt(0,a.length-1), x=a[--i], a[i]=a[j], a[j]=x); return a;}

  function min(a,b) {return Math.min(a,b);}
  function max(a,b) {return Math.max(a,b);}
  function isBetween(i,l,h) {return i>=l && i<=h;}
  function rndInt(min,max) {return min+Math.round((max-min)*Math.random());}
  function overlap(aS,aE, bS,bE) {s=max(aS,bS); e=min(aE,bE); return max(e-s,0);}
  function overlapArea(e1,e2) {var p1=elemPos(e1),p2=elemPos(e2); return overlap(p1.left,p1.right,p2.left,p2.right)*overlap(p1.top,p1.bottom,p2.top,p2.bottom);}
  function bestOverlapEl(els,el) {var maxO=0,r=null; for (i=0;i<els.length;++i) {var o=overlapArea(el,els[i]); if (o>maxO) {maxO=o;r=els[i];}} return r;}
    
  var _dragInfo={}; var dropTargets=[];
  function startDrag(el) {
    var d=_dragInfo; if (d.inFct) {return false;} d.inFct=true;
    endDrag(); d.el=el; d.startPos=elemPos(el); d.startX=mouseX; d.startY=mouseY; setPos(d.el,d.startPos.left,d.startPos.top);
    d.prevPos=el.style.position; el.style.position="absolute"; d.prevZIndex=el.style.zIndex; el.style.zIndex=102;
    if (d.el.startDragCb) {d.el.startDragCb(d.el);} d.inFct=false; return false;
  }
  function doDrag() {
    var d=_dragInfo; if (!d.el || d.inFct) {return;} d.inFct=true;
    setPos(d.el,d.startPos.left+(mouseX-d.startX),d.startPos.top+(mouseY-d.startY));
    ov=bestOverlapEl(dropTargets,d.el); if (d.ovEl && d.ovEl!=ov) {removeClass(d.ovEl,'dragHover');} if (ov) {addClass(ov,'dragHover'); d.ovEl=ov;}
    if (d.el.dragCb) {d.el.dragCb(d.el,d.ovEl);} d.inFct=false; return false;
  }
  function endDrag() {
    var d=_dragInfo; if (!d.el) {return;} if (d.inFct) {setTimeout("endDrag",50);} d.inFct=true;
    d.el.style.position=d.prevPos; d.el.style.zIndex=d.prevZIndex; if (d.ovEl) {removeClass(d.ovEl,'dragHover');}
    var dropEl=bestOverlapEl(dropTargets,d.el); if (d.el.onDrop) {if (d.el.onDrop(d.el,dropEl)=='reset') {setPos(d.el,d.startPos.left,d.startPos.top);}}
    d.el=null; d.inFct=false; return false;
  }
  function onDrop(el,dropCb,startDragCb,dragCb) {
    if (typeof(el)=="string") {el=byId(el);} el.style.cursor="pointer";
    document.onselectstart=function() {return false;} // Disable select for IE
    el.onDrop=dropCb; el.startDragCb=startDragCb; el.dragCb=dragCb;
    el.onmousedown=function() {startDrag(el);}; onMouseMove(function() {doDrag();}); onMouseUp(function() {endDrag();});
  }
  
  function getClientWindowWidth(opt) {
    if (!opt) {opt={};} // Mozilla; -17 for scrollbars:
    if (window.innerWidth) {return (window.innerWidth - (window.scrollbars.visible && !opt['ignoreScrollbars'] ? 17 : 0));}
    if (document.documentElement.clientWidth) {return document.documentElement.clientWidth;} // IE6
    if (document.body.clientWidth) {return document.body.clientWidth;} // IE DHTML-compliant any other
  }
  function getClientWindowHeight(opt) {
    if (!opt) {opt={};} // Mozilla; -17 for scrollbars:
    if (window.innerHeight){return (window.innerHeight - (window.scrollbars.visible && !opt['ignoreScrollbars'] ? 17 : 0));}
    if (document.documentElement.clientHeight) {return document.documentElement.clientHeight;} // IE6
    if (document.body.clientHeight) {return document.body.clientHeight;} // IE DHTML-compliant any other
  }
  function winWidth(opt) {return getClientWindowWidth(opt);} 
  function winHeight(opt) {return getClientWindowHeight(opt);}

  function copyToClipboard(txt) {
    if (isIE()) {
      if (!window.clipboardData.setData('Text', txt)) {alert("Error - text was not copied to clipboard!"); return false;}
    } else if (isMozilla()) {
      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;}
  }

  var modalPopupDiv=null;
  function modalPopup(html) {
    html = '<table style="padding:10px;" border="0" width="100%" height="100%"><tr><td align="center" valign="middle">'+html+'</td></tr></table>';
    modalPopupDiv = addPosElem('div',0,0,'zIndex:250;backgroundColor:#FFFFE0;',{'attr':{'innerHTML':html}});
    setFixedPos(modalPopupDiv,0,0,winWidth({'ignoreScrollbars':false})+1,winHeight({'ignoreScrollbars':true})+1);
  }
  function closeModalPopup() {modalPopupDiv=removeElem(modalPopupDiv);}

  function fixScrollPos(el,x,y) {setPos(el,x<0?x:document.documentElement.scrollLeft+x,document.documentElement.scrollTop+y);}
  function setFixedPos(el,x,y,width,height) {
    setPos(el,x,y,width,height);
    if (isIE() && ieVrs()<8) {
      el.style.position='absolute'; fixScrollPos(el,x,y); onScroll(function() {fixScrollPos(el,x,y);}); onResize(function() {fixScrollPos(el,x,y);});
    } else {el.style.position='fixed';}
  }

  function callFunctionsFromArray(arr) {for (var i=0; i<arr.length; ++i) {if (d=arr[i]) {d.fct(d.obj);}}}
  function callFunctionsFromArrayWithEvt(arr,evt) {for (var i=0; i<arr.length; ++i) {if (d=arr[i]) {d.fct(evt?evt:window.event,d.obj);}}}
  // associative array not used because doesn't maintain order; however, sequential search is ok for small arrays
  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,r) {for (var i=0; i<node.childNodes.length; ++i) {r.push(node.childNodes[i]); getAllChildNodes(node.childNodes[i],r);}}

  var mouseX=0; var mouseY=0;
  var mousemoveHandlers=[]; var mousedownHandlers=[]; var mouseupHandlers=[];
  var keypressHandlers=[]; var keydownHandlers=[]; var keyupHandlers=[];
  var onloadHandlers=[]; var onscrollHandlers=[]; var onresizeHandlers=[];
  var ehInitialized=false;
  function initEventHandlers() { // Initialisierung der Ueberwachung der Events
    if (ehInitialized) {return;} ehInitialized=true;
    document.onmousemove = function(evt) {
      mouseX = document.all ? window.event.clientX + document.documentElement.scrollLeft : evt.pageX;
      mouseY = document.all ? window.event.clientY + document.documentElement.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() {moveHideRegisteredPopup(true); return callFunctionsFromArray(onloadHandlers);};
    //var onLoadFct = function() {moveHideRegisteredPopup(true); return callFunctionsFromArray(onloadHandlers);};
    //if (window.addEventListener) {window.addEventListener('onload',onLoadFct,false);}
    //else if (window.attachEvent) {window.attachEvent('onload',onLoadFct);}
    //else {window.onload = onLoadFct;}
    window.onscroll = function() {return callFunctionsFromArray(onscrollHandlers);}
    window.onresize = function() {return callFunctionsFromArray(onresizeHandlers);}
  }
  initEventHandlers(); // initialisation better not on demand, but enforced
  function registerMouseMoveHandler(k,o,f) {initEventHandlers(); setByKey(mousemoveHandlers,k,{obj:o,fct:f});}
  function unregisterMouseMoveHandler(k) {setByKey(mousemoveHandlers,k,null);}
  function onMouseMove(f) {registerMouseMoveHandler(f,null,f);}
  function registerMouseDownHandler(k,o,f) {initEventHandlers(); setByKey(mousedownHandlers,k,{obj:o,fct:f});}
  function unregisterMouseDownHandler(k) {setByKey(mousedownHandlers,k,null);}
  function onMouseDown(f) {registerMouseDownHandler(f,null,f);}
  function registerMouseUpHandler(k,o,f) {initEventHandlers(); setByKey(mouseupHandlers,k,{obj:o,fct:f});}
  function unregisterMouseUpHandler(k) {setByKey(mouseupHandlers,k,null);}
  function onMouseUp(f) {registerMouseUpHandler(f,null,f);}
  function registerKeyPressHandler(k,o,f) {initEventHandlers(); setByKey(keypressHandlers,k,{obj:o,fct:f});}
  function unregisterKeyPressHandler(k) {setByKey(keypressHandlers,k,null);}
  function onKeyPress(f) {registerKeyPressHandler(f,null,f);}
  function registerKeyDownHandler(k,o,f) {initEventHandlers(); setByKey(keydownHandlers,k,{obj:o,fct:f});}
  function unregisterKeyDownHandler(k) {setByKey(keydownHandlers,k,null);}
  function onKeyDown(f) {registerKeyDownHandler(f,null,f);}
  function registerKeyUpHandler(k,o,f) {initEventHandlers(); setByKey(keyupHandlers,k,{obj:o,fct:f});}
  function unregisterKeyUpHandler(k) {setByKey(keyupHandlers,k,null);}
  function onKeyUp(f) {registerKeyUpHandler(f,null,f);}
  function registerOnLoadHandler(k,o,f) {initEventHandlers(); setByKey(onloadHandlers,k,{obj:o,fct:f});}
  function unregisterOnLoadHandler(k) {setByKey(onloadHandlers,k,null);}
  function onLoad(f) {registerOnLoadHandler(f,null,f);}
  function registerOnScrollHandler(k,o,f) {initEventHandlers(); setByKey(onscrollHandlers,k,{obj:o,fct:f});}
  function unregisterOnScrollHandler(k) {setByKey(onscrollHandlers,k,null);}
  function onScroll(f) {registerOnScrollHandler(f,null,f);}
  function registerOnResizeHandler(k,o,f) {initEventHandlers(); setByKey(onresizeHandlers,k,{obj:o,fct:f});}
  function unregisterOnResizeHandler(k) {setByKey(onresizeHandlers,k,null);}
  function onResize(f) {registerOnResizeHandler(f,null,f);}
  function evt2key(evt) {if (!evt) {evt=window.event;} return evt.which ? evt.which : evt.keyCode;}

  // Tooltip-artige Popups, Inhalt wird bei Registrierung uebergeben. ToDo evtl: HTLM optional dynamisch mit cb-fct generieren
  var popupStyles='';
  var registeredPopups = {}; var registeredPopup = null; var registeredPopupCurrBaseElem = null; var registeredPopupDontCoverBaseElem=false;
  function showRegisteredPopup(baseElem,registeredId) {
    onMouseMove(moveHideRegisteredPopup); moveHideRegisteredPopup(true);
    registeredPopupCurrBaseElem = baseElem;
    // ToDo: alle Tooltip-Styles über CSS vorgeben (statt hardcoding)
    registeredPopup = createPosElem('div',10,10,
      'backgroundColor:#FFFFE0;border:1px solid black;padding:2px 6px;position:absolute;zIndex:101;visibility:hidden;display:block;'+popupStyles,{'className':'tooltip'});
    var html = registeredPopups[registeredId].html; if (html.substr(0,5)=='eval:') {html=eval(html.substr(5));}
    registeredPopup.innerHTML = html;
    registeredPopupDontCoverBaseElem = registeredPopups[registeredId].dontCoverBaseElem;
    registeredPopup.wflag=1; addElem(registeredPopup); 
  }
  function moveHideRegisteredPopup(force) {
    if (!registeredPopup || registeredPopupCurrBaseElem==null || registeredPopupCurrBaseElem.offsetParent==null) {registeredPopup=registeredPopupCurrBaseElem=null; return;}
    // Verhindern, dass das Popup seine Breite waehrend des Bewegens aendert:
    var baseElPos=elemPos(registeredPopupCurrBaseElem);
    if (force || !ptIsInElem(mouseX,mouseY,baseElPos,2)) {
      registeredPopup.style.display = "none"; removeElem(registeredPopup); registeredPopup = registeredPopupCurrBaseElem = null;
    } else {
      var w=registeredPopup.offsetWidth, h=registeredPopup.offsetHeight; 
      var x = Math.max(10,Math.min(winWidth() - w - 10, mouseX + 10));
      var y = Math.max(10,Math.min((winHeight()+document.documentElement.scrollTop) - h - 10, mouseY + 10));
      if (registeredPopupDontCoverBaseElem) {
        //if (x < mouseX && x+w > mouseX && y < mouseY && y+h > mouseY) { // kann irritierend wirken: Popup hoch/runterklappen nur wenn Ueberlappung
          var visibleHeightIfBelow = (winHeight+document.documentElement.scrollTop)-baseElPos.bottom;
          var visibleHeightIfAbove = baseElPos.top-document.documentElement.scrollTop;
          y = visibleHeightIfAbove > visibleHeightIfBelow ? mouseY-10-h : mouseY+10;
        //}
      }
      //if (x+w>winWidth()-10) {x=winWidth()-10-w;}
      setPos(registeredPopup,x,y);
      if (registeredPopup.wflag==1) {registeredPopup.wflag=2; registeredPopup.style.width=registeredPopup.offsetWidth+"px"; registeredPopup.style.visibility='visible';}
    }
  }
  var popupBaseIdCnt = 0;
  function registerPopup(baseElem,popupHtml,dontCoverBaseElem) {
    initEventHandlers(); if (!baseElem.id || baseElem.id.length == 0) { baseElem.id = "popupBase" + (++popupBaseIdCnt); }
    registeredPopups[baseElem.id] = {'html':popupHtml,'dontCoverBaseElem':dontCoverBaseElem};
    baseElem.onmouseover = function() {showRegisteredPopup(this,baseElem.id);};
  }

  // Konsole wird mit Ctrl+Alt+C angezeigt
  if (!window.logConsole) {
    document.writeln('<style>#logConsole{z-index:100;display:none;position:absolute;bottom:0;right:0;width:600px;height:200px;overflow:scroll;border:1px solid #999;font-family:courier,monospace;background:#eee;font-size:10px;padding:3px;} html>body #logConsole{position:fixed;} #logConsole .links {position:absolute; right:0;top:0; text-align:right;}</style>');
    var logConsole={
      init:function(){logConsole.d=document.createElement('div');document.body.appendChild(logConsole.d);var links=document.createElement('div');links.className='links'; links.innerHTML='<a href="javascript:logConsole.hide()">close</a> <a href="javascript:logConsole.clear()">clear</a>';logConsole.d.appendChild(links);var id='logConsole';if(!document.getElementById(id)){logConsole.d.id=id;} if (cookie('logConsole')=='show') {logConsole.show();} else {logConsole.hide();}},
      hide:function(){logConsole.d.style.display='none';setCookie('logConsole','hide');},
      show:function(){logConsole.d.style.display='block';setCookie('logConsole','show');},
      log:function(o){if (typeof(o)=='string') {o=o.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');} if (logConsole.d) {logConsole.d.innerHTML+='<br/>'+o;logConsole.d.scrollTop=10000;}},
      clear:function(){logConsole.d.parentNode.removeChild(logConsole.d);logConsole.init();logConsole.show();}
    };
    registerOnLoadHandler(null,null,logConsole.init);
    onKeyDown(function(e){if (e.keyCode==67&&e.ctrlKey&&e.altKey) logConsole.d.style.display=='none'?logConsole.show():logConsole.hide();});
  }
  function showConsole() {if (logConsole.show) {logConsole.show();}}

  function getHttpReq(url,method,async,opt) {
    var req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); 
    if (!req) {throw 'Your Webbrowser does not support Ajax';} 
    if (method==null) {method="POST";} req.open(method,url,async);
    if (opt!=null && opt['cache']) {req.setRequestHeader("cache-control","public, max-age=30000000");}
    else {req.setRequestHeader("cache-control","no-cache, no-store");}
    if (method=="POST") {req.setRequestHeader("Content-type","application/x-www-form-urlencoded");}
    return req;
  }
  function httpReqSend(req,data,opt) { // Kapselung wegen Exception handling
    if (isObj(data)) {var a=[]; for (var k in data) {a.push(encodeURIComponent(k)+'='+encodeURIComponent(data[k]));} data=a.join("&");}
    if (opt && opt.ignoreException) {req.send(data);} else {
      try {req.send(data);} catch (e) {
        if (opt && opt.onerror) {opt.onerror('Downloadfehler: ' + e.message);} else {log('Downloadfehler: ' + e.message);}
        throw e;
      }
    }
  }
  function httpReqSync(url,method,data,opt) {var req=getHttpReq(url,method,false,opt); httpReqSend(req,data); var r=req.responseText; req.abort(); return r;}
  function get(url,opt) {return httpReqSync(url,"GET",null,opt);}
  function post(url,data,opt) {return httpReqSync(url,"POST",data,opt);} // data kann String (z.B. "a=1&b=2") oder Array sein
  function getCached(url) {return get(url,{'cache':T});}
  function postCached(url,data) {return post(url,data,{'cache':T});}
  function getHttpReq4Async(url,callbackFct,method,async,opt) {
    var req=getHttpReq(url,method,async,opt);
    req.onreadystatechange=function() {
      try {
        if (req.readyState==4) {callbackFct(req.responseText,req.readyState,req);} // State 4 bedeutet ready
        // else {alert("loading...["+req.readyState+"]);}
      } catch (e) {
        var logMsg="Downloadfehler: "+e.message+"\nData received:\n"+(req.responseText?req.responseText.substr(0,400):"");
        if (opt && opt.onerror) {opt.onerror(logMsg);} else {log(logMsg);}
        throw e;
      }
    }
    return req;
  }
  function httpReqAsync(url,callbackFct,method,data,opt) {var req=getHttpReq4Async(url,callbackFct,method,true,opt); httpReqSend(req,data); return req;}
  function getAsync(url,callbackFct,opt) {return httpReqAsync(url,callbackFct,"GET",null,opt);}
  function postAsync(url,callbackFct,data,opt) {return httpReqAsync(url,callbackFct,"POST",data,opt);} // data kann String (z.B. "a=1&b=2") oder Array sein
  
} // document._commonsIncluded_

