Version 0.2.0rc11.2.2

für Paket
jautis 0.2
Author
Fabian F.
Erstellt
Mittwoch, 14.07.2010 17:38
Änderungen
  • PinnwandCodes gehen wieder

Quelltext

Syntaxhervorhebung aktivieren (kann bei längeren Quelltexten den Browser kurz einfrieren)

// jautis 0.2
// main source file
// for more information see http://www.jautis.net
//
// ==UserScript==
// @name            jautis 0.2
// @namespace       http://www.jautis.net/
// @description     jautis: just another userscript to improve SchülerVZ
// @version         0.2.0rc11.2.2
// @author          The jautis team
// @date            2010-06-14
// @include         http://www.schuelervz.net*
// @include         http://schuelervz.net*
// @include         https://www.schuelervz.net*
// @include         https://schuelervz.net*
// @include         https://secure.schuelervz.net*
// @include         http://www.studivz.net*
// @include         http://studivz.net*
// @include         https://www.studivz.net*
// @include         https://studivz.net*
// @include         https://secure.studivz.net*
// @include         http://www.meinvz.net*
// @include         http://meinvz.net*
// @include         https://www.meinvz.net*
// @include         https://meinvz.net*
// @include         https://secure.meinvz.net*
// ==/UserScript==
//
// -----------------------------------------------------
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// -----------------------------------------------------
//

//Uncomment this and the line at the bottom to enable Firebug speed test
//document.body.appendChild(document.createElement('script')).innerHTML =  "(" + (function(){


/********************************************************************
 * Struktur des Scripts                                             *
 * 1. Konstandendefinition
 * 2. Basisfunktionen
 * 3. CSS-Management
 * 4. BB-Code
 * 5. Einstellungen
 * 6. Themes umwandeln (gestrichen, Themes werden als CSS heruntergeladen);
 * 7. Tooltip
 * 8. Dialog
 * 9. Einstellungsmenü
 * 10. Imagemanager
 * 11. Standard-Themes (gestrichen, keine mehr enthalten)
 * 12. Hauptmenü
 * 13. BB-Code textareas
 *
 ********************************************************************/

/**
 * Notes for Opera kompatibility
 * - Do not use var [name1, name2] = array.
 * - Array.forEach and simular are simulated by jautis
 * - Use GM_functions and unsafeWindow only if neccessary. If you need one check
 *   first if it is available.
 * - use debug() for debugging.
 */

/* Formating
 * for long css texts replace ".{74}" by "\0'\n  + '"
 */

/********************************************************************
 * 1. Konstandendefinition
 ********************************************************************/

 
///SVZ-Server.
if (location.href.indexOf("studivz.net") > -1) {
  var VZ_NETWORK = "studivz";
} else if (location.href.indexOf("meinvz.net") > -1) {
  var VZ_NETWORK = "meinvz";
} else {
  var VZ_NETWORK = "schuelervz";
}


const VZ_SERVER = "http://www." + VZ_NETWORK + ".net/";

const JAUTIS_SERVER = "http://ajax.jautis.net/";

///Jautis-Version
const JAUTIS_VERSION = "0.2.0rc11.2.2";

///needed often
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const SVGNS = "http://www.w3.org/2000/svg";

/**
 * The constant USERIDS
 *@author Michael Z.
 */
try {
  var USERIDS = document.getElementById("Grid-Navigation-Main")
                   .getElementsByTagName("li")[1]
                   .getElementsByTagName("a")[0]
                   .getAttribute("href").match(/Profile\/([-\w]+)/i)[1] || false;
}catch(e){
  var USERIDS = false;
}

//if (typeof unsafeWindow == "undefined") {
if (!unsafeWindow) {
  var unsafeWindow = window;
}

/********************************************************************
 * 2. Basisfunktionen
 ********************************************************************/

/**
 * debugs something
 * @param obejct the object to debug
 */
function debug(object) {
  if(unsafeWindow.console) {
    unsafeWindow.console.debug(object)
  }
}


/*
 * deletes whitespaces at the start and at the end of a text
 * @return the finished text*/
String.prototype.trim = function(){
  return this.replace(/^\s*/, "").replace(/\s*$/, "")
}
/*
 * deletes whitespaces at the start and at the end of a text
 * @return the finished text*/
String.prototype.htmlencode = function(){
  return this.replace(/</g, "$lt;").replace(/"/g, "&quot;")
}

/**
 * Solves this bloody this-Problem
 * @return a function that calls, if it is called, the method is called while
 *         this is realy the object.
 */

function jautisHint(object, methodname) {
  var methodstring = methodname + "";
  var object = object;
  return function() {
    var val = object[methodstring].apply(object, arguments);
    return val;
  }
}

function globalOffsetLeft(elm) {
  var left = 0;
  while (elm) {
    left += elm.offsetLeft;
    var elm = elm.offsetParent;
  }
  return left;
}

function globalOffsetTop(elm) {
  var top = 0;
  while (elm) {
    top += elm.offsetTop;
    var elm = elm.offsetParent;
  }
  return top;
}

/**
 * Encrypts (= verschlüsseln) a given text
 * @param mode a given mode, add some of these values:
 *   1  Does Nothing (compatibility)
 *   2  shifts each normal character by a given value
 *   4  easy chararacter switching
 *   8  shifts each character by a rotating value. Buggy.
 *   16 free
 * @date 2009-03-14
 */
String.prototype.encrypt = function(mode) {
  var text = this;

  if (mode & 8) {//1. 2 Zeichen: Faktor
    var faktor = Math.floor(Math.random() * 100);
    var newtext = "";
    for(var i = 0, j = 0;i < text.length; i++){
      j += faktor;
      newtext += String.fromCharCode((text.charCodeAt(i)+j) % 16162 + 52);
    }
    text = (String.fromCharCode(faktor+93)) + newtext;
  }

  if (mode & 4) {
    var newtext = "";
    translations = [ ["a","3"], ["4","6"], ["8","9"], ["2","7"], ["c","5"],
        ["o","q"], ["m","ö"], ["t","1"], ["0","ä"], ["d","i"], ["x","s"],
        ["-","w"], ["r",")"], ["ü","b"], [",","z"], ["k","g"], ["(","v"],
        ["f","l"], ["y","j"], ["n","+"], ["h",";"], [".",":"], ["e","p"],
        ["u","?"], ["1","ß"] ]
    for (var i = 0; i < text.length; i++){
      for(var j = 0; j < translations.length; j++){
        if (translations[j][0] == text.substr(i,1).toLowerCase()) {
          newtext += translations[j][1];
          break;
        }
        else if (translations[j][1] == text.substr(i,1).toLowerCase()) {
          newtext += translations[j][0];
          break;
        }
      }
      if (i>newtext.length-1) {
        newtext += text.substr(i,1);
      }
    }
    text = newtext;
  }

  if(mode & 2){
    var newtext="", buchstaben="R|lmno7zXeAt3Ia;E0k§$+~YUfBCc-sÖ{[26ßH#giN&O4MWQ!\"VjZd}Ü.:JKpqrD5S_>uvw])öäy*/8T'<bhP?,FG9%(üÄ1x=L";
    for (var i = 0; i < text.length; i++) {
      var pos=buchstaben.indexOf(text.substr(i,1))-30
      if(pos<-30){
        newtext+=text.substr(i,1);
        continue;
      }
      if(pos<0)
        pos+=buchstaben.length;
      newtext+=buchstaben.substr(pos,1)
    }
    text = newtext;
  }
  return text;
}

String.prototype.decrypt = function(mode){
  var text=this
  if(mode & 2){
    var newtext="", buchstaben="R|lmno7zXeAt3Ia;E0k§$+~YUfBCc-sÖ{[26ßH#giN&O4MWQ!\"VjZd}Ü.:JKpqrD5S_>uvw])öäy*/8T'<bhP?,FG9%(üÄ1x=L";
    for(var i=0;i<text.length;i++){
      var pos=buchstaben.indexOf(text.substr(i,1))+30
      newtext+=(pos<30) ? text.substr(i,1) : buchstaben.substr(pos % buchstaben.length,1)
    }
    return newtext;
  }
  if(mode & 4)
    text = text.encrypt(4)
  if(mode & 8){//1. 2 Zeichen: Faktor
    var faktor=parseInt(text.charCodeAt(0)-93),newtext="";
    for(var i=1,j=0;i<text.length;i++){
      j+=faktor;
      newtext+=String.fromCharCode((text.charCodeAt(i)-j)%16162-52)
    }
    return newtext;
  }
  return text;
};

if (typeof Array.some != "function") {
  Array.some = function(array, func) {
    for (i = 0; i < array.length; i++) {
      if (func(array[i])) {
        return true;
      }
    }
    return false;
  }
}
if (typeof Array.forEach != "function") {
  Array.forEach = function(array, func) {
    for (i = 0; i < array.length; i++) {
      func(array[i]);
    }
  }
}
if (typeof Array.filter != "function") {
  Array.filter = function(array, func) {
    var result = [];
    for (i = 0; i < array.length; i++) {
      if (func(array[i])) {
        result.push(array[i]);
      }
    }
    return result;
  }
}

/********************************************************************
 * 3. CSS-Management
 ********************************************************************/

/**
 * this function cleans a given CSS-Code so that it does not look so ugly
 * @author Michael Z.
 * @date 2009-03-14
 * @param code the code to be cleaned
 * @return the cleaned code
 */
function cleanCSS(code) {
  return code;
  
  function cleanCommand(a, name, value) {
    while (name.length < 15) {
      name = name + " ";
    }
    return "  " + name + ": " + value + ";\n";
  }
  function replaceSection(a, modifiers, content) {
    content = (content + ";").replace(/([^:]+)\s?\:\s?([\w\W]*?)\s?;\s?/g, cleanCommand)
    modifiers = modifiers.replace(/,\s?/g, ",\n");
    return modifiers + " {\n" + content + "}\n\n";
  }
  function getComment() {
    return comments.shift().replace(/^\n*/, "\n").replace(/\n*$/, "\n");
  }
  function setComment(comment) {
    comments.push(comment);
    return "___COMMENT___";
  }
  var comments = [];
  code = code
    .replace(/\/\*[\w\W]*?\*\//g, setComment)
    .replace(/\n/g, " ")
    .replace(/\s\s+/g, " ")
    .replace(/([^\{]+)\{([\w\W]*?);?\s*\}\s*/g, replaceSection)
    .replace(/___COMMENT___/g, getComment)
  return code;
}

/**
 * this function adds a css-code to the current page
 * the code is automatically cleaned.
 * If the function finds an String that matches /\{IMG:\w+\}/, it replaces it by
 * the data-url of the image whith the id (using imagemanager).
 * @param code the css code to be added
 */
var _css         = "";
var _css_element = null;
function CSS(code){
  var code = code;

  if (_css_element != null) { //Seite schon geladen
    code = code.replace(/\{IMG\:([\w\.\-\/]+)\}/gi, function(all, id) {
      var manager = new Imagemanager(id);
      if(!manager.isActual()) {
        manager.onload = function(){
          CSS(code);
        };
      }
      return manager.getImage();
    });//replace
    _css_element.innerHTML += cleanCSS(code) + "\n";
  }
  else {
    _css += code + "\n";
  }
}

/**
 * runs a x-path
 * @param node the node where the path sould start.
 * @param expr the xpath as String
 * @return an array of elements that match the xpath
 * @author see MDC
 */
// Evaluate an XPath expression aExpression against a given DOM node
// or Document object (aNode), returning the results as an array
// thanks wanderingstan at morethanwarm dot mail dot com for the
// initial work.
function evaluateXPath(aNode, aExpr) {
  var xpe = new XPathEvaluator();
  var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ?
    aNode.documentElement : aNode.ownerDocument.documentElement);
  var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null);
  var found = [];
  var res;
  while (res = result.iterateNext())
    found.push(res);
  return found;
}

if (typeof Array.some != "function") {
  Array.some = function(array, func) {
    for (i = 0; i < array.length; i++) {
      if (func(array[i])) {
        return true;
      }
    }
    return false;
  }
}
if (typeof Array.forEach != "function") {
  Array.forEach = function(array, func) {
    for (i = 0; i < array.length; i++) {
      func(array[i]);
    }
  }
}
if (typeof Array.filter != "function") {
  Array.filter = function(array, func) {
    var result = [];
    for (i = 0; i < array.length; i++) {
      if (func(array[i])) {
        result.push(array[i]);
      }
    }
    return result;
  }
}

/********************************************************************
 *                4. BB-Code functions                              *
 *                                                                  *
 * This part creates a class BBCoder, which can parse a text for    *
 * BB-Tags. It also adds a Method to the String-Class for easy BB   *
 * parsing.                                                         *
 ********************************************************************/
//TODO: improve bb security methods

/**
 * creates a new BBCoder-Object
 * @author Michael Z.
 * @date 2008-03-14
 */
function BBCoder() {}

/**
 * The maximum number of videos and music allowed while parsing the Strings. The number is
 * automatically decreased if a video is found while parsing.
 * A value of -1 allows an infinite number of videos.
 */
BBCoder.prototype.maximumVideosInSection = 5;
BBCoder.prototype.maximumMusicInSection = 1;

//private
BBCoder.prototype.noBBSections = [];
BBCoder.prototype.noBBString = null;

/*  -----------  STRING PARSING METHODS --------------- */
/**
 * this Method parses a given String with the current settings
 * @param code the BB-Coded String.
 * @return the HTML-Output
 */
BBCoder.prototype.parseString = function(code) {
  code = this.searchNoBBSections(code);
  code = this.replacePreparsers(code);

  code = this.parseForControls(code);
  code = this.parseForFont(code);
  code = this.parseForDecorations(code);
  code = this.parseForMusic(code);
  code = this.parseForParagraphStyle(code);
  code = this.parseForColors(code);

  code = this.parseForImages(code);
  code = this.parseForVideos(code);
  code = this.parseForLists(code);
  code = this.parseForDates(code);
  code = this.parseForTables(code);
  code = this.parseForCSS(code);
  code = this.parseForQuotes(code);

  code = this.parseForLinks(code);
  code = this.restoreNoBBSections(code);
  return code;
}

BBCoder.prototype.searchNoBBSections = function(code) {
  this.noBBString = "_\"" + Math.random() + "_";
  this.noBBSections = [];
  code = code.replace(
      /\[nobb\]([\w\W]*?)\[\/nobb\]/gi,
      jautisHint(this, "replaceNoBBSection"));

  return code;
}
BBCoder.prototype.replaceNoBBSection = function(all, code) {
  this.noBBSections.push(code);
  return this.noBBString;
}
BBCoder.prototype.restoreNoBBSections = function(code) {
  for(var i = 0; i < this.noBBSections.length; i++) {
    code = code.replace(this.noBBString, this.noBBSections[i])
  }
  return code;
}

BBCoder.prototype.replacePreparsers = function(code) {
  code = code.replace(/\[nb\]([\w\W]*?)\[\/nb\]/ig,
        function(all,a){return a.replace(/\n/g, "")} )
  code = code.replace(/\[nw\]([\w\W]*?)\[\/nw\]/ig,
        function(all,a){return a.replace(/[ ]/g, "")} )
    //entschlüsseln
  code = code.replace(/\[enc(\d+)\]([\w\W]*?)\[\/enc\]/ig,
        this.getDecryptedText);
  code = code.replace(/\[hidden\][\w\W]*?\[\/hidden\]/ig, "");
  code = code.replace(/\[br\]/ig, "<br />");
  return code;
}

BBCoder.prototype.parseForFont = function(code) {
  code = code.replace(/\[h(?:eadline)?=?(\d)?\]([\w\W]*?)\[\/h(\d|eadline)?\]/ig,
      function (all, level, text) {
        return level ? "<h" + level + ">" + text + "</h" + level + ">"
                     : "<h2>" + text + "</h2>";
      })    //bilder
  code = code.replace(/\[b\]([\w\W]*?)\[\/b\]/ig, "<b>$1</b>");
  code = code.replace(/\[i\]([\w\W]*?)\[\/i\]/ig, "<i>$1</i>")
  code = code.replace(/\[size=\s?([+-]?\d)\]([\w\W]*?)\[\/size\]/gi,
      function (all, size, text) {
        return '<font style="font-size:' + (100+size*7) + '%">' + text + '</font>';
      });

  return code;
}
BBCoder.prototype.parseForControls = function(code) {
  code = code.replace(/\[clear\]/ig, "<div style=\"clear:both;\" />")
  code = code.replace(/\[hr\]/ig, "<hr/>")
  return code;
}
BBCoder.prototype.parseForDecorations = function(code) {
  code = code.replace(/\[u\]([\w\W]*?)\[\/u\]/ig                  , "<u>$1</u>")
  code = code.replace(/\[s\]([\w\W]*?)\[\/s\]/ig                  , "<s>$1</s>")
  code = code.replace(/\[sub\]([\w\W]*?)\[\/sub\]/ig              , "<sub>$1</sub>")
  code = code.replace(/\[sup\]([\w\W]*?)\[\/sup\]/ig              , "<sup>$1</sup>")
  code = code.replace(/\[blink\]([\w\W]*?)\[\/blink\]/ig          , "<blink>$1</blink>") // LUHE
  code = code.replace(/\[backwards\]([\w\W]*?)\[\/backwards\]/ig  , "<bdo dir=\"rtl\">$1</bdo>") // LUHE
  code = code.replace(/\[art=([\w\s]+)\]([\w\W]*?)\[\/art\]/gi    , "<span style=\"font-family:'$1'\">$2</span>")
  code = code.replace(/\[overline\]([\w\W]*?)\[\/overline\]/ig    , "<span style=\"text-decoration: overline\">$1</span>")
  return code;
}
BBCoder.prototype.parseForMusic = function(code) {
  return code.replace(/\[music=([\w]*?)\]([\w\-]*?)\[\/music\]/ig,
    jautisHint(this, "getHTMLForMusic"));
}

BBCoder.prototype.parseForParagraphStyle = function(code) {
  code = code.replace(/\[code\]([\w\W]*?)\[\/code\]/ig,
      "<code>$1</code>");
  code = code.replace(/\[center\]\n?([\w\W]*?)\n?\[\/center\]/ig,
      "<center>$1</center>");
  code = code.replace(/\[right\]\n?([\w\W]*?)\n?\[\/right\]/ig,
      "<div style=\"text-align:right\">$1</div>");
  code = code.replace(/\[left\]\n?([\w\W]*?)\n?\[\/left\]/ig,
      "<div style=\"text-align:left\">$1</div>");
  code = code.replace(/\[scroll=?(up|down|right|alternate)?\]([\w\W]*?)\[\/scroll\]/ig, function (all, a, b){
      var scroll="<marquee "
	  if (a=="alternate") {scroll+="behavior="}
	  else {scroll+="direction="}
	  scroll+="\""+a+"\">"+b+"</marquee>"
	  return scroll;
	  });  // DOTO
  code = code.replace(/\[newTopDirection=([\w\W]*?)\|?(\d*?)\]/ig, function (all, a, b){
      if (document.URL.indexOf("http://www.schuelervz.net/Profile/")<0){
      return all;
      }
      else {
	  if (b) {b=b-1;
	  var element = document.getElementById("Profile_InformationSnipplet").getElementsByTagName("h3")[b];}
	  else {
	  var element = document.getElementById("Profile_InformationSnipplet").firstChild;}
	  var h3 = document.createElement("h3");
	  h3.innerHTML=a;
	  document.getElementById("Profile_InformationSnipplet").insertBefore(h3, element);
	  var dl=document.createElement("dl");
	  dl.id="Mod-Profile-Information-"+a;
	  dl.setAttribute("class", "obj-keyValueList");
	  document.getElementById("Profile_InformationSnipplet").insertBefore(dl, element);
	  return "";
	  }
	  });
  code = code.replace(/\[newDirection=([\w\W]*?) in ([\w\W]*?)\|?(\d*?)\]([\w\W]*?)\[\/newDirection\]/ig, jautisHint(this, "getHTMLForNewDirection"));
  code = code.replace(/\[spoiler=?(\d)*?\]([\w\W]*?)\[\/spoiler\]/ig, function (all, a, b){
      if (!a) {
	  var a = Math.floor(Math.random() * 10000)
	  }
		return '<a onclick=\'if (document.getElementById("spoiler'+a+'").style.display=="block") {document.getElementById("spoiler'+a+'").style.display="none";}else {document.getElementById("spoiler'+a+'").style.display="block"}\'>Spoiler ein bzw. ausblenden</a><br/><div id="spoiler'+a+'" style="display:none;">'+b+'</div>';
	  });

  return code;
}
BBCoder.prototype.parseForColors = function(code) {
  code = code.replace(/\[border(?:=([\w#]\w*))[^\]]*\]\n?([\w\W]*?)\n?\[\/border\]/ig,
      "<div style=\"border: 1px solid transparent; border-color:$1\">$2</div>");
  code = code.replace(/\[colorbox=([#\w]\w*)[^\]]*\]\n?([\w\W]*?)\n?\[\/colorbox\]/gi ,
      '<div style="background:$1">$2</div>');
  code = code.replace(/\[bgcolor=([#\w]\w*)[^\]]*\]([\w\W]*?)\[\/bgcolor\]/gi,
      '<font style="background:$1">$2</font>');
  code = code.replace(/\[color=([#\w]\w*)[^\]]*\]([\w\W]*?)\[\/color\]/gi,
      '<font color="$1">$2</font>');
  return code;
}

//shoulod be parsed at the end
BBCoder.prototype.parseForLinks = function(code) {
  var me = this;
  code = code.replace(/\[anker=(\w+)[^\]]*\]/gi,
      '<a name="$1"></a>');
  code = code.replace(/\[url(?:=([^\]]+))?\](.*?)\[\/url\]/gi, jautisHint(this, "getHTMLForLink"))
  // [email] deactivated for security reasons
  code = code.replace(/\[\[([^\]]+)\]\]/gi, jautisHint(this, "getHTMLForWikiLink"));
  code = code.replace(/\[((?:(?:(?:ftp|http|https)\:\/\/)|(?:\/|\#))[^\]]+)\]/gi ,jautisHint(this, "getHTMLForWikiLink"))
  code = code.replace(/(?:(?:(?:ftp|http|https):\/\/)|www\.)[^\s<>\[\]]+[\w\-_]/gi,
      jautisHint(this, "getHTMLForInlineLink"));
  return code;
}

BBCoder.prototype.parseForImages = function(code) {
  code = code.replace(/\[img(?:=(right|left))?\]([^\"]*?)\[\/img\]/gi,
          jautisHint(this, "getHTMLForImage"));

  code = code.replace(
    /\[base64image\][\w\W]*?(data:image\/\w+;base64,[\w+/\\+=\s\n]*)[\w\W]*?\[\/base64image\]/gi,
    "<img src=\"$1\"/>");
  return code;
}

BBCoder.prototype.parseForVideos = function(code) {
  return code.replace(/\[video=([\w\|]*?)\]([\w\-\W]*?)\[\/video\]/ig,
    jautisHint(this, "getHTMLForVideo"));
}

BBCoder.prototype.parseForLists = function(code){
  while(code.search(/\[list=?[^\]]*\][\w\W]*?\[\/list\]/) > -1) {
    code = code.replace(
       /([\w\W]*)\n?\[list=?([^\]])*\]\n?([\w\W]*?)\[\/list\]\n?/,
       jautisHint(this, "getHTMLForList"));
  }
  return code;
}

BBCoder.prototype.parseForTables = function(code){
  while(code.search(/\[table[^\"]*\][\w\W]*?\[\/table\]/) > -1) {
    code = code.replace(
       /([\w\W]*)\n?\[table[=\s]?([^\"\]]*)\]([\w\W]*?)\[\/table\]\n?/,
       jautisHint(this, "getHTMLForTable"));
  }
  return code;
}

BBCoder.prototype.parseForDates = function(code){
  var me = this;
  code = code.replace(/\[date\]([\w\W]*?)\[\/date\]/ig, function(all, datestring){
      return me.transformDate(datestring);
    });
  code = code.replace(/\[dyndate\]([\w\W]*?)\[\/dyndate\]/ig, function(all, datestring){
      var id = ("dyndate_" + Math.random() * 10).replace(/\./,"");
      var datedata = datestring;
      var parseDate = me.transformDate;
      setInterval(function(){
        (document.getElementById(id) || {}).innerHTML = parseDate(datedata)
      }, datestring.search(/[si]/)<0 ? 20000 :datestring.search(/s/) < 0 ? 3000 :1000)
      return "<span id='" + id + "'>" + parseDate(datestring) + "</span>";
    });
  return code;
}

BBCoder.prototype.parseForQuotes = function parseQuotes(code){
  while(code.search(/\[quote(?:[=\s][^\]]*?(?:\[[^\]]*\][^\]]*?)*)?\][\w\W]+?\[\/quote\]/) > -1) {
    code = code.replace(/([\w\W]*)\n?\[quote(?:[=\s]([^\]]*?(?:\[[^\]]*\][^\]]*?)*))?\]\n?([\w\W]+?)\n?\[\/quote\]/,
            jautisHint(this, "getHTMLForQuote"));
  }
  return code;
}

BBCoder.prototype.parseForCSS = function (code) {
  while(code.search(/\[css[\s=][^\]]*\][\w\W]*?\[\/css\]/) > -1) {
    code = code.replace(/([\w\W]*)\n?\[css[\s=]([^\]]*)\]([\w\W]*?)\[\/css\]/, jautisHint(this, "getHTMLForCSS"));
  }
  return code;
}

/*  -----------  EXTENDED PARSING METHODS --------------- */
/**
 * this Method parses a given DOM-Node with the current settings and transforms
 * all content.
 * @param element A DOM-Node
 */
/*BBCoder.prototype.parseNode = function(element) {
  var currentNodes = [];
  for (var i = 0; i < element.childNodes.length; i++) {
    if(element.nodeType == 1) {
      currentNodes.push(element.childNodes[i]);
    } else {
      this.replaceTextNodes(currentNodes);
      currentNodes = [];
      this.parseNode(element.childNodes[i]);
    }
  }
  this.replaceTextNodes(currentNodes);
}*/
/**
 * replaces some text nodes with their correspondenting HTML elements
 * @param nodeArray an array of text nodes
 */
/*BBCoder.prototype.replaceTextNodes = function(nodeArray) {
  if(nodeArray.length < 1) {
    return;
  }

  var text = "";
  for(var index = 0; index < nodeArray.length; index++) {
    text += nodeArray[index].data;
  }
  var parentNode = nodeArray[0].parentNode
  var tempdiv = document.createElement("div");
  tempdiv.innerHTML = this.parseString(text);
  var newNodes = tempdiv.childNodes;
  for(var index = 0; index < newNodes.length; index++) {
    parentNode.insertBefore(newNodes[index], nodeArray[0]);
  }
  for(var index = 0; index < nodeArray.length; index++) {
    parentNode.removeChild(nodeArray[index]);
  }
}*/
/**
 * removes all \n from text nodes and replaces ll HTML-BR-Elements by \n.
 * It also joins following text nodes.
 */
BBCoder.prototype.removeBRFromElement = function(element) {
  if (element.nodeType == 3) {
    //Textknoten behandeln, \n entfernen und mit vorherigem verketten
    var data = element.data.replace(/\n/g, "");
    if(element.previousSibling && element.previousSibling.nodeType == 3) {
      element.previousSibling.data += data;
      element.parentNode.removeChild(element);
    } else {
      element.data = data;
    }
  } else if (element.nodeType == 1 && element.nodeName.toLowerCase() == "br") {
    //BR ersetzen
    var parent = element.parentNode;
    if(element.previousSibling && element.previousSibling.nodeType == 3) {
      element.previousSibling.data += "\n";
      element.parentNode.removeChild(element);
    } else {
      element.parentNode.replaceChild(document.createTextNode("\n"), element);
    }
  } else {
    //kinder rekursiv durchlaufen. Liste kopieren damit sie sich nicht ändert.
    Array.filter(element.childNodes, function() {return true;}).forEach(
      jautisHint(this, "removeBRFromElement"));
  }
}
/**
 * replacres all \n in text nodes by HTML-BR-Elements
 */
BBCoder.prototype.addBRToElement  = function(element) {
  var nodes = [];
  for (var i = 0; i < element.childNodes.length; i++) {
    nodes[i] = element.childNodes[i];
  }
  for(var i = 0; i < nodes.length; i++) {
    if(nodes[i].nodeType == 3) {
      var textNode = nodes[i];
      var splitIndex;
      while((splitIndex = textNode.data.indexOf("\n", 0)) >= 0) {
        textNode = textNode.splitText(splitIndex + 1);
        element.insertBefore(document.createElement("br"), textNode);
      }
    } else {
      this.addBRToElement(nodes[i]);
    }
  }
}
/**
 * parses a node that contains brs. the brs are removed and after the BB-Code is
 * parsed they are restored again.
 */
BBCoder.prototype.parseNodeWithBR  = function(element) {
  this.removeBRFromElement(element);
  this.parseNode(element);
  this.addBRToElement(element);
}

BBCoder.prototype.parseNode = function(element) {
  if(element.nodeType == 3 || (!element.innerHTML && element.innerHTML !== "")) {
    var tmp = document.createElement("div");
    element.parentNode.replaceChild(tmp, element);
    tmp.appendChild(element);
    element = tmp;
  }
  var bb = element.innerHTML;
  element.innerHTML = this.parseString(bb);
}
/*  -----------  TRANSFORMING/REPLACING METHODS --------------- */

BBCoder.prototype.getHTMLForVideo = function(fullBB, dataString, videoId) {
  var data = dataString.split("|"); //videoPlatform, width, height
  var videoURL = null;
  var params = {allowFullscreen : "true", allowNetworking : "internal",
    allowScriptAccess: "always", quality: "best"};
  var attrs = {
    width : data.length > 1 && data[1].length > 2 ? parseInt(data[1]) : 0,
    height: data.length > 2 && data[2].length > 2 ? parseInt(data[2]) : 0,
    //type  : "application/x-shockwave-flash", //TODO: add to those that need it
  };
  if (!attrs.width) {
    attrs.width = attrs.height ? attrs.height * 4 / 3 : 360;
  }
  if (!attrs.height) {
    attrs.height = attrs.width / 4 * 3;
  }

  this.maximumVideosInSection--;

  if(this.maximumVideosInSection == -1) { // was 0
    this.maximumVideosInSection++;
    return fullBB;
  }

  switch (data[0]) {
    case "youtube":
    case "short":
      videoURL = "http://www.youtube.com/v/" + videoId
          + '&rel=0&border=1&hl=de&fmt=22';
      params.quality = "best";
      break;
    case "clipfish":
      attrs.classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000";
      attrs.codebase = "http://fpdownload.macromedia.com/pub/shockwave/cabs/"
         + "flash/swflash.cab#version=8,0,0,0";
      videoURL = "http://www.clipfish.de/videoplayer.swf?as=0&vid="
         + videoId + "&r=1";
      params.bgcolor = "#FF0000";
      break;
    case "myvideo":
      videoURL = "http://www.myvideo.de/movie/" + videoId
      break;
    case "myspace":
      videoURL = "http://mediaservices.myspace.com/services/media/embed.aspx/m="
         + data + ",t=1,mt=video,searchID=,primarycolor=,secondarycolor="
      break;
    case "googlevideo":
      videoURL = "http://video.google.de/googleplayer.swf?docid=-" + videoId;
      break;
    case "veoh":
      videoURL = "http://www.veoh.com/veohplayer.swf?permalinkId=" + videoId
        + "&id=anonymous&player=videodetailsembedded&videoAutoPlay=0";
      params.bgcolor = "#FFFFFF"
      break;
    case "sevenload":
      videoURL = "http://de.sevenload.com/pl/" + videoId + "/" + width + "x"
        + height + "/swf";
      break;
    case "vimeo":
      videoURL = "http://www.vimeo.com/moogaloop.swf?clip_id=" + videoId;
      break;
    case "yahoo":
      videoURL = "http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?id="
        + videoId;
      break;
    case "gmx":
      videoURL = "http://video.gmx.net/movie/" + videoId;
      params.scale = "showAll";
      break;
    case "aol":
      videoURL = "http://o.aolcdn.com/mediaplayer/players/fpm/fpm.swf?assetId="
        + "video:asset:pmms:" + videoId;
      params.scale = "showAll";
      break;
  }

  if (videoURL) {
    html = '<object';
    for (name in attrs) {
      html += " " + name + '="' + attrs[name] + '"';
    }
    html += '><param name="movie" value="' + videoURL + '"/>';
    for (name in params) {
      html += '<param name="' + name + '" value="' + params[name] + '"/>';
    }
    html += '<embed src="' + videoURL + '"';
    for (name in attrs) {
      html += " " + name + '="' + attrs[name] + '"';
    }
    for (name in params) {
      html += " " + name + '="' + params[name] + '"';
    }
    html += '></embed></object>';
    return html;
  } else {
    return "Videodefinition ungültig!";
  }
  /*else if(type=="yahoo2") {
    html = '<object type="application/x-shockwave-flash" '
         + 'data="http://d.yimg.com/cosmos.bcst.yahoo.com'
         + '/up/fop/embedflv/swf/fop.swf?id=' + data
         if (width) {html+='width="' + width +'"'}
		 else{html+='width="470"'}
		 if (height) {html+='height="' + height +'"'}
		 else{html+='height="315"'}
		 html+= '> <param name="quality" value="best" /> '
         + '<param name="allowfullscreen" value="true" /> '
         + '<param name="allowScriptAccess" value="always" /> '
         + '<param name="scale" value="showAll" /> '
         + '<param name="allowNetworking" value="internal" /> '
         + '<param name="movie" value="http://d.yimg.com/cosmos.bcst.yahoo.com'
         + '/up/fop/embedflv/swf/fop.swf?id=' + data + '" /></object> '
  }*/
  return html;
}

//TODO: document
BBCoder.prototype.getHTMLForMusic = function(fullBB, data, musicId) {
 if (!userSettings.get("backgroundmusic.activeted")&&!userSettings.get("backgroundmusic.deactiveted")) {
 var backgroundmusicelm = document.createElement("div");
 backgroundmusicelm.innerHTML = "Entscheidnen Sie sich, ob sie Hintergrundmusik aktivieren möchten oder nicht.<br/>"
 var backgroundmusicbutton   = document.createElementNS(XULNS, "button")
  backgroundmusicbutton.setAttribute("label", "Hintergrundmusik aktivieren");
  backgroundmusicbutton.style.marginTop="1em";
  backgroundmusicbutton.addEventListener("command", function(){
    userSettings.set("backgroundmusic.activeted", true);
    dialog.close();
  }, true);
  backgroundmusicelm.appendChild(backgroundmusicbutton)
 var backgroundmusicbutton2   = document.createElementNS(XULNS, "button")
  backgroundmusicbutton2.setAttribute("label", "Hintergrundmusik deaktivieren");
  backgroundmusicbutton2.style.marginTop="1em";
  backgroundmusicbutton2.addEventListener("command", function(){
    userSettings.set("backgroundmusic.deactiveted", true);
    dialog.close();
  }, true);
  backgroundmusicelm.appendChild(backgroundmusicbutton2)
  var dialog = new JautisDialog("Hintergundmusik Registrierung", backgroundmusicelm)
  return '<span style="border:1px solid black; font-size:0.6em;">Noch nicht verfügbar!<br/>Wenn aktiviert, neuladen nötig.</span>';
 }
 else if (!userSettings.get("backgroundmusic.activeted", true)||userSettings.get("backgroundmusic.deactiveted", true)) {
 return '<span style="border:1px solid black; font-size:0.6em;">Deaktiviert!</span>';
 } 
  else if (document.URL.indexOf("http://www.schuelervz.net/Profile/")<0){
  return '<span style="border:1px solid black; font-size:0.6em;">Einbindung von Hintergrundmusik hier nicht möglich.</span>';
  }
  else {
  musicId += "&autoplay=1";
  var musicURL = null;
  var params = {allowFullscreen : "true", allowNetworking : "internal",
    allowScriptAccess: "always", quality: "best"};
  var width = "35";
  var height = "40";

  this.maximumMusicInSection--;

  if(this.maximumMusicInSection == -1) { 
    this.maximumMusicInSection++;
    return fullBB;
  }

  switch (data) {
    case "youtube":
      musicURL = "http://www.youtube.com/v/" + musicId
          + '&hl=de&fs=1&fmt=6';
      params.quality = "best";
      break;
    case "clipfish":
      attrs.classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000";
      attrs.codebase = "http://fpdownload.macromedia.com/pub/shockwave/cabs/"
         + "flash/swflash.cab#version=8,0,0,0";
      musicURL = "http://www.clipfish.de/videoplayer.swf?as=0&vid="
         + musicId + "&r=1";
      params.bgcolor = "#FF0000";
      break;
    case "myvideo":
      musicURL = "http://www.myvideo.de/movie/" + musicId
      break;
    case "myspace":
      musicURL = "http://mediaservices.myspace.com/services/media/embed.aspx/m="
         + data + ",t=1,mt=video,searchID=,primarycolor=,secondarycolor="
      break;
    case "googlevideo":
      musicURL = "http://video.google.de/googleplayer.swf?docid=-" + musicId;
      break;
    case "veoh":
      musicURL = "http://www.veoh.com/veohplayer.swf?permalinkId=" + musicId
        + "&id=anonymous&player=videodetailsembedded&videoAutoPlay=1";
      params.bgcolor = "#FFFFFF"
      break;
    case "sevenload":
      musicURL = "http://de.sevenload.com/pl/" + musicId + "/" + width + "x"
        + height + "/swf";
      break;
    case "vimeo":
      musicURL = "http://www.vimeo.com/moogaloop.swf?clip_id=" + musicId;
      break;
    case "yahoo":
      musicURL = "http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?id="
        + musicId;
      break;
    case "gmx":
      musicURL = "http://video.gmx.net/movie/" + musicId;
      params.scale = "showAll";
      break;
    case "aol":
      musicURL = "http://o.aolcdn.com/mediaplayer/players/fpm/fpm.swf?assetId="
        + "video:asset:pmms:" + musicId;
      params.scale = "showAll";
      break;
  }

  if (musicURL) {
    html = '<div style="text-align:center;"><object';
	html += " width=" + width;
	html += " height=" + height;
    html += '><param name="movie" value="' + musicURL + '"/>';
    for (name in params) {
      html += '<param name="' + name + '" value="' + params[name] + '"/>';
    }
    html += '<embed src="' + musicURL + '"';
    for (name in params) {
      html += " " + name + '="' + params[name] + '"';
    }
	html += " width=" + width;
	html += " height=" + height;
    html += '></embed></object><br><span style="color:red;font-weight:bolder;">Hintergrundmusik</span></div>';
    return html;
  } else {
    return "Musikdefinition ungültig";
  }
  return html;
  }
}

BBCoder.prototype.getHTMLForList = function(fullBB, prefix, type, content){
  content = content.replace(/^[\n\s]*\[([\*\+\#o])\]/, "");
  items = content.split(/\n?\[[\*\+\#o]\]/);
  var newContent = "";
  items.map(function(text) { newContent += "<li>" + text + "</li>"; });
  var tag = type == "#" ? "ol" : "ul";
  return prefix + "<" + tag + ">" + newContent + "</" + tag + ">";
}
BBCoder.prototype.getHTMLForQuote = function(fullBB, prefix, from, content) {
  var fromText = from ? " von " + from : "";

  return prefix + '<div class="quote"><div class="quote_h"> Zitat'
       + fromText + ': </div><div class="quote_p"> '
       + content + ' </div></div>';
}

BBCoder.prototype.getDecryptedText = function(fullBB, method, content) {
  return "<span class=\"bb_decrypted\">"
       + content.decrypt(method * 1).replace(/</g, "&lt;")
       + "</span>";
}
BBCoder.prototype.getHTMLForNewDirection = function(all, name, id, position, text) {
	  var TopDirection = /\[newTopDirection=([\w\W]*?)\|?\d*?\]/ig.exec(document.getElementById("Profile_InformationSnipplet").innerHTML);
	  if (id.indexOf("Mod-Profile-Information")<0 && document.getElementById(id) || id=="Mod-Profile-Information-"+TopDirection[1]) {
	  if (document.URL.indexOf("http://www.schuelervz.net/Profile/")<0) {
      return all;
      }
      else {
	  if (position) {position=position-1;
	  var element = document.getElementById(id).getElementsByTagName("dt")[position];}
	  else {
	  var element = document.getElementById(id).firstChild;}
	  var dt=document.createElement("dt");
	  dt.innerHTML=name+":";
	  document.getElementById(id).insertBefore(dt, element);
	  var dd=document.createElement("dd");
	  dd.innerHTML=text;
	  document.getElementById(id).insertBefore(dd, element);
	  return "";}
	  }
	  else {
	  return "Fehlerhafte ID";
	  }
}

BBCoder.prototype.transformDate = function(datestring) {
  var newstr = "", d = new Date();
  function fillWithZero(val) { //TODO: add to class Number/String
    return val < 10 ? "0" + val : val;
  }
  for(var i = 0; i < datestring.length; i++){
    switch (datestring[i]) {
      case "\\":
        i++;
        newstr += datestring[i];
        break;
      case "s": //Sekunden
        newstr += fillWithZero(d.getSeconds());
        break;
      case "s": //Sekunden
        newstr += d.getSeconds();
        break;
      case "i": //Minuten
        newstr += fillWithZero(d.getMinutes());
        break;
      case "i": //Minuten
        newstr += d.getMinutes();
        break;
      case "H": //Stunden
        newstr += fillWithZero(d.getHours());
        break;
      case "G": //Stunden
        newstr += d.getHours();
        break;
      case "d": //Monatstag
        newstr += fillWithZero(d.getDate());
        break;
      case "j": //Monatstag
        newstr += d.getDate();
        break;
      case "l": //Wochentag
        newstr += (["Sonntag", "Montag", "Dienstag", "Mittowch", "Donnerstag",
            "Freitag", "Samstag"])[d.getDay()]
        break;
      case "D": //Wochentag
        newstr += (["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"])[d.getDay()]
        break;
      case "n": //Monat
        newstr += fillWithZero(d.getMonth()+1);
        break;
      case "m": //Monat
        newstr += d.getMonth()+1
        break;
      case "M": //Monat
        newstr += (["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli",
            "August", "September", "Oktober", "November", "Dezember"])
            [d.getMonth()]
        break;
      case "F": //Monat
        newstr += (["Jan", "Feb", "März", "Apr", "Mai", "Jun", "Jul", "Aug",
            "Sept", "Okt", "Nov", "Dez"])[d.getMonth()]
        break;
      case "Y": //Jahr
        newstr += d.getFullYear()
        break;
      case "y": //Jahr
        newstr += (d.getFullYear()+"").substr(2)
        break;
      default:
        newstr += datestring[i];
    }
  }
  return newstr;
}

BBCoder.prototype.getHTMLForLink = function(fullBB, url, linktext){
  if(!url)
    url = linktext + "";
  if(url.search(/http\:\/\/|https\:\/\/|ftp\:\/\/|\/|\#|mailto\:/i)!==0)
    url = "http://" + url;
  return "<a href=\"" + url.replace(/\"/g, "&quot;") + "\" class=\"bblink\" "
    + "onclick=\"if(jautis_check_link) return jautis_check_link(this.href)\">"
    + linktext + "</a>";
}
BBCoder.prototype.getHTMLForWikiLink = function(fullBB, linkContent) {
  var seperationPosition = -1;
  if (linkContent.indexOf("|") > -1) {
    seperationPosition = linkContent.indexOf("|");
  } else if (linkContent.indexOf(" ") > -1) {
    seperationPosition = linkContent.indexOf(" ");
  }
  var url = linkContent.substr(0, seperationPosition);
  var text = linkContent.substr(seperationPosition + 1);
  return seperationPosition > 0
      ? this.getHTMLForLink(fullBB, url, text)
      : fullBB;
}

BBCoder.prototype.getHTMLForInlineLink = function(url, position, code) {
  var closingFound = code.lastIndexOf(">", position);
  var openingFound = code.lastIndexOf("<", position);
  if (openingFound < 0 || openingFound < closingFound) {
    //outside HTML
    return this.getHTMLForLink(url, url, url);
  } else {
    return url;
  }
}

BBCoder.prototype.getHTMLForImage = function(fullBB, align, source) {
  var data = source.replace(/[\s\n\"]/g, "").split("|");
  var src = data[0], width = data[1], height = data[2];

  //Rechte?
  var domain = /\:\/\/[^\/]*?(\w+\.\w+)\//.exec(src);
  var allowedDomains;
  if(!domain)
    return '<img src="" width="100" height="100" title="Bildardesse ungültig!">';
  if(userSettings) {
    allowedDomains = userSettings.get("bbimageallowed");
  }
  if(!allowedDomains || !allowedDomains.forEach) {
    allowedDomains = ["imagevz.net"];
  }
  if(allowedDomains.indexOf(domain[1]) < 0) {
    var returnstr = '<img src="http://jautis.net/images/'
          + 'unlock_image.jpg" title="Bildaufruf verweigert. Domain:'
          + domain[1] + '" onclick="bb_code_add_image_domain(\''
          + domain[1] + '\'); return false" domain="' + domain[1]
          + '"  realsrc="' + src + '" class="bb_locked_image"';
  } else {
    var returnstr = '<img src="' + src+'" title="' + src + '"';
  }
  if(width) {
    returnstr += " width=\"" + width + "\"";
  }
  if(height) {
    returnstr += " height=\"" + height + "\"";
  }
  if(align) {
    returnstr += " align=\"" + align + "\"";
  }
  return returnstr+'>';
}

BBCoder.prototype.getHTMLForTable = function(fullBB, prefix, attributes, tableContent) {
  var tableHTML = attributes.indexOf("border") > -1
      ? "<table class=\"bbhasborder\">" : "<table>";
  var tableRows = tableContent.split("[tr]");
  for (var row = tableRows[0].trim() == "" ? 1 : 0; row < tableRows.length; row++) {
    tableHTML += BBCoder.prototype.getHTMLForTableRow(tableRows[row]);
  }
  tableHTML += "</table>";
  return prefix + tableHTML;
}
BBCoder.prototype.getHTMLForTableRow = function(rowContent) {
  var cells = rowContent.split("[td]"); //TODO: attributes
  var rowHTML = "<tr>";
  for (var cell = cells[0].trim() ? 0 : 1; cell < cells.length; cell++) {
    rowHTML += "<td>" + cells[cell] + "</td>";
  }
  rowHTML += "<tr>";
  return rowHTML;
}
BBCoder.prototype.getHTMLForCSS = function (fullBB, prefix, csscode, content) {
  csscode = csscode.replace(/[^\w:;\s-\"]/, "")
                .replace(/([^-])*?(border-radius|border-colors)/, "$1-moz-$2");
  cssCommands = csscode.split(";");

  var returnCSS = "";
  for (var i = 0; i < cssCommands.length; i++) {
    if (cssCommands[i].replace(/-(left|top|right|bottom)/g, "")
        .search(/^\s*(border|border-color|-moz-border-colors|border-width|border-style|-moz-border-radius|color|display|text-align|background|background-image|background-color|background-position|background-repeat|margin|padding)\s*:/)==0){
      returnCSS += cssCommands[i].replace(/\"/g, "&quot;") + ";";
    }
  }
  return prefix + "<div style=\"" + returnCSS + "\">" + content + "</div>";
}

/**
 * This Method parses a string
 *
 */
String.prototype.parseBB = function(){
  var bbcoder = new BBCoder();
  text = bbcoder.parseString(this);
  return text;
}

window.addEventListener("load", function parseBB_settings_loading_function(){
if(userSettings)
  userSettings.register("bbimageallowed", ["imagevz.net"])
unsafeWindow.bb_code_add_image_domain=function(domain){
  if(userSettings)
    setTimeout(function() {
      allowedDomains = userSettings.get("bbimageallowed");
      if(!allowedDomains || !allowedDomains.forEach)
        allowedDomains = ["imagevz.net"]
      allowedDomains.push(domain)
      userSettings.set("bbimageallowed", allowedDomains);
    }, 1);
  for(var i=0; i < document.images.length; i++)
    if(document.images[i].className == "bb_locked_image"
            && document.images[i].getAttribute("domain") == domain) {
      document.images[i].setAttribute("src",
                                   document.images[i].getAttribute("realsrc"));
      document.images[i].className = "";
      document.images[i].title = "Domain soeben entsprerrt";
    }
}
}, true);

/********************************************************************
 * 5. Einstellungen
 *
 * Klassen:
 * - Settingsobject
 *
 * Globale Variablen:
 * - globalSettings
 * - userSettings
 ********************************************************************/
/**
 * creates a new Settings instance.
 * @param prefix (optional) the prefix to be used. If it is not set, "" is taken
 */
function Settingsobject() {
  if(arguments[0]) {
    this.prefix = arguments[0];
  }
  this.defaultValues = {}; //single user
}
//
Settingsobject.prototype.prefix = "";
// an object of formatted strings, private
Settingsobject.prototype.defaultValues = {};

if(typeof GM_setValue != "undefined") {
  // Greasemonkey
  Settingsobject.prototype.set = function(name, value){
    GM_setValue(this.prefix+""+name, this.formatValue(value));
    debug("setting " + name + " to " + this.formatValue(value).substr(0, 500))
  }

  Settingsobject.prototype.get = function(name) {
    var value = GM_getValue(this.prefix + "" + name, this.getDefault(name));
    return this.unformatValue(value);
  }
} else {
  // not Greasemonkey
  /**
   * cookie syntax:
   * propertyname/propertyvalue/propertyname/propertyvalue...
   * the propertynames/-values are decoded with decodeURIComponent
   */
  debug("not GM");
  Settingsobject.prototype.set = function(name, value) {
    var stringValue = encodeURIComponent(this.formatValue(value));
    var realName = encodeURIComponent(name);
    var insert = false; // if the value was already insert
    var cookieData = new RegExp("jautis_" + encodeURIComponent(this.prefix) + "=([^;]*)")
                                           .exec(document.cookie) || ["", ""];
    var array = cookieData[1].split("/");
    if(array.length % 2 == 1) {
      //mosly length == 1 and array[0] == "" because the cookie was empty
      array.pop();
    }
    for(var i = 0; i < array.length - 1 && !insert; i += 2) {
      if(array[i] == realName) {
        array[i + 1] = stringValue;
        insert = true;
      }
    }

    if (!insert) {
      array.push(realName);
      array.push(stringValue);
    }
    document.cookie = "jautis_"+ encodeURIComponent(this.prefix) + "=" + array.join("/");
  }

  Settingsobject.prototype.get = function(name) {
    var stringValue = this.getDefault(name);
    var realName = encodeURIComponent(name);
    var cookie = (new RegExp("jautis_" + encodeURIComponent(this.prefix) + "=([^;]*)")
                                           .exec(document.cookie) || ["", ""])[1];
    var array = cookie.split("/");
    for(var i = 0; i < array.length - 1; i += 2) {
      if(array[i] == realName) {
        stringValue = array[i + 1];
      }
    }
    return this.unformatValue(decodeURIComponent(stringValue));
  }
}

/**
 * gets the registered default value for a Setting.
 */
Settingsobject.prototype.getDefault = function(name) {
  if(this.defaultValues[name] !== undefined) {
    var defaultValue = this.defaultValues[name];
  } else {
    var defaultValue = "{o}null";
  }
  return defaultValue;
}

/**
 * turns a object into a string that can be saved
 */
Settingsobject.prototype.formatValue = function(value) {
  if(value === undefined) {
    value = "{o}";
  } else if (typeof value == "boolean")
    value = value ? "{b}1" : "{b}0";
  else if (typeof value == "string")
    value = "{s}" + value;
  else if (typeof value == "number")
    value = "{n}" + value;
  else if (value && typeof value.toSource == "function")
    value = "{o}" + value.toSource();
  return value;
}

/**
 * turns the string back into an object
 */
Settingsobject.prototype.unformatValue = function(string) {
  var value;
  if(!string || !string.indexOf) {
    value = string;
  } else if (string.indexOf("{o}") == 0) {
    try{
      value = eval("("+string.substr(3)+")");
    }catch(e){
      debug("Fehler beim  Aufrufen der Variable :"
        + "Beim umwandeln in Objekt trat ein Fehler auf. \n\n"
        + e + "\n\ncode:\n" + string.substr(3))
      value = null;
    }
  } else if (string.indexOf("{b}")==0) {
    value = !!parseInt(string.substr(3));
  } else if (string.indexOf("{n}")==0) {
    value = parseFloat(string.substr(3));
  } else if (string.indexOf("{s}")==0) {
    value = string.substr(3);
  } else {
    value = string;
  }
  return value;
}

Settingsobject.prototype.register = function(name, defaultValue){
  this.defaultValues[name] = this.formatValue(defaultValue);
  return true;
}

var globalSettings = new Settingsobject("global.");

if (USERIDS) {
  var userSettings = new Settingsobject();
  userSettings.prefix = USERIDS + "."
} else {
  userSettings=false;
}

/********************************************************************
 * 6. Themes
 *
 * Klassen:
 *  - Theme
 *
 * Einstellungen:
 *  - userSettings: themeData.<id>
 *  - userSettings: themes = Theme[];
 *
 ********************************************************************/

(userSettings || globalSettings).register("themes", []);

/* source is stored in userSettings.themeData.<id> */
function Theme(id, name, author, image) {
  this.id = id + "";
  this.name = name + "";
  this.author = author + "";
  this.image = image + "";
}
Theme.prototype.id = null;
Theme.prototype.name = null;
Theme.prototype.author = null;
Theme.prototype.image = null;
Theme.prototype.source = null;

/**
 * this method creates the CSS-Style for the given theme
 * @return a String for the CSS style
 */
Theme.prototype.getStyle = function() {
  return globalSettings.get("themeData." + this.id);
};

/**
 * this method displayes the current page in the given theme.
 */
Theme.prototype.activate = function() {
  var styleelement = document.getElementById("themestyle");

  if(!styleelement){
    styleelement    = document.createElement("style")
    styleelement.id = "themestyle";
    styleelement.setAttribute("rel","stylesheet"); //für tagName==link
    styleelement.setAttribute("type","text/css");
    document.getElementsByTagName("head")[0].appendChild(styleelement);
  }

  styleelement.innerHTML = this.getStyle();
};
Theme.prototype.toSource = function() {
  return "new Theme(" + this.id.toSource() + ", " + this.name.toSource() + ", "
      + this.author.toSource() + ", " + this.image.toSource() + ")";
}

Theme.getThemes = function() {
  return userSettings.get("themes");
}

Theme.installTheme = function(theme, themeCSS) {
  if (!theme instanceof Theme) {
    throw "Falscher Themetyp";
  }
  var themes = Theme.getThemes();
  var installed = false;
  for (var i = 0; i < themes.length && !installed; i++) {
    if (themes[i].id == theme.id) {
      themes[i] = theme;
      installed = true;
    }
  }
  if (!installed) {
    themes.push(theme);
  }
  globalSettings.set("themeData." + theme.id, themeCSS);
  (userSettings || globalSettings).set("themes", themes);
}

Theme.uninstallTheme = function(theme) {
  var themes = Theme.getThemes();
  debug ("uninstalling " + theme.id);
  for (var i = 0; i < themes.length; i++) {
    if (themes[i].id == theme.id) {
      themes.splice(i, 1);
      i--;
    }
  }
  (userSettings || globalSettings).set("themes", themes);
}

/********************************************************************
 * 7. Tooltip
 ********************************************************************/
if(userSettings) {
  userSettings.register("tooltipopacity", 0.9);
}

(function(){

function createTooltipElement(){
  debug("Tooltipelement wird erstellt",2)
  var elm=document.createElement("div");
  elm.id="tooltipelm";
  elm.innerHTML="<table><tr><td><img src=\"\" id=\"tooltipimg\"></td><td id=\"tooltiptext\"></td></tr></table>";
  document.body.appendChild(elm)
  document.body.addEventListener("mousemove",movetooltip,true)
  setInterval(renderTooltipVisibility,100)
  debug("Tooltipelement erstellt!",2)
  return true;
}
function movetooltip(evt){
  document.getElementById("tooltipelm").style.left=evt.clientX+5+"px"
  document.getElementById("tooltipelm").style.top =evt.clientY+"px"
}
CSS("#tooltipelm {border :2px solid black; width : 400px; "
                + "background : #efff65; position : fixed; color : black;"
                + "opacity : 0.9; display:none; z-index:900}");


//aktuelle ID des Tooltipinhalts.
var tooltip_currentid = false;
//Objekt des aktuellen Tooltips.
var tooltip_currentObject = false;
//Was der Tooltip sein solte (Wird bei mousemove geändert)
var tooltip_shouldBeObject = false;
/*//id des Elements das geladen werden soll. Um ein Überschneiden der Timeouts zu verhindern.
var tooltip_soonid=false;*/


var currentTooltipVisibility=0,desiredTooltipVisibility=0;
//für setIntervall.
function renderTooltipVisibility(){
  if(currentTooltipVisibility==desiredTooltipVisibility)
    return;//nichts zu tun;
  currentTooltipVisibility +=(currentTooltipVisibility<desiredTooltipVisibility) ? 1 : -1;
  tooltipVisibility(currentTooltipVisibility)
}

function tooltipVisibility(x){//0:unsichtbar; 5:max
  var elm = document.getElementById("tooltipelm")
  if(!elm)
    return;
  if(x<1){
    elm.style.display = "none";
    return;
  }
  elm.style.display = "block";
  var maxopacity = userSettings ? userSettings.get("tooltipopacity") : 0.9;
  elm.style.opacity = maxopacity / 5 * x;
}

/**
 * Class to handle Tooltips
 *
 * tooltip.onshow can be a funtion that is called when the tooltip is
 * displayed. You can change the text then.
 * tooltip.delay (in millisecons) says how long it will take until the tooltip
 * is displayed
 *
 * @author Michael Z.
 * @param element element for which the Tooltip should be
 * @param text HTML-Content of the Tooltip (optional)
 * @param image image of the Tooltip (optional)
 */
function Tooltip(elm) {

  //public
  this.element = elm;

  this.contentid = Math.floor(Math.random()*100000000000)


  //für Funktionen, in denen this schon anderst belegt ist (event listener)
  var tooltipobject = this;

  //Bilder und Text
  this.text = Tooltip.arguments.length > 1 ? Tooltip.arguments[1] : "";
  this.image  = Tooltip.arguments.length > 2 ? Tooltip.arguments[2] : false;


  function showtooltip(mousemoveevt){
    tooltip_shouldBeObject = tooltipobject;
  }
  elm.addEventListener("mousemove", showtooltip, false);
}

Tooltip.prototype.wirdangezeigt = false;

Tooltip.prototype.delay = 500//"auto";//in millisek

//public, function
Tooltip.prototype.onshow=null;

Tooltip.prototype.setText = function(text) {
  this.text = text;
  if(this.wirdangezeigt)
    this.renderTooltipText();
}
Tooltip.prototype.getText = function() {
  return this.text;
}

Tooltip.prototype.setImage = function(image) {
  this.image = image;
  if(this.wirdangezeigt)
    this.renderTooltipImg();
}
Tooltip.prototype.getImage = function() {
  return this.image;
}


//privat
Tooltip.prototype.renderTooltipImg=function(){
  document.getElementById("tooltipimg").style.display=this.image ? "" : "none";
  if(this.image)
    document.getElementById("tooltipimg").src=this.image;
}
//privat
Tooltip.prototype.renderTooltipText=function(){
  document.getElementById("tooltiptext").innerHTML=this.text;
}

Tooltip.prototype.hide=function(){
  hidetooltip();
  this.wirdangezeigt=false;
}

Tooltip.prototype.show = function(){
  if(!document.getElementById("tooltipelm"))
    createTooltipElement();
  if(this.onshow){
    try{
      this.onshow(this);
    }catch(e){}
  }

  this.renderTooltipText();
  this.renderTooltipImg();
  this.wirdangezeigt=true;
}

window.Tooltip = Tooltip;

//BEGIN check if tooltip should be displayed
function tooltip_mousemove1(){
  tooltip_shouldBeObject=false;
}

function tooltip_mousemove2(){
  //anzeigen?
  if(desiredTooltipVisibility==0 && tooltip_shouldBeObject && tooltip_shouldBeObject.delay!=0){
    var currentshouldbe=tooltip_shouldBeObject;
    setTimeout(function(){
      if(tooltip_shouldBeObject!==currentshouldbe)
        return;
      desiredTooltipVisibility=5;
      tooltip_shouldBeObject.show();
    },tooltip_shouldBeObject.delay * 1 )
  }
  else
    desiredTooltipVisibility = tooltip_shouldBeObject ? 5 : 0;

  tooltip_currentObject=tooltip_shouldBeObject
}

document.body.addEventListener("mousemove", tooltip_mousemove1,true);
document.body.addEventListener("mousemove", tooltip_mousemove2,false);
//END check if tooltip should be displayed
})()

/********************************************************************
 * 8. Dialog-Klassen
 ********************************************************************/

/* class JatisDialog:
 *  - JautisDialog(String title[, DOMElement contentElement])
 *  - getWidth()
 *  - getHeight();
 *  - getLeft();
 *  - getTop();
 *  - setWidth(int width)
 *  - setHeight(int width);
 *  - setLeft(int width);
 *  - setTop(int width);
 *  - center()
 *  - sizeTo(width, height[, boolean doCenter = false])
 */
CSS(".jautisdialog { border:2px solid #DC1E64; background:#eee;"
    + "position:fixed; z-index:120;color:black;} "
  + ".jautisdialogtitle { margin: .2em .3em; padding:.1em;  border-bottom: 1px solid #DC1E64;"
    + "cursor:default; position:absolute;top:0;left:0;right:0;height:1.3em;-moz-user-select:none} "
  + ".jautisdialogcontent{ padding:.2em;position:absolute; bottom:0;left:0;"
    + "right:0;top:2em;overflow:auto} "
  + ".jautisdialog_resize_n{ position:absolute; top:-3px; right:3px; left:3px; "
    + "height:4px; cursor:n-resize; } "
  + ".jautisdialog_resize_s{ position:absolute; bottom:-3px; right:3px; "
    + "left:3px; height:4px; cursor:s-resize; } "
  + ".jautisdialog_resize_e{ position:absolute; right:-3px; top:3px; "
    + "bottom:3px; width:4px; cursor:e-resize; } "
  + ".jautisdialog_resize_w{ position:absolute; left:-3px; top:3px; "
    + "bottom:3px; width:4px; cursor:w-resize; } "
  + ".jautisdialog_resize_nw{ position:absolute; left:-3px; top:-3px; "
    + "width:6px; height:6px; cursor:nw-resize; } "
  + ".jautisdialog_resize_nw{ position:absolute; left:-3px; top:-3px; "
    + "width:6px; height:6px; cursor:nw-resize; } "
  + ".jautisdialog_resize_ne{ position:absolute; top:-3px; right:-3px; "
    + "width:6px; height:6px; cursor:ne-resize; } "
  + ".jautisdialog_resize_sw{ position:absolute; left:-3px; bottom:-3px; "
    + "width:6px; height:6px; cursor:sw-resize; } "
  + ".jautisdialog_resize_se{ position:absolute; right:-3px; bottom:-3px; "
    + "width:6px; height:6px; cursor:se-resize; } "
  + ".jautisdialog_closebutton { position:absolute; top:2px; right:2px; "
    + "width:20px; height:20px; background:url({IMG:closebutton.png}); }"
  + ".jautisdialog label, .jautisdialog button[label] {color: inherit}, .jautisdialog button {color: inherit}");
function JautisDialog(title) {
  this.dialogElement       = document.createElement("div");
  this.dialogElement.className = "jautisdialog";
  document.body.appendChild(this.dialogElement);

  //Title
  var titleElement      = document.createElement("div")
  this.dialogElement.appendChild(titleElement)
  this.titleText         = document.createTextNode(title);
  titleElement.appendChild(this.titleText);
  titleElement.className= "jautisdialogtitle";
  
  this.contentContainer = document.createElement("div");
  this.contentContainer.className = "jautisdialogcontent"
  this.dialogElement.appendChild(this.contentContainer);

  this.content = arguments[1] || document.createElement("div");
  this.contentContainer.appendChild(this.content);

  var me = this;
  ["n","ne","e","se","s","sw","w","nw"].forEach(function(direction) {
    var elm = document.createElement("div");
    elm.className = "jautisdialog_resize_" + direction;
    me.dialogElement.appendChild(elm);
  });

  var elm = document.createElement("div")
  elm.className = "jautisdialog_closebutton";
  this.dialogElement.appendChild(elm);

  this.sizeTo(300, 250, true);


  this.close = function(){
    if(this.onclose){
      try{
        if(this.onclose()===false) return;
      }catch(e){}
    }
    document.body.removeChild(this.dialogElement);
  }

  var me = this;
  this.dialogElement.addEventListener("mousedown",
      jautisHint(this, "mousedown"), true);
}
JautisDialog.prototype.setTitle = function(x){
  this.titleText.data = x;
}
JautisDialog.prototype.getTitle = function(){
  return this.titleText.data;
}
JautisDialog.prototype.getLeft = function() {
  return parseInt(this.dialogElement.style.left);
}

JautisDialog.prototype.setLeft = function(left) {
  this.dialogElement.style.left = left*1 + "px";
}

JautisDialog.prototype.getTop = function() {
  return parseInt(this.dialogElement.style.top);
}

JautisDialog.prototype.setTop = function(top) {
  this.dialogElement.style.top = top*1 + "px";
}

JautisDialog.prototype.getWidth = function() {
  return parseInt(this.dialogElement.style.width);
}

JautisDialog.prototype.setWidth = function(width) {
  this.dialogElement.style.width = Math.max(width + 0, 60) + "px";
}

JautisDialog.prototype.getHeight = function() {
  return parseInt(this.dialogElement.style.height);
}

JautisDialog.prototype.setHeight = function(height) {
  this.dialogElement.style.height = Math.max(height + 0, 60) + "px";
}

JautisDialog.prototype.sizeTo = function(width, height) {
  var doCenter = arguments.length > 2 && arguments[2];
  this.setWidth(width);
  this.setHeight(height);
  if (doCenter) {
    this.center();
  }
}

JautisDialog.prototype.center = function() {
  this.setLeft((window.innerWidth - this.getWidth()) / 2);
  this.setTop((window.innerHeight - this.getHeight()) / 2);
}

JautisDialog.prototype.mousedown = function(evt){
  if (evt.target.className == "jautisdialog_closebutton") {
    this.close();
  } else if (evt.target.className
          && evt.target.className.indexOf("jautisdialog_resize_") == 0) {
    var dir = evt.target.className.substr(20);
    JautisDialog.resizer.old_height= this.getHeight();
    JautisDialog.resizer.old_width = this.getWidth();
    JautisDialog.resizer.old_x     = this.getLeft();
    JautisDialog.resizer.old_y     = this.getTop();
    JautisDialog.resizer.resizing  = true;
    JautisDialog.resizer.dialog    = this;
    JautisDialog.resizer.resize_v  = 0;
    JautisDialog.resizer.resize_h  = 0;
    if( dir.indexOf("n") > -1) JautisDialog.resizer.resize_v = -1;
    if( dir.indexOf("s") > -1) JautisDialog.resizer.resize_v =  1;
    if( dir.indexOf("w") > -1) JautisDialog.resizer.resize_h = -1;
    if( dir.indexOf("e") > -1) JautisDialog.resizer.resize_h =  1;
  } else if (evt.target.className == "jautisdialogtitle"){
    JautisDialog.mover.grab_x = evt.layerX
    JautisDialog.mover.grab_y = evt.layerY
    JautisDialog.mover.moving = true;
    JautisDialog.mover.dialog = this;
  }
}
JautisDialog.mousemoveGlobal = function(evt) {
  if (JautisDialog.mover.moving) {
    JautisDialog.mover.dialog.setLeft(evt.clientX - JautisDialog.mover.grab_x)
    JautisDialog.mover.dialog.setTop(evt.clientY - JautisDialog.mover.grab_y)
    return;
  }

  if(!JautisDialog.resizer.resizing)
    return;
  if(JautisDialog.resizer.resize_h < 0) {
    JautisDialog.resizer.dialog.setLeft(evt.clientX)
    JautisDialog.resizer.dialog.setWidth(JautisDialog.resizer.old_width
      + JautisDialog.resizer.old_x -  evt.clientX);
  } else if(JautisDialog.resizer.resize_h > 0) { //TODO
    JautisDialog.resizer.dialog.setWidth(evt.clientX - JautisDialog.resizer.old_x);
  }

  if(JautisDialog.resizer.resize_v < 0){
    JautisDialog.resizer.dialog.setTop(evt.clientY);
    JautisDialog.resizer.dialog.setHeight(JautisDialog.resizer.old_height
      + JautisDialog.resizer.old_y - evt.clientY);
  }
  if(JautisDialog.resizer.resize_v > 0)
    JautisDialog.resizer.dialog.setHeight(evt.clientY - JautisDialog.resizer.old_y);

}
JautisDialog.mouseupGlobal = function(evt){
  JautisDialog.resizer.resizing = false;
  JautisDialog.mover.moving = false;
}
document.documentElement.addEventListener("mousemove", JautisDialog.mousemoveGlobal, true)

document.documentElement.addEventListener("mouseup"  , JautisDialog.mouseupGlobal  , true)

JautisDialog.mover={
  moving:false,
  dialog:null,
  grab_x:0,
  grab_x:0
}

JautisDialog.resizer={
  resizing:false,
  dialog:null,
  old_x:0,
  old_y:0,
  old_width:0,
  old_height:0,
  resize_v:0,// 1: oben, 0:nix, -1:unten
  resize_h:0 // 1: rechts, 0:nix, -1:links
}



/********************************************************************
 * 9. Einstellungsmenü
 ********************************************************************/


/**
 * this class represents a panel in the jautis settings dialog.
 * @param panelName the name of the panel. If two panels have the same callback
 *        they are kombined
 * @param panelTitle The label to be displayed on the top of the panel.
 * @param onloadcallback a function that is called when the panel is load. It
 *        gets one parameter with the Element into that it should set its //TODO
 *        elements for the settings. It may return an object that is send
 *        to the save callback when the panel shall e saved.
 * @param savecallback a function with no arguments, that should save the
 *        current panel. If the constructing function returned an object, it
 *        is passed to theis funciton as first argument.
 */
function JautisSettingsPanel(panelName, panelTitle, onloadcallback){
  this.zindex      = 500;
  this.name        = panelName;
  this.title       = panelTitle;
  this.loadcallback= onloadcallback;
  this.savecallback= JautisSettingsPanel.arguments[3]
      || function(){ debug(this.title + ":\nSpeichern nicht möglich!"
       + "Keine Funktion zum Speichern registriert...")};
}
JautisSettingsPanel.prototype.loadForElement = function(element) {
  this.savedata = this.loadcallback(element);
}
/**
 * @return if the settings were saved correctly
 */
JautisSettingsPanel.prototype.save = function(){
  if (typeof this.savecallback != "function") {
    return true;
  }
  try {
    return this.savecallback(this.savedata);
  } catch(e) {
    return confirm("Fehler beim Speichern!\n\n" + e + "\n\nIgnorieren?");
  }
}


/**
 * Object to handle the Settings of Modules
 * @author Michael Z.
 */
var JautisSettings = {
  panels:[],
  dialog:false
};
JautisSettings.addPanel=function(panel){
  JautisSettings.panels.push(panel)
}

JautisSettings.show = function(){
  if (JautisSettings.dialog || !JautisDialog) {
    return;
  }

  var tabs      = document.createElementNS(XULNS, "tabs")
  var tabpanels = document.createElementNS(XULNS, "tabpanels")
  tabpanels.setAttribute("flex", "1")

  //Alle Tabs auslesen...
  //tabs with low zindex go left (?) XXX
  JautisSettings.panels.sort( function(a,b) {
    return a.zindex < b.zindex ? 1 : a.zindex > b.zindex ? -1 : 0;
  } );

  //to find old tabs again
  var tabPanelsHash = {};

  JautisSettings.panels.forEach( function(panel) {
    if (typeof tabPanelsHash[panel.name] == "undefined") {
      var tab     = document.createElementNS(XULNS, "tab")
      tab.setAttribute("label", panel.title)
      tabs.appendChild(tab)

      var tabpanel= document.createElementNS(XULNS, "tabpanel");
      tabpanel.setAttribute("flex", "1");
      tabpanel.setAttribute("orient", "vertical");
      tabpanels.appendChild(tabpanel);
      tabPanelsHash[panel.name] = tabpanel;
    } else {
      var tabpanel = tabPanelsHash[panel.name];
    }

    try {
      var box = document.createElementNS(XULNS, "scrollbox");
      box.setAttribute("flex", "1");
      box.setAttribute("orient", "vertical");
      box.style.overflow = "auto";
      panel.loadForElement(box);
      tabpanel.appendChild(box);
    } catch(e) {
      var errorLabel  = document.createElementNS(XULNS, "label");
      errorLabel.setAttribute("value", "Fehler beim Aufrufen des Tabs: " + e);
      tabpanel.appendChild(errorLabel);
    }
  });

  var tabbox    = document.createElementNS(XULNS, "tabbox");
  tabbox.setAttribute("flex", "1");
  tabbox.appendChild(tabs);
  tabbox.appendChild(tabpanels);

  var hbox      = document.createElementNS(XULNS, "hbox");
  var button    = document.createElementNS(XULNS, "button");
  button.setAttribute("label", "Abbrechen");
  button.addEventListener("command", function(){
    JautisSettings.dialog.close();
  }, true);
  hbox.appendChild(button);

  var spacer    = document.createElementNS(XULNS, "spacer");
  spacer.setAttribute("flex", "1");
  hbox.appendChild(spacer);

  //apply
  var button    = document.createElementNS(XULNS, "button");
  button.setAttribute("label", "Anwenden");
  button.addEventListener("command", function(){
    JautisSettings.save();
  }, true);
  hbox.appendChild(button);

  //save and close
  var button    = document.createElementNS(XULNS, "button");
  button.setAttribute("label", "Speichern");
  button.addEventListener("command", function() {
    if (JautisSettings.save()) {
      JautisSettings.dialog.close(true);
    }
  }, true);
  hbox.appendChild(button);

  var vbox          = document.createElementNS(XULNS, "vbox");
  vbox.style.width  = "100%";
  vbox.style.height = "100%";
  vbox.appendChild(tabbox);
  vbox.appendChild(hbox);

  JautisSettings.dialog = new JautisDialog("jautis Einstellungen", vbox);
  JautisSettings.dialog.onclose = function() {
    JautisSettings.dialog = false;
    return true;
  }
  JautisSettings.dialog.sizeTo(Math.min(window.innerWidth - 40, 500),
      Math.min(window.innerHeight - 40, 500), true);

};//JautisSettings.show

/**
 * saves the settings
 * @author Michael Z.
 * @date 2009-09-28
 * @return if all save functions returned true
 */
JautisSettings.save = function() {
  if (!JautisSettings.dialog) {
    throw "Settings not open!";
  }
  // do not use standard functions, we have to walk through all elements
  var result = true;
  JautisSettings.panels.forEach(function (panel) {
    result = result && panel.save() !== false;
  });
  return result;
}

/* Usage of these Parts:
  In opening function:
  function(element) {
    var data = {};
    data.test = JautisSettings.checkbox("Test", UserSettings.getValue("test"));
    element.appendChild(data.test);
  }
  In saving function:
  function (data) {
    setAttribute(data.getValue());
  }

  Interface for all Elements:
  getValue()
  setValue(v);
  getLabel()
  setLabel(l)
*/

/*
 * creates a good formatted checkbox that can be insert anywhere and easily
 * saved.
 * @return the checkbox implementing the JautisSettingElements interface
 */
JautisSettings.checkbox = function(label, checked) {
  var box = document.createElement("label");
  box.className = "jautisSettings checkboxLabel";
  var checkbox = document.createElement("input");
  checkbox.setAttribute("type", "checkbox");
  if (checked) {
    checkbox.setAttribute("checked", "checked");
  }
  box.appendChild(checkbox);
  var font = document.createElement("font");
  var text = document.createTextNode(label);
  font.appendChild(text);
  box.appendChild(font);
  delete font;

  box.getValue = function() {
    return checkbox.checked;
  }
  box.setValue = function(checked) {
    checkbox.checked = checked;
  }

  box.getLabel = function() {
    return text.data;
  }
  box.setLabel = function(label) {
    text.data = label;
  }

  return box;
}

CSS(".jautisSettings.checkboxLabel {display:block;}")

/********************************************************************
 * 10. Imagemanager
 ********************************************************************/


/**
 * Imagemanager
 * class to manage Images for e.g. Icons
 * The images have to be uploaded on the jautis server.
 * It is also possible to use this for sound files.
 *
 * @param id path of the image on the jautis server.
 * @user Michael Z.
 * @date 2009-03-27
 */

const IMAGEMANAGER_UPDATEINTERVAL = 7*24*60*60*1000;//7 Tage, in Millisekunden
function Imagemanager (id) {
  this.id = id;
}

/** the name of the image as it is saved on the server, e.g. image.png */
Imagemanager.prototype.id = null
/* called when a Image of the current manager was load
data = {id:..., data:...}
*/
Imagemanager.prototype.onload = function(data){}

/** is false if the image will be loaded and you should watch with onload.*/
Imagemanager.prototype.isActual = function() {
  var settingname = "image." + this.id;
  var time = globalSettings.get(settingname + ".date");
  return time
      && time.getTime() > Date.now() - IMAGEMANAGER_UPDATEINTERVAL;
}

/**
 * gets the data-url of an image
 * @param id the ID of the image in the current album
 */
Imagemanager.prototype.getImage = function() {
  var settingname = "image." + this.id;

  var source = globalSettings.get(settingname + ".data");

  if(!this.isActual()) {
    this.downloadImage();
  }
  return source || "";
}

/* private */
Imagemanager.prototype.downloadImage = function() {
  var path = JAUTIS_SERVER + "base64/" + encodeURI(this.id);
  debug(path);

  if (typeof GM_xmlhttpRequest != "undefined") {
    GM_xmlhttpRequest({
      method : "get",
      url : path,
      onload : jautisHint(this, "reciveImage"),
      onerror:debug
    });
  } else {
    debug("Kann das Bild nicht anfordern:"
      + "Keine Möglichkeit gefunden auf den Server zuzugreifen!");
  }
}

/* private */
Imagemanager.prototype.reciveImage = function(responseDetails) {
  if (responseDetails.status == 200) {
    var settingname = "image." + this.id;
    globalSettings.set(settingname + ".data", responseDetails.responseText);
    globalSettings.set(settingname + ".date", new Date());

    this.onload({"data":responseDetails.responseText, "id":this.id})
  }
}



/********************************************************************
 * 11. Theme definition
 ********************************************************************/

///@deprecated (Michael, 2009-08-25)
/// themes are now stored in the config

/********************************************************************
 * 12. Hauptmenü
 * globalVariables: mainNavigation
 ********************************************************************/
function MenuItem(description, link) {
  this.element = document.createElement("li");
  this.linkElement = document.createElement("a");
  this.element.appendChild(this.linkElement);

  this.linkElement.appendChild(document.createTextNode(description));
  this.linkElement.href = link;
}

/* private */
MenuItem.prototype.element = "";
/* private */
MenuItem.prototype.linkElement = "";
/* private */
MenuItem.prototype.subItem = null;

MenuItem.prototype.getElement = function() {
  return this.element
}

MenuItem.prototype.getLink = function() {
  return this.linkElement.href;
}
MenuItem.prototype.setLink = function(link) {
  this.linkElement.href = link;
}
MenuItem.prototype.getDescription = function() {
  return this.linkElement.firstChild.data;
}
MenuItem.prototype.setDescription = function(description) {
  this.linkElement.firstChild.data = description;
}


//for "Meine Seite ändern"
MenuItem.prototype.addSubItem = function(item) {
  if(this.linkElement.className != "right"
      && this.linkElement.className != "left") {
    try {
      this.element.appendChild(item.linkElement);
    } catch(e) {
    }

    this.linkElement.className = "left";
    item.linkElement.className = "right";
    this.element.className = "clearFix";

    this.subitem = item;
    item.element = this.element;
  }
}
MenuItem.prototype.getSubItem = function(){
  return this.subitem;
}
/*private class */
function OrginalMenuItem(element) {
  this.element = element;
  this.linkElement = element.getElementsByTagName("a")[0];
}
OrginalMenuItem.prototype = MenuItem.prototype;

mainNavigation = {
  //private;
  menuItems : [],
  //private; the element of the main Menu
  listElement : document.getElementById("Grid-Navigation-Main") || document.createElement("ul"),

  // loads the menu from the page
  loadMenuItemsFromPage : function() {
    var children = mainNavigation.listElement.childNodes;
    for(var childNumber = 0; childNumber < children.length; childNumber++) {
      if(children[childNumber].nodeType == 1) {
        mainNavigation.menuItems.push(
                new OrginalMenuItem(children[childNumber]));
      }
    }
  },


  /**
   * inserts a MenuItem to the mainMenu
   * @param item the item to be insert
   * @param before (optional) the item before it should be insert.
   */
  insert : function(item){
    if(mainNavigation.positionOfItem(arguments[1]) >= 0) {
      throw "item cannot be insert, it is allready";
    } else if(arguments[1]) {
      var pos = mainNavigation.positionOfItem(arguments[1]);
      if (pos < 0) {
        throw "Item not in List";
      }
      var after = mainNavigation.menuItems[pos].getElement();
      mainNavigation.listElement.insertBefore(item, after)
    } else {
      mainNavigation.listElement.appendChild(item.getElement());
      mainNavigation.menuItems.push(item);
    }
  },

  positionOfItem : function(item) {
    for (var i = 0; i < mainNavigation.menuItems.length; i++) {
      if (mainNavigation.menuItems[i] == item) {
        return i;
      }
    }
    return -1;
  },

  /**
   * gets the first item that contains the text. It does not check subitems
   * @param textPart the text to contain
   * @return the MenuItem object or <code>null</code> if nothing was found
   */
  getItemByText: function(textPart) {
    for (var i = 0; i < mainNavigation.menuItems.length; i++) {
      if (mainNavigation.menuItems[i].getDescription().indexOf(textPart) > -1) {
        return mainNavigation.menuItems[i];
      }
    }
    return null;
  }
}
mainNavigation.loadMenuItemsFromPage();


/********************************************************************
 * 13. BBCode Area
 ********************************************************************/

function BBCodeArea(element) {
  if (element.className && element.className.indexOf("bbcodearea") > 0) {
    throw new TypeError("BB-Code area schon für dieses Element erstellt!");
  }
  this.element = element;
  this.bbcoder = arguments.length > 1 && arguments[1] instanceof BBCoder
      ? arguments[1] : new BBCoder();
  this.parseForBBCode();
  this.renderClass();
  this.addButtons();
}

BBCodeArea.prototype.element = null;
BBCodeArea.prototype.source = null;
BBCodeArea.prototype.buttonslist = null;

//for editing
BBCodeArea.prototype.editCallback = null;
BBCodeArea.prototype.editSaveCallback = null;
/*
 * 0: disabled
 * 1: normal display
 * 2: waiting for data to load
 * 3: editing
 * 4: currently saving
 */
BBCodeArea.prototype.editingStatus = 0;

BBCodeArea.prototype.parseForBBCode = function() {
  //load source form element
  this.source = "";
  var hasHTML = false;
  for (var i = 0; i < this.element.childNodes.length; i++) {
  //while (this.element.firstChild) {
    var node = this.element.childNodes[i];
    if (node.nodeType == 3) {
      this.source += node.textContent.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "");
    } else if (node.nodeType == 1 && node.tagName == "BR") {
      this.source += "\n";
    } else if (node.nodeType == 1) {
      hasHTML = true;
    }
    //this.element.removeChild(node);
  }
  this.source = this.source.trim();
  if (!hasHTML) {
    var html = this.bbcoder.parseString(this.source);
    this.element.innerHTML = html.replace(/\n/g, "<br/>");
  } else {
    this.bbcoder.parseNodeWithBR(this.element);
  }
}

BBCodeArea.prototype.renderClass = function() {
  var class = this.element.className || "";
  class = class.replace(/\s*bbcodearea\w*/g, "") + " bbcodearea";
  if (parseInt(this.element.offsetHeight) < 200) {
    class += " bbcodearea_short";
  }
  if (this.editCallback != null) {
    class += " bbcodearea_editable";
  }
  this.element.className = class.trim();
}
BBCodeArea.prototype.showSource = function() {
  debug (this)
  var element = document.createElement("div");
  var pre = document.createElement("pre");
  pre.appendChild(document.createTextNode(this.source.trim()));
  element.appendChild(pre);

  var closeButton = document.createElement("a");
  closeButton.appendChild(document.createTextNode("Schließen"));
  closeButton.href = "javascript:;";
  element.appendChild(closeButton);

  var dialog = new JautisDialog("BB-Code Quelltext", element);
  closeButton.addEventListener("click", jautisHint(dialog, "close"), true);
}
BBCodeArea.prototype.addButtons = function() {
  this.removeButtons();
  
  this.buttonslist = document.createElement("ul");
  this.buttonslist.className = "bbcodearea_buttons"
  this.element.appendChild(this.buttonslist);
  this.buttonslist.addEventListener("click", function() {debug("click")}, true);

  if (this.editingStatus < 2) {
    this.buttonslist.appendChild(this.getButton("source", "BB-Code Quelltext",
      jautisHint(this, "showSource")))
    if (this.editingStatus == 1) {
      this.buttonslist.appendChild(this.getButton("edit", "Bearbeiten",
        jautisHint(this, "startEditing")));
    }
  }
}
BBCodeArea.prototype.getButton = function(class, label, clickcallback) {
  var li = document.createElement("li");
  li.className = "bbcodearea_button_" + class;
  li.title = label;
  var span = document.createElement("span");
  span.appendChild(document.createTextNode(label));
  li.appendChild(span);
  li.addEventListener("click", clickcallback, true);
  return li;
}
BBCodeArea.prototype.removeButtons = function() {
  if (this.buttonslist != null) {
    this.element.removeChild(this.buttonslist);
    this.buttonslist = null;
  }
}

BBCodeArea.prototype.makeEditable = function(editCallback, editSaveCallback) {
  this.editingStatus = 1;
  this.editCallback = editCallback;
  this.editSaveCallback = editSaveCallback;
  this.addButtons();
  this.renderClass();
}
BBCodeArea.prototype.clearElementContent = function() {
  this.removeButtons();
  with (this.element) {
    while (firstChild) {
      removeChild(firstChild)
    }
  }
}

BBCodeArea.prototype.startEditing = function() {
  this.editingStatus = 2;
  this.clearElementContent();
  this.element.appendChild(
      document.createTextNode("Daten werden zum Bearbeiten geladen."));
  this.renderClass();
  this.editCallback(jautisHint(this, "startEditingCB"));
}
BBCodeArea.prototype.startEditingCB = function(source) {
  this.editingStatus = 3;
  this.clearElementContent();

  var form = document.createElement("form");
  this.element.appendChild(form);

  this.editTextarea = document.createElement("textarea");
  this.editTextarea.value = source;
  form.appendChild(this.editTextarea);

  var submit = document.createElement("input");
  submit.value = "Speichern";
  submit.type = "submit";
  form.appendChild(submit);

  var abort = document.createElement("input");
  abort.value = "Abbrechen";
  abort.type = "reset";
  form.appendChild(abort);

  this.renderClass();
  new BBCodeableTextarea(this.editTextarea);
  var me = this;
  form.addEventListener("submit", function(evt) {
    evt.preventDefault();
    setTimeout(jautisHint(me, "endEditing"), 0)
  }, true);
  form.addEventListener("reset", function(evt) {
    evt.preventDefault();
    setTimeout(jautisHint(me, "abortEditing"), 0)
  }, true);
}
BBCodeArea.prototype.endEditing = function() {
  this.editingStatus = 4;
  this.clearElementContent();
  this.element.appendChild(document.createTextNode("Daten werden gespeichert."));
  this.renderClass();
  this.editSaveCallback(this.editTextarea.value, jautisHint(this, "endEditingCB"));
}
BBCodeArea.prototype.abortEditing = function() {
  this.editingStatus = 1;
  this.clearElementContent();
  this.element.innerHTML = this.source.replace(/\n/g, "<br/>");
  this.parseForBBCode();
  this.addButtons();
  this.renderClass();
}
BBCodeArea.prototype.endEditingCB = function(newHTML) {
  this.editingStatus = 1;
  this.clearElementContent();
  this.element.innerHTML = newHTML;
  this.parseForBBCode();
  this.addButtons();
  this.renderClass();
}

CSS(".bbcodearea {position:relative;overflow:visible !important;}");
CSS(".bbcodearea_buttons {position:absolute;top: -27px; height:26px; left: 0;right:0; display:none;border-bottom: 1px solid rgba(127,127,127,0.6) !important;opacity:0.4;}");
CSS(".bbcodearea:hover .bbcodearea_buttons {display:block;}");
CSS(".bbcodearea_buttons:hover {display:block;opacity:1;}");
CSS("ul.bbcodearea_buttons > li {display: inline-block; background-color: white; background-position: left center; background-repeat: no-repeat; padding: 5px 5px 0px 26px !important; margin: 0 5px !important; height: 21px !important; position:relative;border: 1px solid #888;border-bottom:0px !important; cursor:default;width:auto !important;opacity:0.6}");
CSS("ul.bbcodearea_buttons > li:hover {border-color:black;opacity:1}");
CSS(".bbcodearea_button_edit {background-image: url({IMG:edit-text-frame-update.png})}");
CSS(".bbcodearea_button_source {background-image: url({IMG:text-plain.png})}");
/********************************************************************
 * 14. BBCodeable Textareas
 ********************************************************************/


/* opens a new ColorPicker. Callback is called after it was closed. */
function ColorPicker(callback, element) {
  if (ColorPicker.currentInstance != null) {
    ColorPicker.currentInstance.close();
  }
  this.callback = callback;
  ColorPicker.currentInstance = this;
  ColorPicker.openFor(element);
}
ColorPicker.prototype.callback = null;
ColorPicker.prototype.close = function() {
  ColorPicker.pickerElement.style.display = "none";
  ColorPicker.currentInstance = null;
  var cbValue = arguments.length > 0 ? arguments[0] : null;
  this.callback(cbValue);
}

/* static methods */
ColorPicker.currentInstance = null;
ColorPicker.pickerElement = null;
ColorPicker.pickerInput = null;
ColorPicker.openFor = function(element) {
  if (ColorPicker.pickerElement == null) {
    ColorPicker.createPickerElement();
  }
  ColorPicker.pickerElement.style.display = "";
  ColorPicker.pickerElement.style.left    = globalOffsetLeft(element) + "px";
  ColorPicker.pickerElement.style.top     = globalOffsetTop(element)  + "px";
}
ColorPicker.createPickerElement = function() {
  var elm = document.createElement("div");
  elm.className = "textareaPopup colorPicker";
  ColorPicker.pickerElement = elm;

  var normalColors = [
    {name: "Schwarz", color:"#000000"},
    {name: "Dunkelgrau", color:"#444444"},
    {name: "Grau", color:"#888888"},
    {name: "Hellgrau", color:"#bbbbbb"},
    {name: "Weiß", color:"#ffffff"},

    {name: "", color: "#880000"},
    {name: "", color: "#888800"},
    {name: "", color: "#008800"},
    {name: "", color: "#000088"},
    {name: "", color: "#880088"},

    {name: "", color: "#ff0000"},
    {name: "", color: "#ffff00"},
    {name: "", color: "#00ff00"},
    {name: "", color: "#0000ff"},
    {name: "", color: "#ff00ff"},

    {name: "", color: "#ff8888"},
    {name: "", color: "#ffff88"},
    {name: "", color: "#88ff88"},
    {name: "", color: "#8888ff"},
    {name: "", color: "#ff88ff"},
  ];
  normalColors.forEach(function(obj) {
    var div = document.createElement("div");
    div.style.backgroundColor = obj.color;
    div.title = obj.name;
    div.className = "colorPicker_color";
    elm.appendChild(div);
    div.addEventListener("click", ColorPicker.clickOnColor, true);
  });

  var div = document.createElement("div");
  div.className = "hasTextInput";
  ColorPicker.pickerInput = document.createElement("input");
  ColorPicker.pickerInput.setAttribute("type", "text");
  div.appendChild(ColorPicker.pickerInput);
  elm.appendChild(div);
  
  var abort = document.createElement("div");
  abort.className = "button abort";
  abort.title = "Abbrechen";
  abort.addEventListener("click",  function() {
    ColorPicker.abort();
  } , true);
  elm.appendChild(abort);

  var submit = document.createElement("div");
  submit.className = "button apply";
  submit.title = "Anwenden";
  submit.addEventListener("click",  function() {
    ColorPicker.currentInstance.close(ColorPicker.pickerInput.value);
  } , true);
  elm.appendChild(submit);

  document.body.appendChild(elm);
}
ColorPicker.clickOnColor = function(evt) {
  if (evt.target.style && evt.target.style.backgroundColor) {
    ColorPicker.currentInstance.close(evt.target.style.backgroundColor);
  } else {
    ColorPicker.currentInstance.close(null);
  }
}
ColorPicker.abort = function() {
  if (ColorPicker.currentInstance != null) {
    ColorPicker.currentInstance.close(null);
  }
}

/**
 * allows you to create a new Link
 * @param callback a function that is called with the resulting value.
 *        the value is the link target, <code>""</code> if the link should be
 *        deleted or <code>null</code> if the user aborted.
 */
function LinkPicker(callback, element, initialValue) {
  if (LinkPicker.currentInstance != null) {
    LinkPicker.currentInstance.close();
  }
  this.callback = callback;
  LinkPicker.currentInstance = this;
  LinkPicker.openFor(element, initialValue);
}
LinkPicker.prototype.callback = null;
LinkPicker.prototype.initialValue = null;
LinkPicker.prototype.close = function() {
  LinkPicker.pickerElement.style.display = "none";
  LinkPicker.currentInstance = null;
  var cbValue = arguments.length > 0 ? arguments[0] : null;
  this.callback(cbValue);
}

/* static methods */
LinkPicker.currentInstance = null;
LinkPicker.pickerElement = null;
LinkPicker.pickerInput = null;
LinkPicker.openFor = function(element, initialValue) {
  if (LinkPicker.pickerElement == null) {
    LinkPicker.createPickerElements();
  }
  LinkPicker.pickerElement.style.display = "";
  LinkPicker.pickerElement.style.left    = globalOffsetLeft(element) + "px";
  LinkPicker.pickerElement.style.top     = globalOffsetTop(element)  + "px";

  //Buttons / input
  LinkPicker.pickerInput.value = initialValue || "";
  LinkPicker.pickerElement.className = LinkPicker.pickerElement.className
    .replace(/\s*(changing|inserting)/, "")
      + ((initialValue) ? " changing" : " inserting");
  LinkPicker.pickerInput.focus();
}

LinkPicker.createPickerElements = function() {
  LinkPicker.pickerElement = document.createElement("div");
  LinkPicker.pickerElement.className = "textareaPopup linkPopup";
  document.body.appendChild(LinkPicker.pickerElement);

  var span = document.createElement("span");
  span.appendChild(document.createTextNode("Linkziel:"));
  LinkPicker.pickerElement.appendChild(span);

  var div = document.createElement("div");
  div.className = "hasTextInput";
  LinkPicker.pickerInput = document.createElement("input");
  LinkPicker.pickerInput.setAttribute("type", "text");
  div.appendChild(LinkPicker.pickerInput);
  LinkPicker.pickerElement.appendChild(div);

  LinkPicker.deleteButton = document.createElement("div");
  LinkPicker.deleteButton.className = "button deleteLink";
  LinkPicker.deleteButton.title = "Link löschen";
  LinkPicker.deleteButton.addEventListener("click", function() {
    LinkPicker.currentInstance.close("");
  } , true);
  LinkPicker.pickerElement.appendChild(LinkPicker.deleteButton);

  var abort = document.createElement("div");
  abort.className = "button abort";
  abort.title = "Abbrechen";
  abort.addEventListener("click",  function() {
    LinkPicker.abort();
  } , true);
  LinkPicker.pickerElement.appendChild(abort);

  LinkPicker.changeButton = document.createElement("div");
  LinkPicker.changeButton.className = "button changeLink";
  LinkPicker.changeButton.title = "Link einfügen oder ändern";
  LinkPicker.changeButton.addEventListener("click", function() {
    LinkPicker.currentInstance.close(LinkPicker.pickerInput.value);
  } , true);
  LinkPicker.pickerElement.appendChild(LinkPicker.changeButton);

}
LinkPicker.abort = function() {
  if (LinkPicker.currentInstance != null) {
    LinkPicker.currentInstance.close(null);
  }
}
/**
 * allows you to create a new Link
 * @param callback a function that is called with the resulting value.
 *        it is either called with an array of [columns, rows] or
 *        <code>null</code> if the user aborted.
 */
//callback is called with width (columns) and height (rows)
function TableCreator(callback, element) {
  if (TableCreator.currentInstance != null) {
    TableCreator.currentInstance.close();
  }
  this.callback = callback;
  TableCreator.currentInstance = this;
  TableCreator.openFor(element);
}

TableCreator.currentInstance = null;
TableCreator.prototype.callback = null;
TableCreator.prototype.close = function() {
  TableCreator.pickerElement.style.display = "none";
  TableCreator.currentInstance = null;
  var cbValue = arguments.length > 0 ? arguments[0] : null;
  this.callback(cbValue);
}

/* static methods */
TableCreator.pickerElement = null;
TableCreator.sizeElement = null;
/*with white bg */
TableCreator.outerSizeElement = null;

TableCreator.openFor = function(element) {
  if (TableCreator.pickerElement == null) {
    TableCreator.createPickerElements();
  }
  TableCreator.pickerElement.style.display = "";
  TableCreator.pickerElement.style.left    = globalOffsetLeft(element) + "px";
  TableCreator.pickerElement.style.top     = globalOffsetTop(element)  + "px";

  TableCreator.sizeTo(1, 1, true);
}


TableCreator.createPickerElements = function() {
  TableCreator.pickerElement = document.createElement("div");
  TableCreator.pickerElement.className = "textareaPopup tablePopup";
  document.body.appendChild(TableCreator.pickerElement);

  TableCreator.outerSizeElement = document.createElement("div");
  TableCreator.outerSizeElement.className = "tablePopupOuter";
  TableCreator.pickerElement.appendChild(TableCreator.outerSizeElement);

  TableCreator.sizeElement = document.createElement("div");
  TableCreator.sizeElement.className = "tablePopupInner";
  TableCreator.outerSizeElement.appendChild(TableCreator.sizeElement);

  TableCreator.outerSizeElement.addEventListener("mousemove",
      TableCreator.sizeMoveListener, true);
  TableCreator.outerSizeElement.addEventListener("click",
      TableCreator.sizeClickListener, true);

  div = document.createElement("p");
  TableCreator.sizeText = document.createTextNode("");
  div.appendChild(TableCreator.sizeText);
  TableCreator.pickerElement.appendChild(div);
}

TableCreator.sizeMoveListener = function(evt) {
  var coulumns = Math.floor(evt.layerX / 18) + 1;
  var rows = Math.floor(evt.layerY / 11) + 1;
  TableCreator.sizeTo(coulumns, rows, false);
}

TableCreator.sizeClickListener = function(evt) {
  var coulumns = Math.floor(evt.layerX / 18) + 1;
  var rows = Math.floor(evt.layerY / 11) + 1;
  TableCreator.currentInstance.close([coulumns, rows]);
}

TableCreator.sizeTo = function(columns, rows, outerAlso) {
  TableCreator.sizeElement.style.width = (columns * 18 + 1) + "px";
  TableCreator.sizeElement.style.height = (rows * 11 + 1) + "px";
  var outerWidth = parseInt(TableCreator.outerSizeElement.style.width);
  var outerHeight = parseInt(TableCreator.outerSizeElement.style.height);
  if (outerAlso || outerWidth < columns * 18 + 19) {
    TableCreator.outerSizeElement.style.width = (columns * 18 + 19) + "px";
  }
  if (outerAlso || outerHeight < rows * 11 + 12) {
    TableCreator.outerSizeElement.style.height = (rows * 11 + 12) + "px";
  }
  TableCreator.sizeText.data = columns + " Spalten, " + rows + " Zeilen";
}

TableCreator.abort = function() {
  if (TableCreator.currentInstance != null) {
    TableCreator.currentInstance.close(null);
  }
}
/**
 * constructs a new Button for a Toolbar
 * @param type the name of the image for the button
 * @param text the text for the button
 * @param class (optional) the class for the button.
 */
function TextareaButton(type, text) {
  this.type = type;
  this.text = text;
  var element = document.createElement("div");
  var span = document.createElement("span");
  span.appendChild(document.createTextNode(text));
  element.appendChild(span);
  element.title = text;
  element.className = "button_" + type;
  if (arguments.length > 2) {
    element.className += " " + arguments[2];
  }

  this.element = element;
  element.addEventListener("click", jautisHint(this, "onclick"), true);
}
TextareaButton.prototype.element = null;
TextareaButton.prototype.setDisabled = function(bool) {}
TextareaButton.prototype.setActive = function(bool) {}

//called after textarea selection was changed
TextareaButton.prototype.render = function() {}

//called if the button is clicked.
TextareaButton.prototype.onclick = function() {}

//child buttons
TextareaButton.prototype.childButtonList = null;
TextareaButton.prototype.appendButton = function(button) {
  if (this.childButtonList == null) {
    this.childButtonList = document.createElement("ul");
    this.element.appendChild(this.childButtonList);
    this.element.className += " hasChildren";
  }
  var li = document.createElement("li");
  li.appendChild(button.element);
  this.childButtonList.appendChild(li);
}

/*
 * adds BBCode editing buttons to a textarea.
 * @param the textarea the buttons should be added to.
 *
 * The editing type (normal or wysiwyg) is chosen by the last one the user
 * selected, if <code>BBCodeableTextarea.mode</code> is set to auto.
 */
function BBCodeableTextarea(textarea) {
  this.textarea = textarea;
  textarea.value = textarea.value.replace(
    /\[enc(\d+)\]([\w\W]*?)\[\/enc\]/ig,
    function(fullBB, method, content) {
      return "[doenc" + method + "]"
        + content.decrypt(method * 1).replace(/</g, "&lt;")
        + "[/doenc]";
    })
  textarea.value = textarea.value.replace(
    /\[size=[\s]+(\d)\]([\w\W]*?)\[\/size\]/ig,
    function(all, a, b) {
      return "[size=+"+a+"]"
        + b
        + "[/size]";
   }
  );
  this.constructButtonsContainer();
  var mode = userSettings.get("BBCodeableTextarea.mode");
  if (mode == "auto") {
    mode = userSettings.get("BBCodeableTextarea.lastMode");
  }
  if (mode == "wysiwyg") {
    this.showWYSIWYG();
  } else {
    this.showNormalButtons();
  }
}

(userSettings || globalSettings).register("BBCodeableTextarea.mode", "auto");
(userSettings || globalSettings).register("BBCodeableTextarea.lastMode", "normal");

BBCodeableTextarea.prototype.noJautisMessage = " [hidden]\n\n"
  + "Du kannst keine BB-Codes darstellen. Dazu benötigst du das Benutzerscript "
  + "jautis. Du bekommst es unter http://www.jautis.net/\n\n[/hidden]";
BBCodeableTextarea.prototype.textarea = null;
BBCodeableTextarea.prototype.buttons = [];
BBCodeableTextarea.prototype.buttoncontainer = null;
BBCodeableTextarea.prototype.maincontainer = null;

BBCodeableTextarea.prototype.constructButtonsContainer = function() {
  var buttonsouter = document.createElement("div");
  buttonsouter.className = "textareaButtonsOuter";

  this.buttoncontainer = document.createElement("div");
  this.buttoncontainer.className = "textareaButtons";
  buttonsouter.appendChild(this.buttoncontainer)

  this.iframe = document.createElement("iframe");
  this.iframe.style.display = "none";
  this.iframe.src = "about:blank;"

  var parentDiv = document.createElement("div");
  parentDiv.className = "wysiwygTextarea";
  this.maincontainer = parentDiv;
  this.textarea.parentNode.replaceChild(parentDiv, this.textarea);
  parentDiv.appendChild(buttonsouter)
  parentDiv.appendChild(this.textarea);
  parentDiv.appendChild(this.iframe);

  this.textarea.addEventListener("select",
        jautisHint(this, "onCursorChange"), true)
  this.iframe.contentDocument.addEventListener("mouseup",
        jautisHint(this, "onCursorChange"), true)
  this.iframe.contentDocument.addEventListener("keyup",
        jautisHint(this, "onCursorChange"), true)
  if (this.textarea.form) {
    this.textarea.form.addEventListener("submit",
        jautisHint(this, "onFormSubmit"), true);
    this.textarea.form.addEventListener("reset",
        jautisHint(this, "onFormReset"), true);
  }
  //iframe style
  var style = document.createElement("style");
  style.appendChild(document.createTextNode(
        "table {border-collapse:collapse; width:100%;}"
      + "td {border:1px dotted #888}"
      + "body{font-size:13px;}"
      + "ul {padding-left:2em}"));
  this.iframe.contentDocument.getElementsByTagName("head")[0].appendChild(style);
}

BBCodeableTextarea.prototype.deleteAllButtons = function() {
  for (var i = 0; i < this.buttons.length; i++) {
    delete this.buttons[i];
  }
  while (this.buttoncontainer.firstChild) {
    this.buttoncontainer.removeChild(this.buttoncontainer.firstChild);
  }
  this.buttons = [];
}

BBCodeableTextarea.prototype.addButton = function(button) {
  this.buttons.push(button);
  this.buttoncontainer.appendChild(button.element);
  //for better breaks:
  this.buttoncontainer.appendChild(document.createTextNode(" "));
}

BBCodeableTextarea.prototype.showNormal = function() {
  this.showNormalButtons();
  this.textarea.style.display = "";
  this.iframe.style.display = "none";
  this.textareaValueFromIframe();
  this.onCursorChange();
  (userSettings || globalSettings).set("BBCodeableTextarea.lastMode", "normal")
}

BBCodeableTextarea.prototype.textareaValueFromIframe = function() {
  this.textarea.value = this.toBB(this.iframe.contentDocument.body);
  if (this.textarea.value.search(/\[\/\w+\]/) > -1) {
    this.textarea.value += this.noJautisMessage;
  }
}

BBCodeableTextarea.prototype.showNormalButtons = function() {
  this.deleteAllButtons();
  
  var bbbutton = new TextareaButton("wysiwygOn", "Grafischer Editor");
  bbbutton.onclick = jautisHint(this, "showWYSIWYG")
  this.addButton(bbbutton);
  
  var previewbutton = new TextareaButton("preview", "Vorschau");
  previewbutton.onclick = jautisHint(this, "showPreview")
  this.addButton(previewbutton);
  
  var helpbutton = new TextareaButton("bbhelp", "Hilfe");
  helpbutton.onclick = jautisHint(this, "showHelp")
  this.addButton(helpbutton);
}

BBCodeableTextarea.prototype.previewDialog = null;
BBCodeableTextarea.prototype.previewContent = null;
BBCodeableTextarea.prototype.showPreview = function() {
  if (this.previewDialog != null) {
    this.previewDialog.close(); //toogle
  } else {
    this.previewContent = document.createElement("div");
    this.previewContent.className = "bbcodearea"
    var e = document.createElement("div");
    e.appendChild(this.previewContent)
    this.previewDialog = new JautisDialog("BB-Code Vorschau", e);
    this.previewDialog.onclose = jautisHint(this, "closedPreview");
    this.reloadPreview();
  }
}
BBCodeableTextarea.prototype.closedPreview = function() {
  this.previewDialog = null;
}
BBCodeableTextarea.prototype.reloadPreview = function() {
  if (this.previewDialog == null) {
    return;
  }
  var coder = new BBCoder();
  this.previewContent.innerHTML = coder.parseString(this.textarea.value).replace(/\n/g, "<br/>");
}

BBCodeableTextarea.prototype.showHelp = function() {
  var content = document.createElement("div");
  //main Help; if Key starts with _, it is rendered as headline
  //TODO: use from jautis.net
  var data = {
    "_1": "Hervorhebung",
    "b, u, i, s":"",
    "_2": "Schrift",
    "[color=Farbe]...[/color]": "Textfarbe. Für farbe eine gültige Farbe einsetzen",
    "bgcolor" : "",
    "_3": "Bereichs-/Absatzformat",
    "colorbox, border": "",
    "_4": "Absätze",
    "h, ...": "",
    "_4": "Sonstiges",
    "doenc, nw, hidden": ""
  };
  var currentTable = document.createElement("table");
  for (tag in data) {
    if(tag[0] == "_") {
      if (currentTable.childNodes.length > 0) {
        content.appendChild(currentTable);
        currentTable = document.createElement("table");
      }
      var h = document.createElement("h2");
      h.appendChild(document.createTextNode(data[tag]));
      content.appendChild(h);
    } else {
      var row = document.createElement("tr");
      var cell = document.createElement("td");
      cell.appendChild(document.createTextNode(tag));
      row.appendChild(cell);
      var cell = document.createElement("td");
      cell.appendChild(document.createTextNode(data[tag]));
      row.appendChild(cell);
      currentTable.appendChild(row);
    }
  }
  if (currentTable.childNodes.length > 0) {
    content.appendChild(currentTable);
  }
  var h = document.createElement("h2");
  h.appendChild(document.createTextNode("Mehr Hilfe"));
  content.appendChild(h);
  
  var p = document.createElement("p");
  p.appendChild(document.createTextNode("Mehr Informationen gibt es auf der "));
  var a = document.createElement("a");
  a.appendChild(document.createTextNode("jautis-Webseite"));
  a.href = "http://www.jautis.net/bbcode.html";
  a.target = "_new";
  a.addEventListener("click", function(evt) {
    GM_openInTab(evt.target.href);
    evt.preventDefault();
  }, true);
  p.appendChild(a);
  p.appendChild(document.createTextNode("."));
  content.appendChild(p);

  var dialog = new JautisDialog("BB-Code Kurzhilfe", content);
  dialog.setLeft(10);
  dialog.setTop(10);
}

BBCodeableTextarea.prototype.showWYSIWYG = function() {
  this.showWYSIWYGButtons();
  this.textarea.style.display = "none";
  this.iframe.style.display = "";
  this.iframe.contentDocument.body.innerHTML = this
    .toHTML(this.textarea.value.replace(this.noJautisMessage, ""));
  this.iframe.contentDocument.designMode = "on";
  this.onCursorChange();
  (userSettings || globalSettings).set("BBCodeableTextarea.lastMode", "wysiwyg")
}

BBCodeableTextarea.prototype.showWYSIWYGButtons = function() {
  this.deleteAllButtons();
  var bbbutton = new TextareaButton("wysiwygOff", "Quelltexteditor");
  bbbutton.onclick = jautisHint(this, "showNormal")
  this.addButton(bbbutton);

//   var button = new TextareaButton("debug", "Debug HTML");
//   var me = this;
//   button.onclick = function() {
//     alert(me.iframe.contentDocument.body.innerHTML);
//   }
//   this.addButton(button);

  //bold, underlined, ...
  var fontButton = new TextareaButton("decorations", "Schriftverzierungen");
  this.addButton(fontButton);
  var me = this;
  ["bold", "italic", "underline", "strikethrough"].forEach(function(type) {
     var button = me.getWYSIWYGButton(type);
     me.buttons.push(button);
     fontButton.appendButton(button);
  });

  ["forecolor", "hilitecolor", "superscript", "subscript",
   "createlink", "createtable"].forEach(jautisHint(this, "addWYSIWYGButton"));
  //TODO: encrypt: preferences-desktop-cryptography.png
  //TODO: font: preferences-desktop-font.png

  var listButton = new TextareaButton("lists", "Liste Einfügen");
  this.addButton(listButton);
  var me = this;
  ["indent", "outdent", "insertunorderedlist",
   "insertorderedlist"].forEach(function(type) {
     var button = me.getWYSIWYGButton(type)
     me.buttons.push(button);
     listButton.appendButton(button);
  })
}

//adds a simple wysiwyg-Button
BBCodeableTextarea.prototype.addWYSIWYGButton = function(type) {
  this.addButton(this.getWYSIWYGButton(type))
}

BBCodeableTextarea.wysiwygLabels = {
  "forecolor" : "Textfarbe"//TODO
};
BBCodeableTextarea.prototype.getWYSIWYGButton = function(type) {
  var type = type;
  var iframe = this.iframe;
  var button = new TextareaButton(type,
          BBCodeableTextarea.wysiwygLabels[type] || type);
  var me = this;
  button.onclick = function() {
    if (me.getButtonStatus(type).disabled) {
      return;
    }
    if (type == "forecolor" || type == "hilitecolor") {
      new ColorPicker(function(color) {
        if (color) {
          iframe.contentDocument.execCommand(type, false,  color);
        }
        me.focusIframe();
      }, button.element)
    } else if (type == "createlink") {
      new LinkPicker(function(link) {
        if (link !== null) {
          me.link(link);
        }
        me.focusIframe();
      }, button.element, me.getButtonStatus(type).value);
    } else if (type == "createtable") { /* not midas :-( */
      new TableCreator(function(size) {
        if (size !== null) {
          me.table(size[0], size[1]);
        }
        me.focusIframe();
      }, button.element);
    } else {
      iframe.contentDocument.execCommand(type, false, null);
      me.focusIframe();
    }
  }
  button.render = function() {
    var class = button.element.className + "";
    class = class.replace(/\s?(disabled|active)/gi, "");
    var status = me.getButtonStatus(type);
    if (status.disabled) {
      class += " disabled"
    }
    if (status.active) {
      class += " active";
    }
    //Todo: font & co with queryCommandValue
    if (class != button.element.className) {
      button.element.className = class;
    }
  }
  return button;
}
//returns an object: {disabled: boolean, active: boolean, value: string | null}
BBCodeableTextarea.prototype.getButtonStatus = function(type) {
  var data = {active:false, value:null, disabled:false};
  var selection = this.iframe.contentWindow.getSelection();
  if (type == "bold" || type == "italic"
      || type == "underline" || type == "strikethrough") {
    data.active = this.iframe.contentDocument.queryCommandState(type);
  } else if (type == "createlink") {
    var as = this.iframe.contentDocument.getElementsByTagName("a");
    for (var i = 0; i < as.length; i++) {
      if (selection.containsNode(as[i], true)) {
        data.value = as[i].getAttribute("href");
      }
    }
    data.active = data.value != null;
    data.disabled = data.active ? false : selection.isCollapsed;
  } else if (type == "superscript" || type == "subscript") {
    var tagNames = type == "superscript" ? ["sup", "sub"] : ["sub", "sup"];
    var tagsActive = [];
    for (var i = 0; i < tagNames.length; i++) {
      tagsActive[i] = Array.some(
              this.iframe.contentDocument.getElementsByTagName(tagNames[i]),
              function(elm) { return selection.containsNode(elm, true) });
    }
    data.active = tagsActive[0];
    data.disabled = tagsActive[1];
  } else if (type == "indent" || type == "outdent") {
    //walk out from selection start and selection end and look if we are in the
    //same list
    var ends = [selection.anchorNode, selection.focusNode];
    //the parent lists for the nodes, parentLists[0] is the most outer one
    var parentLists = [[], []];
    for (var i = 0; i < 2; i++) {
      var parent = ends[i];
      while (parent && parent.nodeType != 9) {
        if (parent.tagName == "UL" || parent.tagName == "OL") {
          parentLists[i].push(parent);
        }
        parent = parent.parentNode;
      }
      parentLists[i].reverse();
    }
    //if we outdent we have not to be in top level
    var levelToCheck = (type == "outdent") ? 1 : 0;
    data.disabled = parentLists[0].length <= levelToCheck
        || parentLists[1].length <= levelToCheck
        || parentLists[0][levelToCheck] != parentLists[1][levelToCheck];
  }
  return data;
}

/**
 * checks if the selection contains at least one element
 */
BBCodeableTextarea.prototype.selectionContains = function(selection, elements) {

}

/* call after another button was clicked, to give the focus back to the frame */
BBCodeableTextarea.prototype.focusIframe = function() {
  this.iframe.contentWindow.focus();
  this.onCursorChange();
}

BBCodeableTextarea.prototype.table = function(columns, rows) {
  if (columns*1 < 1 || rows*1 < 1) {
    throw "Not enough rows!";
  }
  //binäres Potenzieren macht hier wenig Sinn
  var tbody = "", columnstr = "";
  for (var i = 0; i < columns; i++) {
    columnstr += "<td></td>";
  }
  for (var i = 0; i < rows; i++) {
    tbody += "<tr>" + columnstr + "</tr>";
  }
  this.iframe.contentDocument.execCommand("inserthtml", false,
    "<table>" + tbody.replace("<td>", "<td id=\"toFocus\">") + "</table><br/> ");
  var focusTD = this.iframe.contentDocument.getElementById("toFocus");
  focusTD.id = "";
  //set selection
  var selection = this.iframe.contentWindow.getSelection();
  selection.collapse(focusTD, 0);
}
BBCodeableTextarea.prototype.link = function(url) {
  if (url == "") {
    var selection = this.iframe.contentWindow.getSelection();
    var as = this.iframe.contentDocument.getElementsByTagName("a");
    var toDelete = [];
    for (var i = 0; i < as.length; i++) {
      if (selection.containsNode(as[i], true)) {
        toDelete.push(as[i]);
      }
    }
    for (var i = 0; i < toDelete.length; i++) {
      var node = toDelete[i];
      for (var childI = node.childNodes.length - 1; childI >= 0; childI--) {
        node.parentNode.insertBefore(node.childNodes[i], node);
      }
      node.parentNode.removeChild(node);
    }
  } else {
    //create link
    this.iframe.contentDocument.execCommand("createlink", false, url);
  }
}

BBCodeableTextarea.prototype.insertIntoTextarea = function(text) {
  var t = this.textarea;
  var scroll = [t.scrollLeft, t.scrollTop];
  t.value = t.value.substr(0, t.selectionStart) 
      + text + t.value.substr(t.selectionEnd)
  t.scrollLeft = scroll[0];
  t.scrollTop = scroll[1];
}
/**
 * adds a quote of the entry on the current cursor position to the
 * write-message-form.
 * @param text the text to be quoted.
 * @param name the name of the user to be quoted
 * @param userids the userids of the user to be quoted
 */
BBCodeableTextarea.prototype.addQuote = function(text, name, link) {
  var text = text.replace(this.noJautisMessage, "");
  if (this.textarea.style.display == "none") {
    /*if (link) {
      var title = document.createElement("a");
      title.href = link;
      title.appendChild(document.createTextNode(name));
    } else {
      var title = document.createTextNode(name);
    }*/
    var html = this.toHTML(text);
    if (link) {
      name = "<a href=\"" + link + "\">[nobb]" + (name || link) + "[/nobb]</a>"
    }
    if (name) {
      var quoteStr = "[quote=" + name + "]" + html + "[/quote]";
    } else {
      var quoteStr = "[quote]" + html + "[/quote]";
    }
    this.iframe.contentDocument.execCommand("insertHTML", false, quoteStr);
  } else {
    if (link) {
      name = "[url=" + link + "][nobb]" + name + "[/nobb][/url]"
    }
    if (name) {
      var quoteStr = "[quote=" + name + "]" + text + "[/quote]";
    } else {
      var quoteStr = "[quote]" + text + "[/quote]";
    }
    this.insertIntoTextarea(quoteStr);
  }
}

/* Transform methods */
BBCodeableTextarea.prototype.toHTML = function(bbcode) {
  while (bbcode.search(/\[list(?:=#)?\][\w\W]+\[\/list\]/) > -1) {
    bbcode = bbcode.replace(/(\[list[\w\W]*)?\[list(?:=(#))?\][\s\n]*(?:\[\*\])?([\w\W]*)\[\/list\]/g,
        function (all, before, type, content) {
          type = type == "#" ? "ol" : "ul"
          return before + "<" + type + "><li>" + content.replace(/\n?\[\*\]/g, "</li><li>")
              + "</li></" + type + ">";
        })
  }
  while (bbcode.search(/\[table\][\w\W]+\[\/table\]/) > -1) {
    bbcode = bbcode.replace(/(\[table[\w\W]*)?\[table\][\s\n]*(?:\[tr\])?([\w\W]*?)\n?\[\/table\]/g,
        function (all, before, content) {
          content = content.split(/\n?\[tr\]/).map(function(row) {
            return row.replace(/^[\s\n]*(\[td\])?/, "").replace(/\n?\[td\]/g, "</td><td>");
          }).join("</td></tr><tr><td>");
          return before + "<table><tr><td>" + content + "</td></tr></table>";
        })
  }
  return bbcode.replace(/\[b\]([\w\W]*?)\[\/b\]/g, "<span style=\"font-weight:bold\">$1</span>")
               .replace(/\[i\]([\w\W]*?)\[\/i\]/g, "<span style=\"font-style:italic\">$1</span>")
               .replace(/\[u\]([\w\W]*?)\[\/u\]/g, "<span style=\"text-decoration:underline\">$1</span>")
               .replace(/\[s\]([\w\W]*?)\[\/s\]/g, "<span style=\"text-decoration:line-through\">$1</span>")
               .replace(/\[sub\]([\w\W]*?)\[\/sub\]/g, "<sub>$1</sub>")
               .replace(/\[sup\]([\w\W]*?)\[\/sup\]/g, "<sup>$1</sup>")
               .replace(/\[color=([\w#]+)\]([\w\W]*?)\[\/color\]/g, "<span style=\"color:$1\">$2</span>")
               .replace(/\[bgcolor=([\w#]+)\]([\w\W]*?)\[\/bgcolor\]/g, "<span style=\"background-color:$1\">$2</span>")
               .replace(/\[url=([^"\]]+)\]([\w\W]*?)\[\/url\]/g, "<a href=\"$1\">$2</a>")
               .replace(/\n/g, "<br/>");
}

BBCodeableTextarea.prototype.toBB = function(element) {
  
  var bbCodeStack = {
    //each is an array: {code, argument, overwrites: {}}
    s : [],
    
    getLastWithCode : function(code) {
      for (var i = bbCodeStack.s.length - 1; i >= 0; i--) {
        if (bbCodeStack.s[i].code == code) {
          return bbCodeStack.s[i];
        }
      }
      return null;
    },
    
    push: function(code, argument) {
      var o = null;
      if (code == "color" || code == "bgcolor") {
        o = bbCodeStack.getLastWithCode(code);
      }
      var obj = {code: code, argument:argument, overwrites: o}
      bbCodeStack.s.push(obj);
      return obj;
    },
    pop: function() {
      return bbCodeStack.s.pop();
    }
  };
  return this.toBBSub(element, bbCodeStack)
}
BBCodeableTextarea.prototype.toBBSub = function(element, stack) {
  var stack = stack;
  if (element.nodeType == 3) {
    return element.data.replace(/\n/g, "");
    // \n is covered with <br>, but sometimes appears on pasting
  } else if (element.nodeType != 1) {
    return "";
  } else if (element.tagName == "BR") {
    //BUG in midas: <br> with no text after is irgnored when editing
    return element.nextSibling ? "\n" : "";
  } else if (element.tagName == "IMG") {
    return "[img]" + element.src + "[/img]";
  } else if (element.tagName == "UL" || element.tagName == "OL") {
    return this.listElementToBB(element);
  } else if (element.tagName == "TABLE") {
    return this.tableToBB(element);
  } else if (element.childNodes.length < 1) {
    return "";
  }

  var tags = [];
  if (element.tagName == "A" && element.hasAttribute("href")) {
    tags.push(["url", encodeURI(element.getAttribute("href"))]);
  } else if (element.tagName == "SUB") {
    tags.push(["sub"]);
  } else if (element.tagName == "SUP") {
    tags.push(["sup"]);
  } else if (element.tagName == "P") {
    tags.push(["br"]);
  }
  if (element.style.fontWeight && element.style.fontWeight.indexOf("bold") > -1) {
    tags.push(["b"]);
  }
  if (element.style.fontStyle && element.style.fontStyle.indexOf("italic") > -1) {
    tags.push(["i"]);
  }
  if (element.style.textDecoration && element.style.textDecoration.indexOf("line-through") > -1) {
    tags.push(["s"]);
  }
  if (element.style.textDecoration && element.style.textDecoration.indexOf("underline") > -1) {
    tags.push(["u"]);
  }
  if (element.style.color) {
    tags.push(["color", this.rgbToHex(element.style.color)]);
  }
  if (element.style.backgroundColor) {
    tags.push(["bgcolor", this.rgbToHex(element.style.backgroundColor)]);
  }
  var ret = "";
  tags.forEach(function(tag) {
    stacktag = stack.push(tag[0], tag[1] || "");
    if (stacktag.overwrites) {
      ret += "[/" + stacktag.overwrites.code + "]";
    }
    ret += "[" + tag[0] + (tag[1] ? "=" + tag[1] : "") + "]";
  })
  for (var i = 0; i < element.childNodes.length; i++) {
    ret += this.toBBSub(element.childNodes[i], stack);
  }
  tags.reverse().forEach(function(tag) {
    stacktag = stack.pop();
    ret += tag[0] == "br" ? "[br]" : "[/" + tag[0] + "]";
    if (stacktag.overwrites) {
      ret += "[" + stacktag.overwrites.code + (stacktag.overwrites.argument 
                   ? "=" + stacktag.overwrites.argument 
                   : "") + "]";
    }
  })
  return ret;
}
BBCodeableTextarea.prototype.listElementToBB = function(element) {
   var str = (element.tagName == "OL") ? "[list=#]" : "[list]";
   for (var i = 0; i < element.childNodes.length; i++) {
     if (element.childNodes[i].tagName == "LI") {
       str += "\n[*]";
     }
     str += this.toBB(element.childNodes[i]);
   }
   return str + "[/list]";
}
BBCodeableTextarea.prototype.tableToBB = function(element) {
  var ret = "[table]";
  for (var i = 0; i < element.childNodes.length; i++) {
    var node = element.childNodes[i]
    if (node.tagName == "TBODY") {
      return this.tableToBB(node);
    }
    ret += "\n[tr]";
    for (var j = 0; j < node.childNodes.length; j++) {
      ret += "\n[td]" + this.toBB(node.childNodes[j]);
    }
  }
  return ret + "\n[/table]";
}

BBCodeableTextarea.prototype.rgbToHex = function(rgbstr) {
  var colors = /rgb\(\D*(\d+)\D+(\d+)\D+(\d+)/.exec(rgbstr);
  if (!colors) {
    return rgbstr;
  } else {
    //n < 16
    function toHex(n) {
      return "0123456789abcdef".substr(n, 1);
    }
    var hexColor = "#";
    for (var i = 1; i <= 3; i++) {
      hexColor += toHex(Math.floor(colors[i]/ 16)) + toHex(colors[i] % 16);
    };
    return hexColor;
  }
}

/* should be called every time the style around the cursor changes */
BBCodeableTextarea.prototype.cursorChangeTimeout = null;
BBCodeableTextarea.prototype.onCursorChange = function() {
  if (this.cursorChangeTimeout == null) {
    this.cursorChangeTimeout = setTimeout(jautisHint(this, "renderButtons"), 200);
  }
  ColorPicker.abort();
  LinkPicker.abort();
  TableCreator.abort();
}
BBCodeableTextarea.prototype.onFormReset = function() {
  if (this.textarea.style.display == "none") {
    this.showWYSIWYG();
  }
}

BBCodeableTextarea.prototype.onFormSubmit = function() {
  if (this.textarea.style.display == "none") {
    this.textareaValueFromIframe();
  }
  //[doenc]
  this.textarea.value = this.textarea.value.replace(
    /\[doenc(\d*)\]([\w\W]*?)\[\/doenc\]/g,
    function(all, a, b) {
      a = a*1 || 8;
      return "[enc" + a + "]" + b.encrypt(a) + "[/enc]";
    }
  );
}

BBCodeableTextarea.prototype.renderButtons  = function() {
  this.reloadPreview();
  this.cursorChangeTimeout = null;
  this.buttons.forEach(function(b) {b.render()});
}


CSS(' .textareaPopup { position:absolute; left: 50%; top: 50%; border: 1px solid #888; background: #eee; z-index:105; } .textareaPopup p { padding: 0; margin: .2em .1em; } .colorPicker { width: 100px; } .colorPicker .colorPicker_color { margin: 2px; padding: 5px 7px; border: 1px solid #888; display: inline-block; } .colorPicker .colorPicker_color:hover { border-color:black; } .linkPopup { width: 150px; padding: 5px; } .textareaPopup input[type=text] { position:relative; display:block; width: auto; margin-left:-1px; } .textareaPopup div.button { width: 24px; margin-bottom:0; display: inline-block; } .linkPopup .changeLink,.textareaPopup .apply  { background-image: url("{IMG:wysiwyg/dialog-ok-apply.png}"); } .textareaPopup .abort { background-image: url("{IMG:wysiwyg/dialog-close.png}"); } .linkPopup .deleteLink { background-image: url("{IMG:wysiwyg/dialog-cancel.png}"); } .linkPopup.inserting .deleteLink { display:none; } .tablePopup { padding:5px; } .tablePopupInner { background: blue url("{IMG:wysiwyg/table-cells-bg.png}") top left repeat; position:relative; display:inline-block; } .tablePopupOuter { background: white url("{IMG:wysiwyg/table-cells-bg.png}") top left repeat; position:relative; display:inline-block; } .wysiwygTextarea { position: relative; } .textareaButtons { top: auto; heigth:auto; bottom:0; margin-bottom: -5px; position: absolute; -moz-user-select:none; z-index:103; } .textareaButtonsOuter { position:absolute; left:0; right:0; top:0; height:0px; overflow:visible; } .textareaButtons div, .textareaPopup div.button { margin:1px 5px; border: 1px solid #888; background-color: white; background-position: center center; background-repeat: no-repeat; color: black; cursor: default; height: 24px; } .textareaButtons > div { /* for the tab style */ position: relative; border-bottom-color: white ! important; display: inline-block; width: 24px; } .textareaButtons div:hover, .textareaPopup div.button:hover { border-color:black; } .textareaButtons div.active { border-width: 2px; margin: 0px 4px; } .textareaButtons div.disabled { background-color:#ccc; } .textareaButtons ul { position:absolute; left: 0; top: 24px; display:none; z-index:104; border: 1px solid #888; background: #eee; padding: 2px 0; margin: 0; } .textareaButtons li { margin: 0; padding: 0; list-style-type:none; } .textareaButtons ul div { padding-left: 24px; background-position: left center; } .textareaButtons div:hover ul { display:block; } .wysiwygTextarea .textareaButtons { display:none; } .wysiwygTextarea:hover .textareaButtons { display:block; } .wysiwygTextarea textarea, .wysiwygTextarea iframe { border: 1px solid #888; width:100%; height:20em; position:relative; z-index:5; margin: 0; } .wysiwygTextarea iframe a { text-decoration:none; border-bottom: blue 1px dotted; } .textareaButtons > div > span { display:none; } .textareaButtons .button_wysiwygOn { background-image:url("{IMG:wysiwyg/document-edit.png}"); } .textareaButtons .button_preview { background-image:url("{IMG:wysiwyg/document-preview.png}"); } .textareaButtons .button_wysiwygOff { background-image:url("{IMG:wysiwyg/document-edit.png}"); } .textareaButtons .button_debug { background-image:url("{IMG:wysiwyg/flag-yellow.png}"); } .textareaButtons .button_bold { background-image:url("{IMG:wysiwyg/format-text-bold.png}"); } .textareaButtons .button_italic { background-image:url("{IMG:wysiwyg/format-text-italic.png}"); } .textareaButtons .button_underline { background-image:url("{IMG:wysiwyg/format-text-underline.png}"); } .textareaButtons .button_strikethrough { background-image:url("{IMG:wysiwyg/format-text-strikethrough.png}"); } .textareaButtons .button_forecolor { background-image:url("{IMG:wysiwyg/format-text-color.png}"); } .textareaButtons .button_hilitecolor { background-image:url("{IMG:wysiwyg/format-fill-color.png}"); } .textareaButtons .button_superscript { background-image:url("{IMG:wysiwyg/format-text-superscript.png}"); } .textareaButtons .button_subscript { background-image:url("{IMG:wysiwyg/format-text-subscript.png}"); } .textareaButtons .button_createlink { background-image:url("{IMG:wysiwyg/insert-link.png}"); } .textareaButtons .button_createtable { background-image:url("{IMG:wysiwyg/insert-table.png}"); } .textareaButtons .button_lists { background-image:url("{IMG:wysiwyg/format-list-menu.png}"); } .textareaButtons .button_indent { background-image:url("{IMG:wysiwyg/format-indent-more.png}"); } .textareaButtons .button_outdent { background-image:url("{IMG:wysiwyg/format-indent-less.png}"); } .textareaButtons .button_insertunorderedlist { background-image:url("{IMG:wysiwyg/format-list-unordered.png}"); } .textareaButtons .button_insertorderedlist { background-image:url("{IMG:wysiwyg/format-list-ordered.png}"); }'
+ '.wysiwygTextarea {padding: 3px;} '
+ '.wysiwygTextarea > iframe , .wysiwygTextarea > textarea {margin: -3px;'
+ 'padding: 2px !important; border-width:1px; display:block; width: 100% !important;}'
+ '.textareaButtons li {list-style-type:inherit} .textareaButtons ul {list-style-type:none !important; padding: 2px 0 !important; background: rgba(255, 255, 255, 0.8)} '
+ '.textareaButtons .button_decorations { background-image:url("{IMG:wysiwyg/format-text-menu.png}")}');


// CSS für Blog-News-Box // LUHE

CSS('#Grid-Page-Left #BlogNewsBox {border: 1px outset #000;margin-top: 20px;width: 123px;}');
CSS('#Grid-Page-Left #BlogNewsBox div {border: 1px inset #000;padding: 2px;}');
CSS('#Grid-Page-Left #BlogNewsBox p { margin: 0;}');

////////////////////////////////////////////////////////////////////////////////
////////////////////////////// Eigentlicher Beginn /////////////////////////////
////////////////////////////////////////////////////////////////////////////////

//Werbung
CSS("#ad728x90, #ad120x600, #ad125x125, #ad280x50, #ad280x25, #ad280x25_2, #ad125x125, "
    + "#showcase_staticContent, #mod-invitation-invitationbox, "
    + "#MyGroups_Table tr.hidden, #MyGroups_Table tr[class=\"\"], "
    + "#Chat_Advertising_On, #Grid-Advertising-Right, #Grid-Advertising-Top,"
    + "#AdLinkMyPhotobook, .teaserbox-meta, #wallpaperTop, #wallpaperRight"
    + "{display:none;}");


//BEGIN AREA menu
try{(function(){
/**
 * main-menu
 * @author Michael Z.
 * @date 2009-02-21
 */
  var ul = document.getElementById("Grid-Navigation-Main");
  if(!ul) {
    return;
  }

  //Meine Apps Bild
  var item = mainNavigation.getItemByText("Apps");
  if (item){
	CSS("#Grid-Navigation-Main li.obj-new a.obj-new-link {display:none;}");
  }
 
  
  //Seite weiterempfehlen
(userSettings || globalSettings).register("menu.showFriend", false)
if (userSettings && userSettings.get("menu.showFriend")) {
  var item = new MenuItem("einem Freund zeigen", "/Suggest/SuggestForm/?prov="
      + encodeURIComponent(document.URL) + "&desc="
      + encodeURIComponent("\"Ich möchte dir eine Seite zeigen!\"")
      + "&u=" + encodeURIComponent(document.URL));
  mainNavigation.insert(item);
}
//Jautis-Einstellungen
var item = new MenuItem("jautis Einstellungen",
      "javascript:/*showJautisSettings*/;"); //link for css
item.linkElement.addEventListener("click",
    function(){JautisSettings.show()}, true);
mainNavigation.insert(item);

if (userSettings) {
  userSettings.register("menu.showOnlineFriens", true)
  var item = mainNavigation.getItemByText("Freunde");
  if (item && userSettings.get("menu.showOnlineFriens")) {
    var subitem = new MenuItem("online", "/Friends/Friends/" + USERIDS + "/online/1");
    item.addSubItem(subitem)
  }
  
  userSettings.register("menu.showLogout", false)
  if (userSettings.get("menu.showLogout")) {
    var logoutlink = document.getElementsByClassName("logout")[0];
    var item = new MenuItem("Raus Hier", logoutlink ? logoutlink.href : "");
    mainNavigation.insert(item);
  }
}
  //Settings

function MenuSettings(element) {
  this.checkboxes = {};
  var groupbox = document.createElementNS(XULNS, "groupbox");
  groupbox.setAttribute("orient", "vertical");
  element.appendChild(groupbox)
  var caption = document.createElementNS(XULNS, "caption");
  caption.setAttribute("label", "angezeigte Menüeinträge");
  groupbox.appendChild(caption)
  
  if (userSettings) {
    this.checkboxes.showOnlineFriens = JautisSettings.checkbox(
       "Online-Link neben Freunden", userSettings.get("menu.showOnlineFriens"));
    groupbox.appendChild(this.checkboxes.showOnlineFriens);
    
    this.checkboxes.showFriend = JautisSettings.checkbox(
        "Seite einem Freund zeigen", userSettings.get("menu.showFriend"));
    groupbox.appendChild(this.checkboxes.showFriend);
    
    this.checkboxes.showLogout = JautisSettings.checkbox(
       "Logout", userSettings.get("menu.showLogout"));
    groupbox.appendChild(this.checkboxes.showLogout);
  }
}
MenuSettings.prototype.save = function() {
  if (userSettings) {
    userSettings.set("menu.showFriend", 
        this.checkboxes.showFriend.getValue());
    userSettings.set("menu.showOnlineFriens", 
        this.checkboxes.showOnlineFriens.getValue());
    userSettings.set("menu.showLogout", 
        this.checkboxes.showLogout.getValue());
  }
}
JautisSettings.addPanel(new JautisSettingsPanel("menu", "Menü", function(elm) {
  return new MenuSettings(elm);
}, function(s) {s.save()}));

})()}catch(e){debug(e)};
//END AREA menu


//BEGIN AREA BB-CODE
try{(function(){

function parseAllBBElements() {

  //CSS für formatierungselemente // TODO
  CSS(".comment-content .signatur {color:green}");

  //BB-Code CSS
  CSS(".bbcodearea .bbhasborder {border: 1px solid black; border-collapse:collapse}");
  CSS(".bbcodearea .bbhasborder >tbody > tr> td {border: 1px solid black}");
  CSS(".bbcodearea ul  {padding-left:25px;list-style:square}")
  CSS(".bbcodearea ol  {padding-left:25px;list-style:decimal}")
  CSS(".bbcodearea li {margin:0;list-style:inherit;clear:none;overflow:visible;}")
  CSS(".bbcodearea img {max-width:400px; max-height:300px;float:none!important;}")
  CSS(".bbcodearea .quote {border:1px solid #666;}")
  CSS(".bbcodearea .quote_p {padding:2px 3px;}")
  CSS(".bbcodearea .quote_h {background:#666; color:white;padding:2px 3px;}")
  CSS(".bbcodearea .quote_p .quote {margin-left:10px;margin-right:10px;}");
  //TODO durch X-Path ersetzen

  //Forums are rendered with ajax-forum

  if(document.getElementById("Groups_Overview")) {

    CSS(".groupsDescription > .bbcodearea {min-height: 30px}");
    //do not cut buttons
    CSS("#Groups_Overview .obj-innerbox,#Groups_Overview form, dl.obj-keyValueList {overflow: visible}");
    var parentContainer = evaluateXPath(document.getElementById("Groups_Overview"),
       "div[1]/div[1]")[0];
    //seperate content from headline
    var newDescription = document.createElement("div");
    while(parentContainer.childNodes.length>2) {
      newDescription.appendChild(parentContainer.childNodes[2]);
    }
    parentContainer.appendChild(newDescription);
    var descriptionArea = new BBCodeArea(newDescription);

    var nodes=document.getElementById("Groups_Overview").getElementsByTagName("div");
    var announcementArea = new BBCodeArea(nodes[nodes.length-1]);

    var groupEditor = {
      formData : {
        description: null,
        announcement: null,
        categoryId: null,
        homepage: null,
        office: null,
        access: null,
        visibility: null,
        formkey:null,
        iv:null
      },
      ajaxLoading : false,
      sendFormData : function(data, callback) {
        if (groupEditor.ajaxLoading) {
          var d = data; c = callback;
          setTimeout(function() { groupEditor.sendFormData(d, c) }, 200);
          return;
        }
        groupEditor.ajaxLoading = true;
        var callback = callback;
        //object->string
        if (data != null) {
          var dataarr = [];
          for (i in data) {
            dataarr.push(
              encodeURIComponent(i) + "=" + encodeURIComponent(data[i]));
          };
          data = dataarr.join("&");
        }
        var groupids= document.getElementById("Groups_Overview_GroupIds").value;
        var request = new XMLHttpRequest()
        request.open(data === null ? "GET" : "POST",
            VZ_SERVER + "Groups/AdminSettings/" + groupids);
        if (data != null) {
          request.setRequestHeader("Content-Type",
              "application/x-www-form-urlencoded; charset=UTF-8");
        }
        request.addEventListener("load", function (evt) {
          groupEditor.reciveFormData(evt.target.responseText);
          callback();
        }, true);
        request.send(data);
      },
      setFormData : function (all, name, value) {
        if (typeof groupEditor.formData[name] != "undefined") {
          groupEditor.formData[name] = value.replace(/&#(\d+);/g,
                function(all, code) {return String.fromCharCode(code)});;
        }
      },
      reciveFormData : function(text) {
        groupEditor.ajaxLoading = false;
        groupEditor.setAllFieldsTo(null);
        var pos = text.indexOf("<form action=\"/Groups/AdminSettings/");
        if (pos >= 0) {
          text = text.substring(pos, text.indexOf("</form>", pos));
          //read data
          text.replace(/<input[^>]*name=\"([^>"]*)\"[^>]*value=\"([^>"]*)/g,
            groupEditor.setFormData);
          text.replace(/<input[^>]*value=\"([^>"]*)\"[^>]*name=\"([^>"]*)/g,
            function(all, value, name) {
              groupEditor.setFormData(all, name, value);
            });
          text.replace(/<textarea[^>]*name=\"([^>"]*)\"[^>]*>([^<]*)/g,
            groupEditor.setFormData);
          text.replace(/<select[^>]*name=\"([^>"]*)\"[\w\W]*?<option[^>]*value=\"([^>"]*)\"[^>]*selected/g,
            groupEditor.setFormData);
          text.replace(/<select[^>]*name=\"([^>"]*)\"[\w\W]*?<option[^>]*selected[^>]*value=\"([^>"]*)\"/g,
            groupEditor.setFormData);
        }
        //bug in svz
        if (groupEditor.formData.categoryId == null) {
          groupEditor.formData.categoryId = "";
        }
        if (groupEditor.formData.access == null) {
          groupEditor.formData.access = "";
        }
        if (groupEditor.formData.visibility == null) {
          groupEditor.formData.visibility = "";
        }
        for (var i in groupEditor.formData) {
          if (groupEditor.formData[i] == null) {
            //error => prevent saving!
            groupEditor.setAllFieldsTo("Fehler beim Laden, NICHT SPEICHERN (" +i + " nicht gefunden)")
          }
        }
      },
      setAllFieldsTo :function(val) {
        for (var i in groupEditor.formData) {
          groupEditor.formData[i] = val;
        }
      },
      editDescription : function(cb) {
        var cb = cb;
        groupEditor.sendFormData(null, function() {
          cb(groupEditor.formData.description);
        });
      },
      saveDescription : function(description, cb) {
        var cb = cb, description = description;
        groupEditor.formData.description = description;
        groupEditor.sendFormData(groupEditor.formData, function() {
          cb(description.replace(/\n/g, "<br>"));
        })
      },
      editAnnouncement : function(cb) {
        var cb = cb;
        groupEditor.sendFormData(null, function() {
          cb(groupEditor.formData.announcement);
        });
      },
      saveAnnouncement : function(announcement, cb) {
        var cb = cb, announcement = announcement;
        groupEditor.formData.announcement = announcement;
        groupEditor.sendFormData(groupEditor.formData, function() {
          cb(announcement.replace(/\n/g, "<br>"));
        })
      }
    };
    var statusDiv = evaluateXPath(document.getElementById("Groups_Overview"),
        "div[2]/div[@class=\"obj-innerbox\"]")[0];
    debug(statusDiv)
    if (statusDiv && statusDiv.textContent.indexOf("Gründer")> -1) {
      descriptionArea.makeEditable(
            groupEditor.editDescription, groupEditor.saveDescription);
      announcementArea.makeEditable(
            groupEditor.editAnnouncement, groupEditor.saveAnnouncement);
    }
    
    var dds = document.getElementById("GroupsInformation").getElementsByTagName("dd");
    for(var i = 0; i < dds.length; i++) {
      if (dds[i].getElementsByTagName("a").length < 1) {
        new BBCodeArea(dds[i]);
      }
    }
  }

  if (document.getElementById("profileRight")) {
    CSS("dl.obj-keyValueList {overflow:visible}")
    CSS("dl.obj-keyValueList dd {margin-left:115px;overflow:visible}")
    if (userSettings.get("layout.NoUmbrueche")) {CSS("dd.is_long {width:94%;margin-left:5% !important;clear:left}")}

    var dds=document.getElementById("profileRight").getElementsByTagName("dd");
    for(var i=0;i<dds.length;i++) {
      var dt = dds[i].previousSibling;
      while (dt.tagName != "DT" && dt) {
        dt = dt.previousSibling;
      }
      if (dt && dt.textContent.indexOf("Homepage") > -1) {
        var as = dds[i].getElementsByTagName("a");
        for (var aIndex = as.length - 1; aIndex >= 0; aIndex--) {
          as[aIndex].parentNode.replaceChild(document.createTextNode(as[aIndex].textContent), as[aIndex]);
        }
      }
      if (dds[i].getElementsByTagName("a").length < 1) {
        new BBCodeArea(dds[i])
      }

      if(dds[i].textContent.length > 200)
        dds[i].className+=" is_long"
    }

    var divs=document.getElementById("Mod-Pinboard-Snipplet").getElementsByTagName("p");

    for(var i=0;i<divs.length;i++){
      if( divs[i].className=="pinboard-entry-text")
        new BBCodeArea(divs[i])
    }
    try{
      new BBCodeArea(document.getElementById("microblogContent").getElementsByTagName("p")[0])
    }catch(e){}
    
    function reloadPinnboard() {
      if (document.getElementById("Pinboard_entry")) {
        //right events: Block klick, wait for submit event, and then simulate click
        var blockClick = true; //false after the simulated one
        
        var outer = document.getElementById("Mod-Pinboard-Snipplet");
        var form = outer.getElementsByTagName("form");
        //new BBCodeableTextarea(document.getElementById("Pinboard_entry"));
		//TODO:rausgenommen wegen Fehler beim Senden im iframe
        CSS("label[for=Pinboard_entry].floatL {float:none;display:block}");
        CSS(".pinboard-write form{overflow:visible !important;}");
        CSS("#Mod-Pinboard-Snipplet .hint, #Mod-Pinboard-Snipplet .form-buttons{width: auto;}");
      }
    }
    reloadPinnboard();
    
  }

  if (document.getElementById("messages-list")) {
    Array.forEach(document.getElementsByClassName("messageListContent"),
      function(elm) {
        var messageElement = elm;
        var formated = false;
        elm.addEventListener("overflow", function() {
          if (!formated) {
            formatmessage(messageElement)
            formated = true;
          }
        }, true);
      });
    function formatmessage(elm) {
      //evt.target = div.body
      debug("formatting")
      new BBCodeArea(elm.getElementsByClassName("body_text")[0])
    }
  }

  if(document.getElementById("FriendsList")){
    var divs=document.getElementById("FriendsList").getElementsByTagName("div");
    for(var i=0;i<divs.length;i++)
      if(divs[i].className=="labeledText")
        new BBCodeArea(divs[i])
  }

  if(document.getElementById("FriendsList")){
    var dds=document.getElementById("Grid-Page-Center-Content").getElementsByTagName("dd");
    for(var i=0;i<dds.length;i++)
        if(dds[i].className=="microblog")
          new BBCodeArea(dds[i])
    }

  if(document.getElementById("Mod-Feedbox-Snipplet")){
    CSS("#startLeft div.teaserbox div.text div#settings_visibility ul li {overflow:visible}"); 
    var divs=document.getElementById("Mod-Feedbox-Snipplet").getElementsByTagName("div");
    for(var i=0;i<divs.length;i++)
        if(divs[i].className=="feedEntry")
          new BBCodeArea(divs[i])
    }

  if(document.getElementById("Mod-Feeds-Home-Pagelet")){
    var divs=document.getElementById("Mod-Feeds-Home-Pagelet").getElementsByTagName("div");
    for(var i=0;i<divs.length;i++)
        if(divs[i].className=="feedEntry")
          new BBCodeArea(divs[i])
    }


    if(document.getElementById("Mod-Photos-Album")){
      var ps=document.getElementById("Mod-Photos-Album").getElementsByTagName("p");

      for(var i = 0; i < ps.length; i++) {
        new BBCodeArea(ps[i])
      }

      try{
        new BBCodeArea(document.getElementById("Mod-Photos-Album").getElementsByTagName("td")[0])
      }catch(e){};
    }

    if(document.getElementById("Pinboard_List")){
      var divs=document.getElementById("Pinboard_List").getElementsByTagName("div");
      for(var i=0;i<divs.length;i++)
        if(divs[i].className=="pinboard-entry-text")
          new BBCodeArea(divs[i])
    }


  //TODO: emoticons
  // gelöscht wegen schlechtem codestil

  // XXX
  if (document.getElementById("Messages_List")){ //TODO: formatierung (or delete)
    function registerMailBody (elm) {
      var wasFormated = false;
      if(elm.textContent.replace(/[\s\n]*/,"") != "")
        FormatElement(elm);
      else
        elm.addEventListener("DOMAttrModified", function(evt){
          if(wasFormated || evt.currentTarget.textContent.replace(/[\s\n]*/,"")=="")
            return;
          wasFormated=true;
          var eventTarget=evt.currentTarget
          var text=eventTarget.innerHTML;
          if(text.match(/\[attach(=[^\]]*)?\][^\[]*\[\/attach\]/))
            evt.currentTarget.innerHTML = text.replace(/\[attach(?:=([^\]]*))?\s?\]([^\[]*)\[\/attach\]/, function(all, text, b){
              var elm=document.createElement("a");
              elm.href=b.replace(/(\s|<[^>]*>)/g, "");
              elm.appendChild(document.createTextNode(text || "Anhang 1"));
              eventTarget.parentNode.appendChild(elm);
              return "";
            })
          new BBCodeArea(eventTarget);

        }, true)
    } //end function registerMailBody

    var divs=document.getElementById("Messages_List").getElementsByTagName("div");
    for(var i=0;i<divs.length;i++){
      if(divs[i].className!="body_text")
        continue;
      registerMailBody(divs[i])
    }

    //TODO: use BBCodeableTextarea
    //phxpreview deleted because it should be replaced, Michael (2009-09-01)

  }//endif


}
setTimeout(parseAllBBElements, 1);
})()}catch(e){debug(e)};
//END AREA BB-CODE

//BEGIN AREA MESSAGEINFORMATION
try{(function(){

if(userSettings) {
userSettings.register("mail.active", true);
userSettings.register("mail_last_look", 0);
userSettings.register("mail_new_list", []);
userSettings.register("mail_minutes_between_look", 1);


var newMessageCounterElm = document.createElement("span");
var newMessageCounterText = document.createTextNode("");
newMessageCounterElm.appendChild(newMessageCounterText);

var as=document.getElementById("Grid-Navigation-Main").getElementsByTagName("a");
for(var i=0; i < as.length; i++) {
  if(as[i].href.indexOf("Messages") > -1){
    as[i].appendChild(newMessageCounterElm);
    as[i].title="";
    var messageTooltip = new Tooltip(as[i])
    messageTooltip.onshow = function() {mailTooltipRender() };
    break;
  }
}

newMessageElm = document.createElement("div")
newMessageElm.id="newMails"
document.body.appendChild(newMessageElm)

CSS("#newMails {position:fixed;right:0;bottom:0;z-index:100}");
CSS("#newMails > * {border: 1px solid black;background:#eee}");
CSS("#newMails > * + * {border-top: none}");
CSS("#Grid-Navigation-Main .no_new_mails {display:none;}");
CSS("#Grid-Navigation-Main .new_mails {position:absolute; top:1px;"
  + "right:2px; font-weight:bold; }");
CSS("#Grid-Navigation-Main .new_mails:before "
  + "{content:\"(\";font-weight:bold;}");
CSS("#Grid-Navigation-Main .new_mails:after "
  + "{content:\")\";font-weight:bold;}");
CSS("#Grid-Navigation-Main a {position:relative}");

/**
 * Looks at the start page it the message count has changed. If yes, the normal
 * lookForMails is called. This is done because of the captcha.
 * @author Michael Z.
 * @date 2009-08-25
 */
userSettings.register("unreadMails", 0);
function lookForMailsSave() {
  var request = new XMLHttpRequest();
  request.open("GET", VZ_SERVER + "Start", true);
  try {
    request.addEventListener("load", reciveMailsSave, true);
  } catch(e) {
    //opera...
    request.onreadystatechange = function() {
      if (request.readyState == 4) {
        reciveMailsSave({target:request});
      }
    }
  }
  request.send(null);
}

function reciveMailsSave(evt) {
  var temp = /title="Nachrichtendienst">Nachrichtendienst \((\d+)\)/
             .exec(evt.target.responseText);
  unreadMails = temp ? temp[1] : 0;
  if (unreadMails != userSettings.get("unreadMails")) {
    lookForMails();
  }
  userSettings.set("unreadMails", unreadMails);
}

function lookForMails(){
  //the page to call. Default is the first one, more are automatically called if
  // the first has many unread messages
  var page = lookForMails.arguments[0] || 1;

  function recivedMailPage(){
     var mails = userSettings.get("mail_new_list");


    var newMails=[];//jeweils array: [id, von, von-ids, von-bild, betr, zeit]
    var tmp = mailpage.responseText.match(/<div id=\"msg_[\w\W]*?class="deleteMsgLink"/g) || [];

    if(!tmp)
      return;
    if(!mails.some) {
      //not an array
      mails = [];
    }

    for(var i = 0; i < tmp.length; i++){
      //delete Mails that are not new
      if(tmp[i].search(/class="[^\"]*status_new/)<0){
        var tmp2= /<input type="hidden" value="(\d+)" class="msgId"/.exec(tmp[i]) || ["",""]
        for(var j = mails.length-1; j >= 0; j--) {
          if(mails[j] == tmp2[1]*1 || mails[j][0] == tmp2[1]*1) {
            mails.splice(j, 1);
          }
        }
        continue;
      }
      // add new mails
      var arr = [];
      var tmp2= /<input type="hidden" value="(\d+)" class="msgId"/.exec(tmp[i]) || ["",""]
      arr[0]  = tmp2[1]*1
      var tmp2= /<a href="\/Profile\/([-\w]+)" title="([^\"]+)">/.exec(tmp[i]) || ["","",""]
      arr[2]  = tmp2[1]
      arr[1]  = tmp2[2]
      var tmp2= /<img src="([^\"]+)/.exec(tmp[i]) || ["",""]
      arr[3]  = tmp2[1]
      var tmp2= /title="lesen">[\n\s]*(.*?)[\n\s]*<\/a>/.exec(tmp[i]) || ["",""]
      arr[4]  = tmp2[1]
      var tmp2= /<small>([^>]*)<\/small>/.exec(tmp[i]) || ["",""]
      arr[5]  = tmp2[1];

      if(!mails.some(function(val) {return val == arr[0] || val[0] == arr[0]})){
        mails.push(arr);
        newMails.push(arr);
      }
    }
    
    if (newMessageCounterText.data != mails.length) {
      newMessageCounterText.data = mails.length;
      newMessageCounterElm.className = mails.length>0 ? "new_mails" : "no_new_mails";
    }

    if(newMails.length > 0){
      var newMailsText="";
      newMails.forEach(function(val){
        var table=document.createElement("table");

        var tr=document.createElement("tr");

        var td=document.createElement("td");
        var img=document.createElement("img");
        img.src=val[3];
        td.appendChild(img);
        tr.appendChild(td);

        var td=document.createElement("td");
        var a=document.createElement("a");
        a.href="/Profile/"+val[2];
        a.appendChild(document.createTextNode(val[1]));
        td.appendChild(a);
        tr.appendChild(td);

        var td=document.createElement("td");
        var span=document.createElement("span");
        span.appendChild(document.createTextNode(val[5]));
        td.appendChild(span);
        var a=document.createElement("a");
        a.href="javascript:;";
        a.addEventListener("click",function(){
          table.parentNode.removeChild(table);
        },true)
        a.className="closeButton";
        td.appendChild(a);
        tr.appendChild(td);

        table.appendChild(tr)

        var tr=document.createElement("tr");

        var td=document.createElement("td");
        var a=document.createElement("a");
        a.href="/Messages/Inbox/messageId/"+val[0]+"/p/"+page;
        a.appendChild(document.createTextNode(val[4]));
        td.appendChild(a);
        td.setAttribute("colspan", "2")
        tr.appendChild(td);

        table.appendChild(tr)

        //nicht früher, wegen Bug
        img.parentNode.setAttribute("rowspan", "2")
        newMessageElm.appendChild(table);

        setTimeout(function(){
          table.style.opacity=0.8;
        }, 1000)
      })
      if(page==1){
        playMailSound();
      }
    }

    userSettings.set("mail_new_list",mails)

    if (newMails.length > 15 && page < 5)//eine Seite oder mehr
      lookForMails(page + 1)
    else
      renderMailStatus(false);
  }//function recivedMailPage


  var mailpage = new XMLHttpRequest();
  mailpage.open("GET", VZ_SERVER + "Messages/Inbox/p/" + page, true)
  mailpage.onload = recivedMailPage;
  mailpage.send(null);
}//function lookForMails;

/**
 * renders the information on the mail element, and checks if there are new Mails.
 */
function renderMailStatus(){
  if (!userSettings.get("mail.active")) {
    return false;
  }
  var checkForNew = arguments[0] !== false;

  var lastlook = userSettings.get("mail_last_look") || 0;
  var minutes_between_look = userSettings.get("mail_minutes_between_look");

  if (minutes_between_look < 0.5)
    minutes_between_look = 1;

  if (lastlook < (new Date()).getTime() - minutes_between_look*60*1000
      && checkForNew) {
    lookForMailsSave()
    userSettings.set("mail_last_look", (new Date()).getTime())
  } else {
    var mails = userSettings.get("mail_new_list") || [];
    newMessageCounterText.data = mails.length;
    newMessageCounterElm.className = mails.length > 0 ? "new_mails" : "no_new_mails";
  }
}

userSettings.register("mail.sound", "");
userSettings.register("mail.soundformat", "ogg")

function playMailSound() {
  var soundName = userSettings.get("mail.sound");
  if (soundName == "") {
    return;
  }
  var format = userSettings.get("mail.soundformat");

  var soundmanager = new Imagemanager("sound/" + soundName + "." + format);
  if (soundmanager.isActual()) {
    var elm    = document.createElement("embed");
    elm.width  = "0"
    elm.height = "0"
    elm.setAttribute("src", imagemanager.getImage());
    document.body.appendChild(elm);
  } else {
    soundmanager.onload = playMailSound;
    soundmanager.getImage();
  }
}


function mailTooltipRender() {
  if(!userSettings.get("mail.active")) {
    messageTooltip.setText("Das automatische Überprüfen der Nachrichten ist deaktiviert");
  } else {
    var mails = userSettings.get("mail_new_list") || [];
    if(mails.length > 0) {
      var html = "Du hast " + mails.length + " neue Nachrichten";
      for(var i = 0; i < mails.length; i++) {
        html  += "<p>";
        html  += "<img src=\"" + mails[i][3] + "\" style=\"max-height:4em;float:left;border-right:.5em solid transparent\"/>"
        html  += "<b>" + mails[i][4] + "</b>";
        html  += "<br/>";
        html  += mails[i][1] + ", " + mails[i][5];
        html  += "<div style=\"clear:both\"></div></p>";
      }
      messageTooltip.setText(html);
    }
    else {
      messageTooltip.setText("Du hast keine neuen Nachrichten");
    }
  }
}
setTimeout(renderMailStatus, 100);
setInterval(renderMailStatus, 1000)

/*
Nachrichtenseite->Beim aufklappen aktuelaisieren
*/
if(document.getElementById("messages-list")) {
  // to avoid double overflows
  var messageLatelyRequested = false;
  document.getElementById("messages-list")
      .addEventListener("overflow", lookForMails, false)
}

//Einstellungen
JautisSettings.addPanel(new JautisSettingsPanel("mail", "Nachrichten", function(elm){
  //data to be sent to the saving function
  var data = {};
  /* Structure:
   * - groupbox
   *   - caption
   *     - checkbox (JautisSettings) "Nach neuen Nachrichten schauen"
   *   - hbox
   *     - label: "Alle "
   *     - label, rendered by renderTimeLabel()
   *     - label: " Minuten nach Nachrichten sehen"
   *   - scale (data.timeSlider)
   *   - button: "Nachrichtenzähler zurücksetzen"
   */

  var groupbox = document.createElementNS(XULNS, "groupbox");
  groupbox.setAttribute("flex", "1")
  groupbox.setAttribute("orient", "vertical")

  var caption    = document.createElementNS(XULNS, "caption")
  groupbox.appendChild(caption);

  data.activeCB  = JautisSettings.checkbox("Nach neuen Nachrichten schauen",
      userSettings.get("mail.active"));
  caption.appendChild(data.activeCB);


  //hbox for time slider label
  var hbox    = document.createElementNS(XULNS, "hbox")
  groupbox.appendChild(hbox)
  var label        = document.createElementNS(XULNS, "label")
  label.setAttribute("value", "Alle ");
  hbox.appendChild(label)
  data.timeLabel    = document.createElementNS(XULNS, "label")
  data.timeLabel.setAttribute("value", "?");
  hbox.appendChild(data.timeLabel)
  var label        = document.createElementNS(XULNS, "label")
  label.setAttribute("value", " Minuten nach Nachrichten sehen");
  hbox.appendChild(label)

  /* left: 0.5min, middle: 10min, right: 60min.
   * we use time = a * val^2 + b * val + c*/
  data.timeCalculateVars =
      { a : 0.0049, b : 0.105, c : 0.5 };
  data.timeSlider = document.createElementNS(XULNS, "scale");
  var val = userSettings.get("mail_minutes_between_look");
  with (data.timeCalculateVars) {
    //alert(val + "=>" + (-b + Math.sqrt(b * b - 4 * a * (c - val))) / (2 * a));
    var val = (-b + Math.sqrt(b * b - 4 * a * (c - val))) / (2 * a);
    data.timeSlider.setAttribute("value",
      Math.floor(Math.abs(val)));
  }
  groupbox.appendChild(data.timeSlider);

  function renderTimeLabel() {
    var val = data.timeSlider.getAttribute("value") * 1;
    with (data.timeCalculateVars) {
      var minutes = val * val * a + val * b + c;
      data.timeLabel.setAttribute("value",
          (Math.round(minutes*10)/10 + "").replace(".", ","));
    }
  }
  data.timeSlider.addEventListener("change", renderTimeLabel, true);
  renderTimeLabel();

  var button   = document.createElementNS(XULNS, "button")
  button.setAttribute("label", "Nachrichtenzähler zurücksetzen");
  button.style.marginTop="1em";
  button.addEventListener("command", function(){
    userSettings.set("mail_new_list", []);
    renderMailStatus()
  }, true);
  groupbox.appendChild(button)

  elm.appendChild(groupbox)
  return data;
}, function(data) {
  var val = data.timeSlider.getAttribute("value") * 1, minutes;
  with (data.timeCalculateVars) {
    minutes = val * val * a + val * b + c;
  }
  userSettings.set("mail_minutes_between_look", minutes)
  userSettings.set("mail.active", data.activeCB.getValue())
  renderMailStatus();
}))
}//if (userSettings)
})()}catch(e){debug(e)};
//END AREA MESSAGEINFORMATION

//BEGIN AREA ALGEMEINE EINSTELLUNGEN
//BEGIN AREA SCHRIFTARTEN
if (userSettings.get("Schriftart") == "Normal") {
CSS("html {font: tahoma,verdana,arial,sans-serif;}");}
if (userSettings.get("Schriftart") == "Arial") {
CSS("html {font: 11px arial, sans-serif;}");}
if (userSettings.get("Schriftart") == "Bauhaus 93") {
CSS("html {font: 11px 'bauhaus 93', sans-serif;}");}
if (userSettings.get("Schriftart") == "Flubber") {
CSS("html {font: 11px flubber, sans-serif;}");}
if (userSettings.get("Schriftart") == "Good Times") {
CSS("html {font: 8px 'good times', sans-serif;}");}
if (userSettings.get("Schriftart") == "SF Movie Poster") {
CSS("html {font: 11px 'sf movie poster', sans-serif;}");}
if (userSettings.get("Schriftart") == "Verdana") {
CSS("html {font: 11px verdana, sans-serif;}");}
if (userSettings.get("Schriftart") == "Sans Serif") {
CSS("html {font: 10px sans-serif;}");}
//END AREA SCHRIFTARTEN
try{(function(){
if (!userSettings) {
  return;
}
userSettings.register("allgemein.GroupViewing", true);
userSettings.register("allgemein.NWCode", true);
JautisSettings.addPanel(new JautisSettingsPanel("algemein", "Allgemeines", function(elm){
  var checkboxes = {};
  var groupbox = document.createElementNS(XULNS, "groupbox");
  groupbox.setAttribute("flex", "0.75")
  groupbox.setAttribute("orient", "vertical")
  
  var textdiv = document.createElement("div");
  textdiv.appendChild(document.createTextNode("Hauptschriftart des SchülerVzs"));
  textdiv.appendChild(document.createElement("br"));
  groupbox.appendChild(textdiv)  
  
        var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "Normal");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "Normal");				
		}, true);
		groupbox.appendChild(button)
		var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "Arial");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "Arial");					
		}, true);
		groupbox.appendChild(button)		
		var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "Bauhaus 93");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "Bauhaus 93");							
		}, true);
		groupbox.appendChild(button)		
		var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "Flubber");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "Flubber");				
		}, true);
		groupbox.appendChild(button)	
		var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "Good Times");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "Good Times"); 	
		}, true);
		groupbox.appendChild(button)
		var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "SF Movie Poster");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "SF Movie Poster");		
		}, true);
		groupbox.appendChild(button)		
        var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "Verdana");
		button.style.marginTop="0em";
		button.addEventListener("command", function(){
					userSettings.set("Schriftart", "Verdana");
		}, true);
		groupbox.appendChild(button)
		
		// Signatur
		var groupbox2 = document.createElementNS(XULNS, "groupbox");
        groupbox2.setAttribute("flex", "0.75")
        groupbox2.setAttribute("orient", "vertical")		
		var description=document.createElementNS(XULNS, "description");
		description.appendChild(document.createTextNode("Signatur"));
		groupbox2.appendChild(description)
		var button   = document.createElementNS(XULNS, "button")
		button.setAttribute("label", "ändern");
		button.addEventListener("click", function(){
        var hbox=document.createElementNS(XULNS, "hbox")
        var vbox=document.createElementNS(XULNS, "vbox")
        var mytextbox=document.createElement("textarea")
		var br=document.createElement("br")
        var spacer=document.createElementNS(XULNS, "spacer")
        var button=document.createElementNS(XULNS, "button")

		mytextbox.setAttribute("cols","50")
		mytextbox.setAttribute("rows","6")
        hbox.setAttribute("flex","1")
        hbox.setAttribute("stye","width:100%;height:100%;position:absolute;top:0;bottom:0")
        //hbox.setAttribute("flex","1")
        mytextbox.value=userSettings.get("signatur_text")+""
        spacer.setAttribute("flex","1")
		button.setAttribute("label","Speichern")
        hbox.appendChild(mytextbox)
		hbox.appendChild(br)
        hbox.appendChild(vbox)
        vbox.appendChild(spacer)
        vbox.appendChild(button)
        button.addEventListener("command", function(){
          userSettings.set("signatur_text", mytextbox.value);
          dialog.close()
        }, true);
        var div=document.createElement("div")
        div.appendChild(hbox)
        var dialog=new JautisDialog("Signatur ändern", div)
		}, true)
		groupbox2.appendChild(button)
		
  var groupbox3 = document.createElementNS(XULNS, "groupbox");
  groupbox3.setAttribute("flex", "0.75")
  groupbox3.setAttribute("orient", "vertical")
  
  var textdiv = document.createElement("div");
  textdiv.appendChild(document.createTextNode("Andere Funktionen"));
  textdiv.appendChild(document.createElement("br"));
  groupbox3.appendChild(textdiv)
    checkboxes.GroupViewing = JautisSettings.checkbox(
       "Vorschau auf Gruppen in Profilen", userSettings.get("allgemein.GroupViewing"));
    groupbox3.appendChild(checkboxes.GroupViewing);
	
	checkboxes.NWCode = JautisSettings.checkbox(
       "Automatisches NW-Code hinzufügen in Foren", userSettings.get("allgemein.NWCode"));
    groupbox3.appendChild(checkboxes.NWCode);

  elm.appendChild(groupbox)
  elm.appendChild(groupbox2)
  elm.appendChild(groupbox3)
  
  return checkboxes;
  }, function(checkboxes) {
    for(name in checkboxes) {
      userSettings.set("allgemein." + name,
                    checkboxes[name].getValue());
    }
}) );
})()}catch(e){debug(e)};
//END AREA ALGEMEINE EINSTELLUNGEN

//BEGIN AREA PROFILEPAGESCROLL
try{(function(){
if(!document.getElementById("Profile_InformationSnipplet")) {
  return;
}

function reloadStyles() {
  var computedStyles = {"borderRightColor": "#000000", "backgroundColor": "#ffffff"}
  var element = document.getElementById("Grid-Page-Center-Content");
  if (element) {
    computedStyles = getComputedStyle(element, "");
  }


  CSS("#provilenavigation  {position:absolute;right:0px;width:0px;top:100px;}"
    + "#provilenavigation > div  {position:fixed}"
    + "#provilenavigation svg {width:20px;height:20px;margin-top:10px;cursor:pointer;}"
    + "#provilenavigation .navigationBorder{ "
    + "fill:" + computedStyles.backgroundColor
    + "; stroke:"  + computedStyles.borderRightColor + "; stroke-width:1px}"
    + ".provilenavigation.inView .navigationBorder{ "
    + "fill:" + computedStyles.backgroundColor + ";}"
    + "#provilenavigation .dark, #provilenavigation .light{ "
    + "fill:" + computedStyles.borderRightColor + "; }"
    + "#provilenavigation .darkline{ "
    + "stroke:" + computedStyles.borderRightColor + "; stroke-width:1px}"
    + "#provilenavigation .light{ opacity:0.5; }")
}
reloadStyles();
window.addEventListener("load", reloadStyles, false);

var div = document.createElement("div")
var navcontainer = document.createElement("div")
div.appendChild(navcontainer);
div.id = "provilenavigation";
document.getElementById("Grid-Page-Center-Content").appendChild(div);

var navigationLinks = [];

function NavigationLink(type) {
  this.type = type;
  this.create();
  this.render();
}
NavigationLink.prototype.type = "";
NavigationLink.prototype.element = null;
NavigationLink.prototype.svg = null;


NavigationLink.prototype.create = function() {
  this.svg = document.createElementNS(SVGNS, "svg");
  this.svg.setAttribute("width", "20px");
  this.svg.setAttribute("height", "20px");
  this.createBorder();
  this.createIcon();

  this.element = document.createElement("div");
  this.element.appendChild(this.svg);
  navcontainer.appendChild(this.element);

  this.element.addEventListener("click", jautisHint(this, "click"), true);
}

NavigationLink.prototype.addPath = function(data, class) {
   var path = document.createElementNS(SVGNS, "path");
  path.setAttribute("d", data);
  path.setAttribute("class", class);
  this.svg.appendChild(path);
}

NavigationLink.prototype.createBorder = function() {
  this.addPath("M 0 0 L 2 2 L 18 2 L 20 4 L 20 16 L 18 18 L 2 18 L 0 20",
          "navigationBorder");
}

NavigationLink.prototype.createIcon = function() {
  if (this.type == "top") {
    this.addPath("M 3 16 l 7 -7 l 7 7 z", "light");
    this.addPath("M 3 10 l 7 -7 l 7 7 z", "dark");
  } else if (this.type == "profile") {
    this.addPath("M 7 10 L 8 11 L 8 16 L 7 17 L 11 17 L 10 16 L 10 11 L 11 10 z", "dark");
    this.addPath("M 6.5 6 a 2.5 2.5 0 0 1 2.5 -2.5 a 2.5 2.5 0 1 1 -2.5 2.5 ", "dark");
  } else if (this.type == "groups") { //TODO
  } else if (this.type == "pinn") {
    this.addPath("M 4 6 L 10 6 M 12 6 L 17 6 M 4 9 l 1 0 m 2 0 l 5 0 m 2 0 l 3 0 M 4 12 l 3 0 m 2 0 l 8 0 M 4 15 l 7 0", "darkline");
  } else if (this.type == "bottom") {
    this.addPath("M 3 4 l 7 7 l 7 -7 z", "light");
    this.addPath("M 3 10 l 7 7 l 7 -7 z", "dark");
  }
}

NavigationLink.prototype.render = function() {
  var class = "provilenavigation " + this.type;
  var inView = false;
  if (this.type == "top") {
    inView = window.scrollY < 100;
  } else if (this.type == "bottom") {
    inView = window.scrollY > window.scrollMaxY - 100;
  } else {
    var element = null;
    if (this.type == "profile") {
      element = document.getElementById("Profile_InformationSnipplet");
    } else if (this.type == "groups") {
      element = document.getElementById("Mod-Groups-Snipplet");
    } else if (this.type == "pinn") {
      element = document.getElementById("Mod-Pinboard-Snipplet");
    }

    if (element) {
      var top = globalOffsetTop(element);
      inView = window.scrollY > top - window.innerHeight
            && window.scrollY < top + element.offsetHeight;
    }
  }
  if (inView) {
    class += " inView";
  }
  this.element.className = class;
}

NavigationLink.prototype.click = function() {
  if (this.type == "top") {
    window.scroll(0, 0);
  } else if (this.type == "profile") {
    window.scroll(0, globalOffsetTop(
            document.getElementById("Profile_InformationSnipplet")));
  } else if (this.type == "groups") {
    window.scroll(0, globalOffsetTop(
            document.getElementById("Mod-Groups-Snipplet")));
  } else if (this.type == "pinn") {
    window.scroll(0, globalOffsetTop(
            document.getElementById("Mod-Pinboard-Snipplet")));
  } else if (this.type == "bottom") {
    window.scroll(0, window.scrollMaxY);
  }
}


navigationLinks.push(new NavigationLink("top"));
navigationLinks.push(new NavigationLink("profile"));
navigationLinks.push(new NavigationLink("groups"));
navigationLinks.push(new NavigationLink("pinn"));
navigationLinks.push(new NavigationLink("bottom"));
window.addEventListener("scroll", function() {
  navigationLinks.forEach(function(link) {link.render();})
}, true);

})()}catch(e){debug(e)};
//END AREA PROFILEPAGESCROLL


//BEGIN AREA PROFILEPAGEGROUPS
try{(function(){

if( !document.getElementById("Mod-Groups-Snipplet")) {
  return;
}
CSS(".groupsColumn       {position:relative;}")
CSS(".groupsColumn > div {position:absolute;top:2px;right:1em;}")

//Hole die Elemente
var groupslist = document.getElementById("Mod-Groups-Snipplet").getElementsByTagName("ul")[0]
var groupsheadline = document.getElementById("Mod-Groups-Snipplet").getElementsByTagName("h2")[0]

if(!groupslist || !groupsheadline)
  return;

CSS(".groupsCount {font-weight:normal;margin-left:.2em;}"
  + ".groupsCount:before {content:\"(\"} .groupsCount:after {content:\")\"}"
  + "#Mod-Groups-Snipplet h2 { position:relative;}"
  + ".GroupFilter { position:absolute; top:0; right:.2em; cursor:pointer;}"
  + "#ClearGroupFilter:after {content:\"⌫\"}"
  + ".GroupFilter .fieldText { float:none; font-size:100%;margin:0;"
  + " padding:1px 3px;min-width:5em;max-width:15em;width:0;}");

// number of groups
var span = document.createElement("span");
span.className = "groupsCount"
span.appendChild(document.createTextNode(
      "" + groupslist.getElementsByTagName("li").length));
groupsheadline.appendChild(span);

//Filter
/**
 * this function filters the group list fo a specific string.
 * @param searchString the string to be searched.
 */
function renderFilter(searchString) {
  var lis = groupslist.getElementsByTagName("li");
  debug("Suche wird ausgewertet: " + searchString);
  //The string to be searched
  var search = new RegExp("(" + searchString.replace(/(\W)/g, "\\$1") + ")", "i");

  //filterinput.style.width=search.length*0.6+"em";
  for (var listIndex = 0; listIndex < lis.length; listIndex++) {
    var a = lis[listIndex].getElementsByTagName("a")[0];
    if (!a) {
      continue;
    }
    //remove old highlightings
    if (a.childNodes.length != 1 || a.firstChild.nodeType != 3) {
      var text = document.createTextNode(a.textContent);
      while (a.firstChild) {
        a.removeChild(a.firstChild);
      }
      a.appendChild(text);
    }

    if (searchString == "") {
      //nothing to search => display
      lis[listIndex].style.display = "";

    } else if (a.firstChild.data.search(search) > -1) {
      /* search string found => split the text and add a <strong> around every
       * result */
      // an array in which every second element is a match to the regexp
      var found = a.firstChild.data.split(search);
      debug("Gefunden: " + found.toSource());
      for (var i = 0; i < found.length; i ++) {
        if ( i < found.length - 1) {
          //split text node if neccessary
          a.lastChild.splitText(found[i].length)
        }
        if (i % 2 == 1) {
          // a match => highlight
          var text = a.childNodes[i];
          var strongElement = document.createElement("strong");
          a.replaceChild(strongElement, text);
          strongElement.appendChild(text);
        }
      }
      lis[listIndex].style.display = "";

    } else {
      // not found => hide
      lis[listIndex].style.display = "none";
    }
  }
}


var filterdiv = document.createElement("div");
filterdiv.appendChild(document.createTextNode("Filter: "));
filterdiv.className = "GroupFilter";

var filterinput=document.createElement("input")
filterinput.className="fieldText"
filterinput.addEventListener("keyup", function(evt){
  renderFilter(evt.target.value);
}, true);
filterdiv.appendChild(filterinput)

var elm = document.createElement("span")
elm.id = "ClearGroupFilter";
elm.addEventListener("click", function(evt){
  filterinput.value = "";
  filterinput.style.width = 0;
  renderFilter("");
}, true);
filterdiv.appendChild(elm)

groupsheadline.appendChild(filterdiv);

})()}catch(e){debug(e)};
//END AREA PROFILEPAGEGROUPS


//BEGIN AREA GROUPMESSAGEREMINDER
try{(function(){
// reminds the user if he has new messages in a group topic
//TODO
})()}catch(e){debug(e)};
//END AREA GROUPMESSAGEREMINDER


//BEGIN AREA GROUPPAGES
try{(function(){

//only if you are a member
if (document.getElementById("Groups_Overview")
  && evaluateXPath(document.getElementById("Groups_Overview"),
 "div[1]/div[@class=\"forumThreadsOverview obj-innerbox\"]").length > 0) {


  //Einstellungen (E-Mail-Benachrichtungung, unsichtbar)

  var h2 = document.createElement("h2");
  h2.className = "mH";
  h2.appendChild(document.createTextNode("Einstellungen"))

  var form = document.createElement("form");
  form.className = "groupsRightColumns"
  form.action = "/Groups/";
  form.method = "POST";

  function onload() {
    var response = settingspage.responseText
    form.innerHTML = "";

    var label = document.createElement("label");
    var input_email = document.createElement("input");
    input_email.type = "checkbox";
    if (response.search(/ id="Groups_emailNotification2"[^>]*checked/) > -1) {
      input_email.checked = true;
    }
    label.appendChild(input_email);

    label.appendChild(document.createTextNode("E-Mail bei neuen Nachrichten"));
    form.appendChild(label);

    form.appendChild(document.createElement("br"));

    if (VZ_NETWORK == "schuelervz") {
      //schuelervz
      var label = document.createElement("label");
      var input_visible = document.createElement("input");
      input_visible.type = "checkbox";
      if (response.search(/id="Groups_visibility0"[^>]*checked/) > -1) {
        input_visible.checked = true;
      }
      label.appendChild(input_visible);

      label.appendChild(document.createTextNode("Jeder darf sehen dass ich in dieser Gruppe bin"));
      form.appendChild(label);
    } else {
      //studivz / meinvz seperated
      var label = document.createElement("label");
      var input_visibilityAllUnis = document.createElement("input");
      input_visibilityAllUnis.type = "checkbox";
      if (response.search(/id="visibilityAllUnis"[^>]*checked/) > -1) {
        input_visibilityAllUnis.checked = true;
      }
      label.appendChild(input_visibilityAllUnis);

      label.appendChild(document.createTextNode("StudiVZ-Nutzer dürfen sehen dass ich in dieser Gruppe bin"));
      form.appendChild(label);

      var label = document.createElement("label");
      var input_visibilityAllPlatforms = document.createElement("input");
      input_visibilityAllPlatforms.type = "checkbox";
      if (response.search(/id="visibilityAllPlatforms"[^>]*checked/) > -1) {
        input_visibilityAllPlatforms.checked = true;
      }
      label.appendChild(input_visibilityAllPlatforms);

      label.appendChild(document.createTextNode("MeinVZ-Nutzer dürfen sehen dass ich in dieser Gruppe bin"));
      form.appendChild(label);
    }

    form.appendChild(document.createElement("br"));

    var input_submit = document.createElement("input");
    input_submit.type = "submit";
    input_submit.value = "Ändern";
    input_submit.className = "fieldBtnSubmit";
    form.appendChild(input_submit);

    form.addEventListener("submit", function(evt){
      evt.preventDefault()
      var text = settingspage.responseText;
      var text = text.substr(text.indexOf("<div id=\"GroupSettings\">"));
      var data = "formkey=" + /name="formkey" value="(\w+)/.exec(text)[1]
               + "&iv="+ /name="iv" value="(\w+)/.exec(text)[1]
               + "&groupId="+ /name="groupId" value="(\w+)/.exec(text)[1];

      data += "&emailNotification=" + (input_email.checked ? "2" : "0");
      if (VZ_NETWORK == "schuelervz") {
        data += "&visibility=" + (input_visible.checked ? "1" : "0");
      } else {
        if (input_visibilityAllPlatforms.checked) {
          data += "&visibilityAllPlatforms=1";
        }
        if (input_visibilityAllUnis.checked) {
          data += "&visibilityAllUnis=1";
        }
      }

      debug("Sende Daten um Gruppeneisntellungen zu ändern: " + data)

      var settingsRequest = new XMLHttpRequest();
      settingsRequest.open('POST',VZ_SERVER + "Groups/",true);
      settingsRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      settingsRequest.setRequestHeader("Content-Length", data.length);
      settingsRequest.onload = function(){
        alert(settingsRequest.responseText.indexOf("gespeichert")>-1
          ? "Einstellungen gespeichert"
          : "Fehler beim Speichern der Einstellungen");
      }
      settingsRequest.send(data)
    }, true);
  }
  var settingspage = new XMLHttpRequest();
  settingspage.open("GET", location.href.replace("Overview","Settings"), true);
  settingspage.onload = onload;
  settingspage.send(null);

  form.innerHTML = "lade...";

  var result = evaluateXPath(document.getElementById("Groups_Overview"),
                             "div[2]/h2[2]");
  if(result.length > 0) {
    result[0].parentNode.insertBefore(form, result[0])
    result[0].parentNode.insertBefore(h2, form)
  }
  //Ende Einstellungen
}

})()}catch(e){debug(e)};
//END AREA GROUPPAGES



//BEGIN AREA GROUPS
try{(function(){

if (!userSettings || !userSettings.register || !USERIDS) {
  return;
}

userSettings.register("group_list", {});

//Objekt aus Gruppen immer
//groupList[ids] = {
//  name:
//  founder: [name, ids, image]
//  mods:[ [name, ids, image], ... ]
//  mod:(bool)
//  members:(integer)
//  is_old:(bool)
//  lastvisit:(date)
//}


var groupList = userSettings.get("group_list");
if(typeof groupList != "object")
  groupList = {};

function safeGroupsList() {
  userSettings.set("group_list", groupList);
}

// reload group  list if you are at your own profile page.
if (location.href.indexOf(USERIDS) > -1
  && document.getElementById("Mod-Groups-Snipplet")){

  for(var i in groupList){
    groupList[i].is_old = true;
  }

  var as=document.getElementById("Mod-Groups-Snipplet").getElementsByTagName("a")
  for(var i=0;i<as.length;i++){
    tmp=/\/Groups\/Overview\/(\w+)/.exec(as[i].href)
    if(!tmp)
      continue;

    var ids=tmp[1];

    if(!groupList[ids])
      groupList[ids]={ name:as[i].textContent }

    groupList[ids].is_old=false;
  }

  safeGroupsList()
}

// add member/moderator/... information to group list on profile pages
if (document.getElementById("Mod-Groups-Snipplet")) {
  CSS(".groupStatus {font-weight:normal;margin-left:.2em;color:inherit;}"
    + ".groupStatus:before {content:\"(\"} .groupStatus:after {content:\")\"}");

  var as = document.getElementById("Mod-Groups-Snipplet")
                   .getElementsByTagName("a");
  for (var linkIndex = 0; linkIndex < as.length; linkIndex++){
    tmp = /\/Groups\/Overview\/(\w+)/.exec(as[linkIndex].href);
    if (!tmp || !groupList[ tmp[1] ]) {
      continue;
    }

    var group = groupList[ tmp[1] ];
    var texts = false;
    if (group.is_old) {
      texts = ["Ehem" , "Ehemaliger", "status_ehem"];
    } else if (group.mod) {
      texts = ["Mod"  , "Moderator" , "status_mod"];
    } else if (group.founder && group.founder[1] == USERIDS) {
      texts = ["G"    , "Gründer"   , "status_g"];
    } else if (location.href.indexOf(USERIDS) < 0) {
      texts = ["M"    , "Mitglied"  , "status_m"];
    } else {
      texts = false;
    }

    if (texts) {
      var statusElement = document.createElement("span")
      statusElement.className = "groupStatus";
      statusElement.appendChild(document.createTextNode(texts[0]))
      statusElement.title = texts[1];
      as[linkIndex].parentNode.appendChild(statusElement);

      as[linkIndex].parentNode.className += " " + texts[2]
    }
  }
}

if (location.href.indexOf("/Forum/ThreadMessages/") > -1) {

  CSS(".groupstatus_g:after {content:\" (G)\";font-weight:normal;}"
    + ".groupstatus_mod:after {content:\" (Mod)\";font-weight:normal;}");

  tmp = /\/Forum\/ThreadMessages\/(\w+)/.exec(location.href)
  if(!tmp || !groupList[tmp[1]])
    return; //kommt eh nix wichtiges mehr

  var group = groupList[tmp[1]]

  var as = document.getElementById("Grid-Page-Center-Content")
                   .getElementsByTagName("a")
  for (var i = 0; i < as.length; i++) {
    tmp=/\/Profile\/([\w-]+)/.exec(as[i].href)
    if(!tmp || as[i].getElementsByTagName("img").length > 0) {
      continue;
    }

    if(group.founder && group.founder[1]==tmp[1]){
      as[i].className = as[i].className
          ? as[i].className + " groupstatus_g" : "groupstatus_g";
      continue;
    }

    for (var j = 0; group.mods && j < group.mods.length; j++) {
      if (group.mods[j][1] == tmp[1]) {
        as[i].className = as[i].className
            ? as[i].className + " groupstatus_mod" : "groupstatus_mod";
      }
    }
  }

}

//Read group data
if (document.getElementById("Groups_Overview")) {

  var ids = document.getElementById("Groups_Overview_GroupIds").value

  var group = groupList[ids];

  if(group) {

    var dds=document.getElementById("GroupsInformation").getElementsByTagName("dd")
    var dts=document.getElementById("GroupsInformation").getElementsByTagName("dt")
    group.mods=[];

    for(var i=0;i<dds.length-1;i++){
      var dd = dds[i];
      var dt = dts[i];
      if(!dt)
        continue;

      if(dt.textContent.indexOf("Gründer:")>-1) {
        var a=dd.getElementsByTagName("a")[0] || {};
        tmp=/\/Profile\/([\w-]+)/.exec(a.href)
        if(tmp)
          group.founder=[a.textContent, tmp[1]];
      }//if

      else if(dt.textContent.indexOf("Moderatoren:") > -1){
        var as=dd.getElementsByTagName("a");
        for(var j=0;j<as.length;j++){
          tmp=/\/Profile\/([\w-]+)/.exec(as[j].href)
          if(!tmp)
            continue;
          if(tmp[1]==USERIDS)
            group.mod=true;
          group.mods.push([as[j].textContent, tmp[1]]);
        }//for
      }//if
    }//for

    safeGroupsList()
  }
}


})()}catch(e){debug(e)};
//END AREA GROUPS


//BEGIN AREA GROUPAJAXFORUM
try{(function(){

function to_Date(text){
  matches=/(\d+)\.(\d+)\.(\d{2,4}) um (\d+)\:(\d+)/i.exec(text);
  if(!matches)
    return false;
  return new Date(matches[3], matches[2]-1, matches[1], matches[4], matches[5], 0);
}

if (document.getElementById("Groups_Overview")) {
  var forumDiv = (evaluateXPath(document.getElementById("Groups_Overview"),
        "div[1]/div[@class=\"forumThreadsOverview obj-innerbox\"]") || [null])[0];
} else {
  var forumDiv = null;
}

if (forumDiv) {
  CSS(".forumThreadsOverview li {float:none;position:relative;overflow:hidden;}")
  CSS(".commentMetaData {float:none; position:relative;}");
  CSS(".commentMetaData .floatR {float:none;position:absolute;top:1px;right:.2em;}");
  CSS(".commentMetaData .forumThreadsTitle {float:none;display:block;margin-right:5em;}");
  CSS(".previewThreadsDetails {min-height:1.2em}");
  CSS(".previewThreadsDetails .floatL {position:absolute;float:none;}");
  CSS(".previewThreadsDetails .floatR {margin-left:25%;float:none;text-align:right;}");

  const GROUPIDS = (/\/Groups\/Overview\/(\w+)/i.exec(location.href)
                   || ["", ""])[1];


  var forumList = forumDiv.getElementsByTagName("ul")[0];

  if(!forumList || !GROUPIDS) {//Forum empty or another error
    return;
  }

  /** class for a topic of the forum */
  function forumThread(id, lastentry, lastwriterid, lastwritername) {

  }


  /** the list of thread elements that is currently displayed */
  var displayedThreadElements = [];

  //check if the mouse is over the list
  var mouse_is_over_forumlist = false;

  document.body.addEventListener("mousemove", function(){
    mouse_is_over_forumlist = false;
  }, true);
  forumList.addEventListener("mousemove", function(){
    mouse_is_over_forumlist = true;
  }, true);

  function blendForumElementOut(object) {//elm=<li>
    var step = 0;
    var element = object.element;
    var elementRealHeight = element.offsetHeight;
    element.style.position = "relative";

    function nextStep() {
      if(mouse_is_over_forumlist){
        return;
      }
      if (step > 4){
        element.parentNode.removeChild (element);
        clearInterval (interval);
      } else {
        element.style.opacity = 0.8 - step/5
        element.style.height = elementRealHeight * (1 - step / 5) + "px";
        step++;
      }
    }
    element.style.height = elementRealHeight + "px";
    var interval = setInterval(nextStep, 200);
    nextStep();
  }


  function blendForumElementIn(object){//elm=<li>
    var step = 0;
    var element = object.element;
    var elementRealHeight = element.offsetHeight;
    element.style.display = "";

    function nextStep() {
      if (mouse_is_over_forumlist) {
        return;
      }

      if (step > 3) {
        element.style.opacity = "";
        element.style.height = "";
        clearInterval(interval);
      } else {
        element.style.display = "";
        element.style.opacity = step * 0.3;
        element.style.height  = elementRealHeight * step * 0.26 + "px";
        step++;
      }
    }

    element.style.display = "none";
    var interval = setInterval(nextStep, 200);
    nextStep();
  }

  function getElementForThread(thread) {
    var li = document.createElement("li");

    //first line
    var div = document.createElement("div");
    div.className = "comment-metainfo";
    li.appendChild(div);

    var date = document.createElement("div");
    date.className = "comment-actions";
    date.appendChild(document.createTextNode(thread.created))
    div.appendChild(date);

  thread.title = thread.title.replace(/&#(.?.?.?.);/g,function (all, a){
  a = String.fromCharCode(a);
  return a;})
  thread.lastwritername = thread.lastwritername.replace(/&#(.?.?.?.);/g,function (all, a){
  a = String.fromCharCode(a);
  return a;})
    var link = document.createElement("a");
    link.className = "profile";
    link.href = "/Forum/ThreadMessages/" + GROUPIDS + "/" + thread.id;
    link.appendChild(document.createTextNode(thread.title))
    div.appendChild(link);

    //second line
    var div = document.createElement("div");
    div.className = "comment-content";
    li.appendChild(div);

    var left = document.createElement("div");
    left.className = "float-left";
    left.appendChild(document.createTextNode(thread.answercount == 1
             ? "[eine Antwort]" : "[" + thread.answercount + " Antworten]"))
    div.appendChild(left);

    if (thread.lastwriterid != "") {
      var right = document.createElement("div");
      right.className = "float-right";
      right.appendChild(document.createTextNode("[letzte Antwort von "))
      var link = document.createElement("a");
      link.className = "profile";
      link.href = "/Profile/" + thread.lastwriterid;
      link.appendChild(document.createTextNode(thread.lastwritername))
      right.appendChild(link);
      right.appendChild(document.createTextNode(": " + thread.lastmessagetime + "]"))
      div.appendChild(right);
    }

    //only use BBCode if we download the complead post.
    new Tooltip(li, "Letzte Antwort: " + thread.lastmessage);
    //TODO: improve, with ajax - loading
    return li;
  }


  function reloadThreads() {
    var request = new XMLHttpRequest();
    request.open("GET", VZ_SERVER + "Forum/Threads/" + GROUPIDS, true);
    request.onload = function() {
      reloadThreads_onload(request);
    };
    request.send(null);
  }

  function reloadThreads_onload(request) {
    var threads = [];
    var items = request.responseText.substr(
      request.responseText.indexOf('class="obj-comment-list"')).split("<li>");
    for (var index = 1; index < items.length; index++) {
      /* [all, created, id, lastwriterid, lastwritername, lastmessage,
        answercount, lastmessagetime] */
      var data = /<div class="comment-actions">(\S*)[\w\W]*?\/ThreadMessages\/\w+\/(\w+)\"[^>]*>([^<]*)[\w\W]*?(?:\/Profile\/([-\w]+)">([^<]*)<\/a>[\w\W]*\:\s([\w\W]*?)\s*<div class="comment-footer">[\w\W]*?\[(\d+|eine) \w+\][\w\W]*?letzte Antwort[\w\W]*?:\s([^\]]*)\]|keine Antworten)/.exec(items[index]);

      if (data) {
        threads.push({
          created:         data[1],
          id:              data[2],
          title:           data[3],
          lastwriterid:    !data[4] ? "" : data[4],
          lastwritername:  !data[5] ? "" : data[5],
          lastmessage:     !data[6] ? "" : data[6],
          answercount:     !data[7] ? 0 : data[7] == "eine" ? 1 : parseInt(data[7]),
          lastmessagetime: !data[8] ? "" : data[8]
        });
      } //end if(data)

    } //end for(index)

    setCurrentThreads(threads);
  }


  function setCurrentThreads(threads) {
    //the old threads as object
    var oldthreads = {}
    for (var i = 0; i < displayedThreadElements.length; i++) {
      oldthreads[displayedThreadElements[i].id] = displayedThreadElements[i];
    }

    /**
     * how this works:
     * - go through the current threads:
     *   - if the tread is new: insert it at the current position.
     *   - else
     *      - remove all old elements until you find the new thread.
     * instead of adding new items directly, they are written to a buffer.
     */
    var oldIndex = 0, buffer = [], li;
    for (var newIndex = 0; newIndex < threads.length; newIndex++) {
      var id = threads[newIndex].id;

      if (!oldthreads[id]
              || oldthreads[id].lastmessagetime != threads[newIndex].lastmessagetime
              || oldthreads[id].lastwriterid != threads[newIndex].lastwriterid
              || oldthreads[id].answercount != threads[newIndex].answercount) {
        // new Message in thread => insert at current position.
        threads[newIndex].element = getElementForThread(threads[newIndex]);
        buffer.push(threads[newIndex])
      } else {
        while (oldIndex < displayedThreadElements.length
            && displayedThreadElements[oldIndex].id != id) {
          blendForumElementOut(displayedThreadElements[oldIndex]);
          oldIndex++;
        }
        while (thread = buffer.shift()) {
          forumList.insertBefore(thread.element, oldthreads[id].element);
          blendForumElementIn(thread);
        }
        threads[newIndex].element = oldthreads[id].element;
        oldIndex++;
      }
    }
    while (thread = buffer.shift()) {
      if (displayedThreadElements[oldIndex]) {
        forumList.insertBefore(thread.element, displayedThreadElements[oldIndex].element);
      } else {
        forumList.appendChild(thread.element);
      }
      blendForumElementIn(thread);
    }
    while (oldIndex < displayedThreadElements.length) {
      blendForumElementOut(displayedThreadElements[oldIndex]);
      oldIndex++;
    }

    displayedThreadElements = threads;
  }

  //Initialisieren
  for (var item = 0; item < forumList.childNodes.length; item++) {
    var li = forumList.childNodes[item];
    if (li.nodeType != 1) {
      continue;
    }
    var as = li.getElementsByTagName("a");

    var data = {
          created:         "",
          id:              as[1] ? /\/ThreadMessages\/\w+\/(\w+)/.exec(as[1].href) : "",
          title:           as[1] ? as[1].textContent : "",
          lastwriterid:    "",
          lastwritername:  "",
          lastmessage:     "",
          answercount:     "",
          lastmessagetime: "",
          element:         li}
    displayedThreadElements.push(data);
  }


  //laden aktivieren
  reloadThreads();
  setInterval(reloadThreads, 20*1000);
} else if (document.getElementById("answerMsgBox")) {
  CSS("#answerMsgBox .dialog-title {position:relative}");
  CSS("#answerMsgBox .dialog-title label {position:absolute;top:-3px; right: 1em;}");

  CSS("#Grid-Page-Center-Content.chatMode .innerbox-info,"
    + "#Grid-Page-Center-Content.chatMode .inline-input,"
    + "#Grid-Page-Center-Content.chatMode .form-buttons {display:none}");
  CSS("#Grid-Page-Center-Content.chatMode #answerMsgBox {display:blocK}");
  CSS("#Grid-Page-Center-Content.chatMode .comment-footer, #Grid-Page-Center-Content.chatMode .comment-actions {display:none}");
  CSS("#Grid-Page-Center-Content.chatMode .comment-metainfo {position:relative}");
  CSS("#Grid-Page-Center-Content.chatMode .comment-metainfo span {position:absolute;top:2px; right: 1em;}");
  CSS("#Grid-Page-Center-Content.chatMode .wysiwygTextarea > iframe, #Grid-Page-Center-Content.chatMode #Forum_content {height:5em;}");
  CSS("#answerMsgBox .status_sent, #answerMsgBox .status_error, #answerMsgBox .status_sending {background-repeat:no-repeat; background-position:top right}");
  CSS("#answerMsgBox .status_sent {background-image:url('{IMG:messagesend-ok.png}')}");
  CSS("#answerMsgBox .status_error {background-image:url('{IMG:messagesend-error.png}')}");
  CSS("#answerMsgBox .status_sending {background-image:url('{IMG:loading_16.png}')}");
  CSS("#answerMsgBox .wysiwygTextarea {width:420px;float:left;}");
  CSS("#answerMsgBox .wysiwygTextarea > textarea, #answerMsgBox .wysiwygTextarea > iframe {float:none;width: 100%; -moz-box-sizing:border-box}");
  CSS("div.obj-box form {overflow:visible}");


  //array of objects:
  // - element <li>
  // - checksum //to compare 2 elements => their content //TODO: improfe?
  var newMessageForm = document.getElementById("Forum_content").form;

  var messageList = [];
  var messagesUL = document.getElementById("answerMsgBox");
  while (messagesUL && messagesUL.tagName != "UL") {
    messagesUL = messagesUL.nextSibling;
  }
  if (!messagesUL) { //should not happen!
    debug("Nachrichtenliste nicht gefunden!");
    return;
  }
  
  var textbox = document.getElementById("Forum_content");
  var newMessageField = new BBCodeableTextarea(textbox);

  /* timeout set after the message is send successfully */
  var resetStatusIconTimeout = null;
  function setStatus(status) {
    if (resetStatusIconTimeout) {
      clearTimeout(resetStatusIconTimeout);
      resetStatusIconTimeout = null;
    }
    newMessageForm.className =(newMessageForm.className + "")
                    .replace(/\s?status_\w+/, "") + " status_" + status;
  }
  
  function makeAreaEditable(groupId, threadId, messageId, area) {
    var formFields = {groupId:groupId, threadId:threadId, messageId:messageId, iv:"", formkey:""};
    area.makeEditable(function(cb) {
      var callback = cb;
      var request = new XMLHttpRequest();
      request.open("GET", "/Forum/EditThreadMessage/" + formFields.groupId + "/"
          + formFields.threadId + "/" + formFields.messageId, true)
      request.addEventListener("load", function() {
        var respText = request.responseText.substr(
           request.responseText.indexOf('<div id="Grid-Page-Center-Content">'));
        var text = /<textarea id=\"Forum_content\"[^>]*>([^<]*)<\/textarea>/.exec(respText);
        formFields.content = text ? text[1].replace(/&#(\d+);/g,
                function(all, code) {return String.fromCharCode(code)}) : "NICHT SPEICHERN!";
        var iv = /<input type="hidden" name="iv" value="(\w+)/.exec(respText);
        formFields.iv = iv ? iv[1] : "";
        var formkey = /<input type="hidden" name="formkey" value="(\w+)/.exec(respText);
        formFields.formkey = formkey ? formkey[1] : "";
        callback(formFields.content);
      }, true);
      request.send(null)
    }, function(text, cb) {
      var callback = cb;
      formFields.content = text;
      var data = [];
      for (var i in formFields) {
        data.push(i + "=" + decodeURIComponent(formFields[i]));
      }
      var request =  new XMLHttpRequest();
      request.open("POST", "/Forum/EditThreadMessage/" + formFields.groupId + "/"
          + formFields.threadId + "/" + formFields.messageId, true)
      request.setRequestHeader("Content-Type",
          "application/x-www-form-urlencoded; charset=UTF-8");
      request.addEventListener("load", function() {
        callback(formFields.content.replace(/\n/g, "<br>"));
      }, true);
      request.send(data.join("&"));
    });
    
    //
  }

  /**
   * parses the message for bb code and adds a quote-link to it.
   * @param listElement a list element containing the forum entry. The content
   *                    has to be seperater from the footer.
   */
  function parseMessageForBBCode(listElement) {
    //divs[0] is the message, divs[1] are the buttons
    var divs = evaluateXPath(listElement,
        "div[1]/div[@class=\"comment-content\"]/div");
    if (divs.length < 1) {
      return;
    }
    
    var area = new BBCodeArea(listElement.getElementsByClassName("comment-content-text")[0]);
    var allAs = listElement.getElementsByTagName("a");
    var results = Array.filter(allAs, function(a) {
        return /Forum\/EditThreadMessage\/(\w+)\/(\w+)\/(\w+)/.exec(a.href) != null;
      })
    if (results[0]) {
      var res = /Forum\/EditThreadMessage\/(\w+)\/(\w+)\/(\w+)/.exec(results[0].href);
      makeAreaEditable(res[1], res[2], res[3], area);
    }
    
    //quote
    var footerDivs = listElement.getElementsByClassName("comment-footer");
    var footerDiv = footerDivs[0] || divs[0];
    var quoteLink = document.createElement("a");
    quoteLink.appendChild(document.createTextNode("[Zitieren]"))
    quoteLink.href = "javascript:;";
    quoteLink.addEventListener("click", function(evt) {
      document.getElementById("answerMsgBox").style.display = "block";
      window.scrollY = 100;
      var listElement = evt.target.parentNode.parentNode.parentNode.parentNode;
      var a = listElement.getElementsByTagName("a")[0] || {};
      var ids = (/Profile\/([\w-]+)/.exec(a.href) || ["", ""])[1] ;
      var img = listElement.getElementsByTagName("img")[0] || {};
      var name = img.alt;
      newMessageField.addQuote( area.source
        .replace(/[nw]([\w\W+])[/nw]/g, 
              function(all, nw) {return nw.replace(/ /g, "")})
        .trim(), name, "/Profile/" + ids);
    }, true);
    var footerAs = footerDiv.getElementsByTagName("a");
    if (footerAs.length < 1) {
      footerDiv.appendChild(document.createTextNode(" "))
      footerDiv.appendChild(quoteLink)
    } else if (footerAs[footerAs.length-1].nextSibling) {
      var prev = footerAs[footerAs.length-1];
      prev.parentNode.insertBefore(quoteLink, prev.nextSibling);
      prev.parentNode.insertBefore(document.createTextNode(" "), prev.nextSibling);
    } else {
      footerAs[footerAs.length-1].parentNode.appendChild(document.createTextNode(" "))
      footerAs[footerAs.length-1].parentNode.appendChild(quoteLink)
    }

//     var bbcoder = new BBCoder();
//     bbcoder.parseNodeWithBR(divs[0]);
  }
  
  function getTimeBetweenUpdates() { //in MS
    var time = to_Date(messageList[0].element
      .getElementsByClassName("datetime")[0].textContent);
    var diff = Date.now() - time.getTime();
    if (diff < 10000) { // 3s
      diff = 10000;
    } else if (diff > 600000) { //10 min
      diff = 600000;
    }
    //TODO: multiplay by user pref
    return chatModeActive ? diff / 8 : diff / 3;
  }
  
  var lastRequest = Date.now();
  function reloadMessages() {
    debug(getTimeBetweenUpdates())
    if (Date.now() - lastRequest < getTimeBetweenUpdates()) {
      debug("Update skipped, intervall between updates was too short");
      return;
    }
    lastRequest = Date.now();
    var request = new XMLHttpRequest();
    request.open("get", location.href, true);
    request.onload = function() {reciveMessages(request)};
    request.send(null);
  }

  //TODO: delete old elements
  function reciveMessages(request) {
    lastRequest = Date.now();
    var text = request.responseText.substr(request.responseText.indexOf(
                    '<div class="form-buttons">'));

    var tmp = /name=\"iv\" value=\"(\w+)\"/.exec(text);
    newMessageForm.elements.namedItem("iv").value = tmp ? tmp[1] : "";
    var tmp = /name=\"formkey\" value=\"(\w+)\"/.exec(text);
    newMessageForm.elements.namedItem("formkey").value = tmp ? tmp[1] : "";

    if (request.responseText.indexOf("Die Antwort wurde gespeichert") > -1) {
      setStatus("sent")
      resetStatusIconTimeout = setTimeout(function() {setStatus("")}, 3000);
    } else if (request.responseText.indexOf(" class=\"error\"") > -1
        || request.responseText.indexOf(" class=\"invalid\"") > -1
        || request.responseText.indexOf(" class=\"highlight errorMsg\"") > -1) { // TODO: improve error detection
      setStatus("error")
      debug(request);
    }

    text = text.substr(0, text.indexOf("</ul>"));
    text = text.split("<li>");
    for (var index = text.length - 1; index > 0; index--) {
      var realText = text[index].substr(0, text[index].indexOf("</li>"));
      if (realText.indexOf("href=\"/l/") > -1) {
        break; //TODO: improve this and don't use this dirty trick!
      }

      var check = realText.replace(/<[^>]*>|&[^;]+;|[\s\n\'\"]/g, "");
      var checkfunc = function(item) {return item.checksum == check};
      if (messageList.some(checkfunc)) {
        //element already found;
      } else {
        var element = document.createElement("li");
        element.innerHTML = realText.replace(/(class=\"comment-content\">)([\s\S]+?)(<div)/, "$1<div>$2</div>$3");
        parseMessageForBBCode(element);
        messagesUL.insertBefore(element, messagesUL.firstChild);
        messageList.splice(0, 0, {element: element, checksum:check});
      }
      delete check, realText, checkfunc;
    }
//     delete text;
  }

  //load the current message list
  for (var index = 0; index < messagesUL.childNodes.length; index++) {
    var node = messagesUL.childNodes.item(index);
    if (node.nodeType != 1) {
      continue;
    }

    var check = node.innerHTML.replace(/<[^>]*>|&[^;]+;|[\s\n\'\"]/g, "");

    //extract the text int an own div
    var divs = evaluateXPath(node,
        "div[1]/div[@class=\"comment-content\"]");
    var contentdiv = divs[0]
    //move all divs except the footer ones to a new div
    var newDiv = document.createElement("div");
    var noDivs = Array.filter(contentdiv.childNodes, function(node) {
      return node.nodeType != 1 || node.tagName != "DIV";
    });

    Array.forEach(noDivs, function(node) {
      newDiv.appendChild(node);
    });
    contentdiv.insertBefore(newDiv, contentdiv.firstChild);
    
    
    parseMessageForBBCode(node);

    messageList.push( {
      element: node,
      checksum: check
    });
  }
  
  reloadMessages();
  setInterval(reloadMessages, 5*1000);
  
  
  
  // Forumbeitragsfunktionen
  /**
   * Dieser Bereich fügt die Zusatzfunktionen unter den Forenbeiträgen hinzu.
   * Außerdem wird ein Link zum anzeigen/verstecken dieser Funktionen angeziegt.
   * Alle Funktionsbereiche sollten die Klasse form-row und forumExtras haben
   */
  
  userSettings.register("forum.showExtras", false);
  // Link zum anzeigen/verstecken der Funktionen
  var extrasShowHideLink;
  // extras anzeigen?
  var showExtras = userSettings.get("forum.showExtras");
  // Container der angezeigt/versteckt werden soll
  var extrasContainer;
  //Element vor das alle Bereiche eingefügt werden sollen
  var insertBeforeThis = document.getElementById("Forum_attachPic");
  
  if (insertBeforeThis) {
    insertBeforeThis = insertBeforeThis.parentNode;
    if (insertBeforeThis.className) {
      insertBeforeThis.className += " forumExtras";
    }
  } else {
    insertBeforeThis = document.createElement("div");
    newMessageForm.appendChild(insertBeforeThis);
  }
  extrasContainer = insertBeforeThis.parentNode;
  
  
  extrasShowHideLink = document.createElement("a");
  extrasShowHideLink.appendChild(document.createTextNode("Extras"));
  extrasShowHideLink.id = "extrasShowHideLink"
  extrasShowHideLink.href = "javascript:;"
  extrasShowHideLink.addEventListener("click", function() {
  if (showExtras) {
    showExtras = false;
    extrasContainer.className 
               = extrasContainer.className 
               ? extrasContainer.className + " hideExtras"
               : "hideExtras";
    userSettings.set("forum.showExtras", false);
   } else {
    showExtras = true;
    extrasContainer.className 
           = extrasContainer.className.replace("hideExtras", "");
    userSettings.set("forum.showExtras", true);
   }
  }, true)
  extrasContainer.insertBefore(extrasShowHideLink, insertBeforeThis);
  if (!showExtras) {
    insertBeforeThis.parentNode.className 
               = insertBeforeThis.parentNode.className 
               ? insertBeforeThis.parentNode.className + " hideExtras"
               : "hideExtras";
  }
  
  CSS(".hideExtras .forumExtras {display:none} "
    + "#extrasShowHideLink { display:block; height:0; overflow:visible; }"
    + "#extrasShowHideLink::before {content:\"▼ \"}"
    + ".hideExtras #extrasShowHideLink::before {content:\"► \"}");
  
  
  
  
  function downUnder(text) {
        var translationsa="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZäöüÄÖÜ1234567890!?,.({[<_"
        var translationsb="ɐqɔpǝɟƃɥıɾʞlɯuodbɹsʇnʌʍxʎzɐqɔpǝɟƃɥıɾʞlɯuodbɹsʇnʌʍxʎzäöüÄÖÜ⇂ᄅᄐㄣގ9ㄥ860¡¿'˙)}]>‾"
        var newtext="";
        for(var i=text.length-1;i>=0;i--){
          var chr=text.charAt(i);
          if(translationsa.indexOf(chr)>-1)
            newtext+=translationsb.substr(translationsa.indexOf(chr),1)
          else if(translationsb.indexOf(chr)>-1)
            newtext+=translationsa.substr(translationsa.indexOf(chr),1)
          else
            newtext+=chr;
        }
        return newtext;
      }
	  function lined(text){
        var newtext="";
		newtext+=text.replace(/(\S)/gi, '̶$1̶');
        return newtext;
      }
	  function backwards(text){
        var translationsa="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZäöüÄÖÜ1234567890!?,.({[<_"
        var translationsb="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZäöüÄÖÜ1234567890!?,.({[<_"
        var newtext="";
        for(var i=text.length-1;i>=0;i--){
          var chr=text.charAt(i);
          if(translationsa.indexOf(chr)>-1)
            newtext+=translationsb.substr(translationsa.indexOf(chr),1)
          else if(translationsb.indexOf(chr)>-1)
            newtext+=translationsa.substr(translationsa.indexOf(chr),77)
          else
            newtext+=chr;
        }
        return newtext;
        }

      /*                    Vorschau                    */

      // entfernt, da BBCodeTextarea diese Funktion im BB-Code-Modus schon 
      // bietet,


      /*                 Verschlüsseln                 */
      var row = document.createElement("div");
      row.className = "form-row forumExtras inline-input";
      var encryptMethod = 3, do_encrypt=false;
      //input type=checkbox
      var elm=document.createElement("input")
      elm.type="checkbox";
      elm.id="checkboxForEncrypt"
      elm.className="fieldCheckbox";
      elm.addEventListener("change", function(evt){
        do_encrypt=evt.target.checked;
        //encrypt_Settingsdiv.style.display=evt.target.checked ? "block" : "none"
      }, true)
      row.appendChild(elm)
      

      //Label
      var elm=document.createElement("label")
      elm.htmlFor="checkboxForEncrypt"
      elm.appendChild(document.createTextNode("Verschlüsseln"));
      row.appendChild(elm)
      
      extrasContainer.insertBefore(row, insertBeforeThis);
          /*                 Durchgestrichen            */
      var row = document.createElement("div");
      row.className = "form-row forumExtras inline-input";

      //input type=checkbox
      var lined_checkbox=document.createElement("input")
      lined_checkbox.type="checkbox";
      lined_checkbox.id="checkboxForLined"
      lined_checkbox.className="fieldCheckbox";
      row.appendChild(lined_checkbox)

      //Label
      var elm=document.createElement("label")
      elm.htmlFor="checkboxForLined"
      elm.appendChild(document.createTextNode("Durchstreichen"));
      row.appendChild(elm)

                  
      extrasContainer.insertBefore(row, insertBeforeThis);


      /*                 Auf den Kopf stellen            */
      var row = document.createElement("div");
      row.className = "form-row forumExtras inline-input";

      //input type=checkbox
      var downunder_checkbox=document.createElement("input")
      downunder_checkbox.type="checkbox";
      downunder_checkbox.id="checkboxForDownUnder"
      downunder_checkbox.className="fieldCheckbox";
      row.appendChild(downunder_checkbox)

      //Label
      var elm=document.createElement("label")
      elm.htmlFor="checkboxForDownUnder"
      elm.appendChild(document.createTextNode("Auf den Kopf stellen"));
      row.appendChild(elm)

	  	  
      extrasContainer.insertBefore(row, insertBeforeThis);
	  /*                 Falsch herum (Rückwärts)           */
      var row = document.createElement("div");
      row.className = "form-row forumExtras inline-input";

      //input type=checkbox
      var backwards_checkbox=document.createElement("input")
      backwards_checkbox.type="checkbox";
      backwards_checkbox.id="checkboxForBackwards"
      backwards_checkbox.className="fieldCheckbox";
      row.appendChild(backwards_checkbox)

      //Label
      var elm=document.createElement("label")
      elm.htmlFor="checkboxForBackwards"
      elm.appendChild(document.createTextNode("Umdrehen"));
      row.appendChild(elm)

      extrasContainer.insertBefore(row, insertBeforeThis);
      /*                       Signatur                 */
      if(userSettings) {
        userSettings.register("signatur_text", "")
      }

      var row = document.createElement("div");
      row.className = "form-row forumExtras inline-input";
      //input type=checkbox
      var signatur_checkbox=document.createElement("input")
      signatur_checkbox.type="checkbox";
      signatur_checkbox.id="checkboxForSig"
      signatur_checkbox.className="fieldCheckbox";
      row.appendChild(signatur_checkbox)

      //Label
      var elm=document.createElement("label")
      elm.htmlFor="checkboxForSig"
      elm.appendChild(document.createTextNode("Signatur anhängen "));
      row.appendChild(elm)

      //Link
      var elm=document.createElement("a")
      elm.appendChild(document.createTextNode("[Signatur ändern]"));
	  elm.style.cursor="pointer";
      elm.addEventListener("click", function(){
        var xulns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        var hbox=document.createElementNS(xulns, "vbox")
        var vbox=document.createElementNS(xulns, "hbox")
        var mytextbox=document.createElement("textarea")
        var spacer=document.createElementNS(xulns, "spacer")
        var button=document.createElementNS(xulns, "button")


        hbox.setAttribute("flex","1")
		vbox.setAttribute("flex","1")
		mytextbox.setAttribute("flex","1")
		button.setAttribute("flex","1")
		mytextbox.setAttribute("cols","50")
        hbox.setAttribute("flex","1")
        hbox.setAttribute("stye","width:100%;height:100%;position:absolute;top:0;bottom:0")
        //hbox.setAttribute("flex","1")
        mytextbox.value=userSettings.get("signatur_text")+""
        spacer.setAttribute("flex","1")
        button.setAttribute("label","Speichern")

        hbox.appendChild(mytextbox)
        hbox.appendChild(vbox)
        vbox.appendChild(spacer)
        vbox.appendChild(button)

        button.addEventListener("command", function(){
          userSettings.set("signatur_text", mytextbox.value);
          dialog.close()
        }, true);

        var elm=document.createElement("div")
        elm.appendChild(hbox)
        var dialog=new JautisDialog("Signatur ändern", elm)
      }, true)
      row.appendChild(elm)
      
      extrasContainer.insertBefore(row, insertBeforeThis);
 
  

  
  //chat mode
  userSettings.register("chatMode", false)
  var chatModeActive = false;
  function setChatMode(chatMode) {
    var elm = document.getElementById("Grid-Page-Center-Content");
    if (chatMode) {
      elm.className += " chatMode";
    } else {
      elm.className = (elm.className + "").replace(/\s?chatMode/, "");
    }
    chatModeActive = chatMode;
    if (chatModeCheckbox) {
      chatModeCheckbox.checked = chatMode;
    }
    userSettings.set("chatMode", chatMode);
  }

  var h2s = newMessageForm.getElementsByTagName("h2");
  if (h2s.length > 0) {
    var label = document.createElement("label");
    var chatModeCheckbox = document.createElement("input");
    chatModeCheckbox.setAttribute("type", "checkbox");
    chatModeCheckbox.addEventListener("change", function(evt) {
      setChatMode(evt.target.checked);
    }, true);
    label.appendChild(chatModeCheckbox);
    label.appendChild(document.createTextNode(" Chatmodus"));
    label.title = "Wenn der Chatmode aktiv ist Umschalt+Enter für einen Absatz benutzen";
    h2s[0].appendChild(label);
  }
  //add chat mode key listeners
  function chatKeyListener(evt) {
    if (evt.keyCode == 13 && !evt.isChar && (chatModeActive ^ evt.shiftKey)) {
      //evt.view.parent.setTimeout('document.getElementById("Forum_content").form.submit()', 0);
      newMessageForm.getElementsByClassName("button")[0].click()// submit();
      evt.preventDefault();
    }
  }
  newMessageForm.elements.namedItem("content")
     .addEventListener("keydown", chatKeyListener, true);
   var iframe = newMessageForm.getElementsByTagName("iframe")[0];
   if (iframe) {
     iframe.contentWindow.addEventListener("keydown", chatKeyListener, true)
   }

  if (userSettings.get("chatMode") == true) {
    setChatMode(true);
  }

  //message sending
  function sendMessage(evt) {
    setStatus("sending");

    if (newMessageForm.elements.namedItem("attachPic").checked) {
      return; //TODO
    }
	if (downunder_checkbox.checked) {
      newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML=downUnder(newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML);
	  newMessageForm.elements.namedItem("content").value=downUnder(newMessageForm.elements.namedItem("content").value);
	}	  
	if (lined_checkbox.checked) {
      newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML=lined(newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML);
	  newMessageForm.elements.namedItem("content").value=lined(newMessageForm.elements.namedItem("content").value);
	}	  
	if (backwards_checkbox.checked) {
      newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML=backwards(newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML);
	  newMessageForm.elements.namedItem("content").value=backwards(newMessageForm.elements.namedItem("content").value);
    }
    if (signatur_checkbox.checked) {
	  newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML+="\n--\n" + userSettings.get("signatur_text");
      newMessageForm.elements.namedItem("content").value+="\n--\n" + userSettings.get("signatur_text");
	}  
    if (do_encrypt) {
	  newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML="[enc"+encryptMethod+"]"+newMessageForm.getElementsByTagName("iframe")[0].contentWindow.document.body.innerHTML.encrypt(encryptMethod)+"[/enc]";
      newMessageForm.elements.namedItem("content").value="[enc"+encryptMethod+"]"+newMessageForm.elements.namedItem("content").value.encrypt(encryptMethod)+"[/enc]";
    }
    if (evt) {
      evt.preventDefault();
    }
    
    /*var boundary = "---------------------------";
    for (var i = 0; i < 29; i++) {
      boundary += Math.floor(10*Math.random());
    }*/
    var message = newMessageForm.elements.namedItem("content").value
    var nobbs = [];
    var nobbreplace = " [nobb=" + Math.random() + "] ";
    message = message.replace(/\[nobb\]([\w\W]+?)\[\/nobb\]/g, function(all) {
      nobbs.push(all)
      return nobbreplace; // [nw]s around nobb
    })
    if (userSettings.get("allgemein.NWCode")) {
	message = message.replace(/([^ ]{70,})/g, function(longtext) {
      return "[nw] " + longtext + " [/nw]"});
    nobbs.forEach(function(nobb) {
      message = message.replace(nobbreplace, nobb)
    });
	}
    if (message == "") {
      return;
      setStatus("");
    }

    var data = "groupId=" + newMessageForm.elements.namedItem("groupId").value
             + "&threadId=" + newMessageForm.elements.namedItem("threadId").value
             + "&content=" + encodeURIComponent(message)
             + "&formkey=" + newMessageForm.elements.namedItem("formkey").value
             + "&iv=" + newMessageForm.elements.namedItem("iv").value;

    var request = new XMLHttpRequest();
    request.open("post",
        location.href.replace("ThreadMessages", "AnswerThread"), true);
    /*request.setRequestHeader("Content-Type",
                "multipart/form-data; boundary=" + boundary)*/
    request.setRequestHeader("Content-Type",
        "application/x-www-form-urlencoded; charset=UTF-8");
    request.addEventListener("load", function() {
      reciveMessages(request);
    }, true);
    request.send(data);

    newMessageForm.elements.namedItem("content").value = "";
    //send event
    newMessageForm.reset();
  }
  //give other modules time to update => use parent Node
  newMessageForm.parentNode.addEventListener("submit", sendMessage, false);
}

})()}catch(e){debug(e)};
//END AREA GROUPAJAXFORUM



//BEGIN AREA THEMES
try{(function(){

/**
 * theme management. See theme class for more information on themes
 */
if (!userSettings || !userSettings.register) {
  return;
}

userSettings.register("theme", "");

var themelist = Theme.getThemes();
/**
 * AB HIER KANNST DU DEINE THEMES EINFÜGEN
 * Anleitung unter jautis.net/themes.html */

//TODO or delete

/** Ab hier nichts mehr verändern! */

var currentThemeId = userSettings.get("theme");
var themesWithId = themelist.filter(function(t) {return currentThemeId==t.id });
if (themesWithId.length > 0) {
  themesWithId[0].activate();
}

//BEGIN GM-menü
if (typeof GM_registerMenuCommand != "undefined") {
  for(var i in themelist){
    (function(theme){
    var theme = theme;
    GM_registerMenuCommand("Theme ändern nach " + theme.name
                         + " von "+ theme.author,
      function(){
        userSettings.set("theme", theme.id);
        theme.activate()
      });
    })(themelist[i])
  }

  GM_registerMenuCommand("Theme Zurücksetzen", function(){
    userSettings.set("theme", "");
    if(document.getElementById("themestyle"))
      document.getElementById("themestyle").innerHTML=""
  });
} //end if
//END GM-menü

if (!JautisSettings) {
  return;
}


function ThemeSettings(element) {
  var container = element;
  //var container = document.createElementNS(XULNS, "vbox");
  //container.setAttribute("flex", "1");
  var groupbox  = document.createElementNS(XULNS, "groupbox");
  groupbox.setAttribute("flex", "1");
  container.appendChild(groupbox);
  var caption   = document.createElementNS(XULNS, "caption");
  caption.setAttribute("label", "Theme wählen");
  groupbox.appendChild(caption);

  var list = document.createElementNS(XULNS, "listbox");
  list.setAttribute("flex", "1");
  groupbox.appendChild(list);
  this.themeListElement = list;
  this.renderThemeList();/*

  //container.appendChild(this.getDownloadArea());
  //element.appendChild(container);*/
  var hbox =  document.createElementNS(XULNS, "hbox");
  var button   = document.createElementNS(XULNS, "button");
  button.setAttribute("label", "Neue Themes herunterladen");
  button.addEventListener("command", jautisHint(this, "download"), true);
  hbox.appendChild(button);
  var spacer   = document.createElementNS(XULNS, "spacer");
  spacer.setAttribute("flex", "1");
  hbox.appendChild(spacer);
  var button   = document.createElementNS(XULNS, "button");
  button.setAttribute("label", "Theme Deinstallieren");
  button.addEventListener("command", jautisHint(this, "uninstall"), true);
  hbox.appendChild(button);
  groupbox.appendChild(hbox);
}

/* the item for the selection "no theme" */
ThemeSettings.prototype.themeListItem_none = null;
/* the items for the themes, themeid => Element */
ThemeSettings.prototype.themeListItems = {};
/* the lists element */
ThemeSettings.prototype.themeListElement = null;


ThemeSettings.prototype.renderThemeList = function() {
  var currentThemeId = userSettings.get("theme")
  var i;
  var item;
  while (this.themeListElement.firstChild) {
    this.themeListElement.removeChild(this.themeListElement.firstChild);
  }
  this.themeListItem_none = document.createElementNS(XULNS, "listitem");
  this.themeListItem_none.setAttribute("label", "Keine Theme anwenden");
  //this.themeListItem_none.setAttribute("author", "SchülerVZ");
  this.themeListItem_none.setAttribute("image", "");
  this.themeListItem_none.setAttribute("selected", (currentThemeId == "").toString());
  this.themeListElement.appendChild(this.themeListItem_none);
  var listElement = this.themeListElement;

  Theme.getThemes().forEach(function(theme) {
    item = document.createElementNS(XULNS, "listitem");
    item.setAttribute("label", theme.name);
    //item.setAttribute("author", themes[i].author);
    item.setAttribute("image", "");
    item.setAttribute("themeid", theme.id);
    listElement.appendChild(item);
    item.setAttribute("selected", (currentThemeId == theme.id).toString());
  });
}
ThemeSettings.prototype.getSelectedTheme =function() {
  var themeId = "";
  var children = this.themeListElement.childNodes;
  Array.forEach(children, function(child) {
    if (child.nodeType == 1 && child.getAttribute("selected") == "true") {
      themeId = child.getAttribute("themeid");
    }
  });
  var themesWithId = Theme.getThemes().filter(function(t) {return t.id == themeId});
  if (themesWithId.length < 1) {
    var theme = null;
  } else {
    var theme = themesWithId[0];
  }
  return theme;
}
ThemeSettings.prototype.save = function() {
  var theme = this.getSelectedTheme();
  userSettings.set("theme", theme != null ? theme.id : "");
  if (theme) {
    theme.activate();
  } else if (document.getElementById("themestyle")) {
    document.getElementById("themestyle").innerHTML="";
  }
}

//   DONWLOADING THEMES
ThemeSettings.prototype.downloadList = null;
ThemeSettings.prototype.downloadStatus = {
  statuslabel:null,
  statusbox:null
};

ThemeSettings.prototype.uninstall = function() {
  var theme = this.getSelectedTheme();
  if (theme == null) {
    alert("Keine Theme zum Deinstallieren ausgewählt");
  } else {
    Theme.uninstallTheme(theme);
    this.renderThemeList()
  }
}
/**
 * opens the download window
 */
ThemeSettings.prototype.download = function() {
  if (!this.downloadDialog) {
    this.downloadDialog = new JautisDialog("Neue Themes herunterladen",
      this.getDownloadArea());
    this.downloadThemeList()
    this.downloadDialog.onclose = jautisHint(this, "downloadDialogClosed")
  }
}
ThemeSettings.prototype.downloadThemes = [];
/**
 * returns the content element for the download window
 */
ThemeSettings.prototype.downloadDialogClosed = function() {
  this.downloadDialog = null;
}
ThemeSettings.prototype.getDownloadArea = function() {
  var groupbox = document.createElementNS(XULNS, "vbox");
  groupbox.setAttribute("flex", "1");
  /*var caption  = document.createElementNS(XULNS, "caption");
  caption.setAttribute("label", "Neue Themes herunterladen");
  groupbox.appendChild(caption);*/

  var list  = document.createElementNS(XULNS, "listbox");
  list.setAttribute("flex", "1");
  groupbox.appendChild(list);
  this.downloadList = list;
  
  var button  = document.createElementNS(XULNS, "button");
  button.setAttribute("label", "Theme herunterladen");
  button.addEventListener("command", jautisHint(this, "downloadTheme"), true)
  groupbox.appendChild(button);
  
  this.downloadStatus.statusbox = document.createElementNS(XULNS, "statusbar");
  groupbox.appendChild(this.downloadStatus.statusbox);
  this.downloadStatus.statuslabel = document.createElementNS(XULNS, "statusbarpanel");
  this.downloadStatus.statusbox.appendChild(this.downloadStatus.statuslabel);
  this.downloadStatus.statusbox.setAttribute("collapsed", "true");

  this.renderDownloadList();

  return groupbox;
}

ThemeSettings.prototype.renderDownloadList = function() {
  with(this.downloadList) {
    while (firstChild) {
      removeChild(firstChild);
    }
  }
  var list = this.downloadList;
  var downloadThemes = this.downloadThemes;
  downloadThemes.forEach(function(themeData) {
    var item = document.createElementNS(XULNS, "listitem");
    item.setAttribute("themeid", themeData.theme.id);
    item.setAttribute("label", themeData.theme.name);
    list.appendChild(item);
    themeData.element = item;
  });
}
ThemeSettings.prototype.downloadThemeList = function() {
  if (this.downloadStatus.statusbox.getAttribute("collapsed") == "false") {
    return;
  }
  
  this.downloadStatus.statusbox.setAttribute("collapsed", "false");
  this.downloadStatus.statuslabel.setAttribute("label", "Liste wird heruntergeladen");

  GM_xmlhttpRequest( {
    method: "GET",
    url: JAUTIS_SERVER + "themes.php",
    onload: jautisHint(this, "reciveThemeList"),
    onerror: jautisHint(this, "requestError")
  } ); 
  debug ("request send to " + JAUTIS_SERVER + "themes.php");
}
ThemeSettings.prototype.requestError = function(resp) {
  this.downloadStatus.statusbox.setAttribute("collapsed", "false");
  this.downloadStatus.statuslabel.setAttribute("label", 
      "Fehler beim Anfordern der Daten:" + req.status + " " + req.statusText);
}
/**
 * donwloads a list of themes from the jautis server
 * The list is in XML:
 * <themes>
 *   <theme>
 *     <id/>
 *     <author/>
 *     <name/>
 *     <rating/>
 *     <link/>
 *     <image/>
 *   </theme>
 * </themes>
 */

ThemeSettings.prototype.reciveThemeList = function(responseDetails) {
  debug("Empfangene Themes: " + responseDetails.responseText);
  this.downloadStatus.statusbox.setAttribute("collapsed", "true");
  var xml = new XML(responseDetails.responseText.replace(/<\?[^>]*>/, ""));
  this.downloadThemes = [];
  this.cssLinks = {};
  for (var i = 0; i < xml.theme.length(); i++) {
    var data = xml.theme[i];
    this.downloadThemes.push({theme:new Theme(data.id + "", data.name + "", data.author + "", data.image + ""), element:null, link:data.link + ""});
  }
  this.renderDownloadList();
}

ThemeSettings.prototype.downloadTheme = function() {
  if (this.downloadStatus.statusbox.getAttribute("collapsed") != "true") {
    return;
  }

  var themeData = null;
  for (var i = 0; i < this.downloadThemes.length; i++) {
    if (this.downloadThemes[i].element.getAttribute("selected") == "true") {
      themeData = this.downloadThemes[i];
    }
  }

  if (themeData == null) {
    alert ("Keine Theme ausgewählt");
  } else {
    try{
    debug("requesting theme: " + themeData.link);
    var me = this;
    GM_xmlhttpRequest( {
      method:"GET",
      url: themeData.link,
      onload: function(response) {
        Theme.installTheme(themeData.theme, response.responseText);
        me.downloadStatus.statusbox.setAttribute("collapsed", "true");
        me.renderThemeList();
      },
      onerror : function(response) {
        alert("Fehler beim Herunterladen (" + response.status + ")")
        me.downloadStatus.statusbox.setAttribute("collapsed", "true");
      }
    } );
    }catch(e) {debug(e)}

    this.downloadStatus.statuslabel.setAttribute("label",
        "Theme " + themeData.theme.name + " wird heruntergeladen");
    this.downloadStatus.statusbox.setAttribute("collapsed", "false");
  }
}


JautisSettings.addPanel(new JautisSettingsPanel("appearance", "Aussehen",
  function(element) {
    themeSettings = new ThemeSettings(element);
    return themeSettings;
  }, function(themeSettings) {
    themeSettings.save();
  }
));

})()}catch(e){debug(e)};
//END AREA THEMES

//BEGIN AREA BACKGROUNDMUSIKSETTINGS
JautisSettings.addPanel(new JautisSettingsPanel("backgroundmusic-settings", "Hintergrundmusik", function(elm){
  var groupbox = document.createElementNS(XULNS, "groupbox");
  groupbox.setAttribute("flex", "1")
  groupbox.setAttribute("orient", "vertical")
  
  var textdiv = document.createElement("div");
  textdiv.appendChild(document.createTextNode("Hier können sie entscheiden, ob Sie möchten,"));
  textdiv.appendChild(document.createElement("br"));
  textdiv.appendChild(document.createTextNode("dass der Hintergrundmusik-Code auf Profil Seiten umgewandelt wird."));
  textdiv.appendChild(document.createElement("br"));
  textdiv.appendChild(document.createTextNode("Wenn ja, wird auf manchen Profilen von selbst Musik ertönen."));
  groupbox.appendChild(textdiv)  
  
 var button   = document.createElementNS(XULNS, "button")
  button.setAttribute("label", "Hintergrundmusik aktivieren");
  button.style.marginTop="1em";
  button.addEventListener("command", function(){
    userSettings.set("backgroundmusic.activeted", true);
	userSettings.set("backgroundmusic.deactiveted", false);
  }, true);
  groupbox.appendChild(button)
  
  var button2   = document.createElementNS(XULNS, "button")
  button2.setAttribute("label", "Hintergrundmusik deaktivieren");
  button2.style.marginTop="1em";
  button2.addEventListener("command", function(){
    userSettings.set("backgroundmusic.deactiveted", true);
	userSettings.set("backgroundmusic.activeted", false);
  }, true);
  groupbox.appendChild(button2)

  elm.appendChild(groupbox)
  
  return elm;
}) );
//END AREA BACKGROUNDMUSIKSETTINGS

//BEGIN AREA QUICKSEARCH
try{(function(){

  /**
   * SEARCH groups
   * improves the search-filed
   * @author Michael Z.
   * @date 2009-02-16
   */
    if(document.getElementById("Quicksearch")) {
      function submitForm(evt){
        evt.preventDefault();
			if(input.className != "preset" && input.value != "") {
				for(var i=0;i<input.value.length;i++){
					input.value = input.value.replace(/(\s)/, "+")
				}
				location.href = VZ_SERVER + "Search/ResultGroups/name/"
				+ encodeURIComponent(input.value);
			}
        else {
          location.href = VZ_SERVER + "Groups";
        }
      }
      function focusInput() {
        if(input.className == "preset") {
          input.className = "";
          input.value = "";
        }
      }
      function blurInput() {
        if(input.value == "") {
          input.className = "preset";
          input.value = "Gruppen";
        }
      }

      var form = document.createElement("form");
	  form.id = "GroupSearch";
      form.addEventListener("submit", submitForm, true);

      var fieldset = document.createElement("fieldset");
      form.appendChild(fieldset);

      var input = document.createElement("input");
      input.value = "Gruppen";
      input.className = "preset";
      input.addEventListener("focus", focusInput, true);
      input.addEventListener("blur", blurInput, true);
      fieldset.appendChild(input);

      document.getElementById("Quicksearch").appendChild(form);
    }
    CSS("#Grid-Page-Left #Quicksearch {border-width:0px;height:auto;}");
    CSS("#Grid-Page-Left #Quicksearch * {border-color:inherit;"
        + "border-style:inherit;border-width:0;}");
    CSS("#Grid-Page-Left #Quicksearch fieldset {border-width:1px;margin-top:5px}");
})()}catch(e){debug(e)};
//END AREA QUICKSEARCH




//BEGIN AREA WRITEMESSAGE (DISABLED)
try{(function(){
    window.writeMessageTo = function writeMessageTo(ids, name){
      var subject= writeMessageTo.arguments[2] || ""
      var text   = writeMessageTo.arguments[3] || ""

      var elm=document.createElement("div")

      var tmp=document.createElement("div")
      tmp.appendChild( document.createTextNode("An:") );
      tmp.className="label";
      elm.appendChild(tmp);

      var tmp=document.createElement("div")
      tmp.appendChild( document.createTextNode(name) );
      tmp.className="labeledText";
      elm.appendChild(tmp);

      elm.appendChild(document.createElement("br"));

      var tmp=document.createElement("div")
      tmp.appendChild( document.createTextNode("Betreff:") );
      tmp.className="label";
      elm.appendChild(tmp);

      var subjectinput=document.createElement("input")
      subjectinput.className="fieldText";
      subjectinput.value=subject;
      elm.appendChild(subjectinput);

      elm.appendChild(document.createElement("br"));

      var tmp=document.createElement("div")
      tmp.appendChild( document.createTextNode("Nachricht:") );
      tmp.className="label";
      elm.appendChild(tmp);

      var texttextarea=document.createElement("textarea")
      texttextarea.appendChild( document.createTextNode(text) );
      elm.appendChild(texttextarea);


      var bbpreview   =document.createElement("div")
      var attachmentarea=document.createElement("div")


      var dialog=new JautisDialog("Nachricht schreiben", elm)
    }

})/*()*/}catch(e){debug(e)};
//END AREA WRITEMESSAGE


//BEGIN AREA BLOGNEWS
try{(function(){
    if(!userSettings || !document.getElementById("Grid-Page-Left")
        || typeof GM_xmlhttpRequest == "undefined")
      return;
    userSettings.register("newsresources", []);
    userSettings.register("newsresources_initiated", false);
    userSettings.register("newsresource", -1);
    userSettings.register("newscache.updateIntervall", 60*60); //in s
    userSettings.register("newscache.data", "");
    userSettings.register("newscache.time", new Date());
    userSettings.register("newscache.id", -1); //-1: old; -2: none
    var newsresources = userSettings.get("newsresources");
    var newsContainer = null;
    var kastenData = "";

    function initiateNewsResurces() {
      newsresources = [];
      userSettings.set("newsresources", newsresources);
      userSettings.set("newsresource", -1);
      ["http://www.mehrblog.net/feed/",
       "http://blog.studivz.net/feed/",
       "http://developer.studivz.net/feed/"].forEach(function(url) {
        initiateNewsResurce(url);
      });
    }

    function initiateNewsResurce(url) {
      var onsuccess = arguments[1] || function(){};
      var onerror = arguments[2] || function(){};
      GM_xmlhttpRequest({
        method: "GET",
        onload : function(response) {
            loadNewsResurceFromResponse(response, onsuccess, onerror)
          },
        onerror: onerror,
        url: url
      });
    }

    function loadNewsResurceFromResponse(response, onsuccess, onerror) {
      var matches = /<title>([^<]*)/.exec(response.responseText);
      if (!matches) {
        onerror();
      } else {
        newsresources.push({title: matches[1], url: response.finalUrl})
        userSettings.set("newsresources", newsresources);
        onsuccess();
      }
    }

    if (!userSettings.get("newsresources_initiated")) {
      initiateNewsResurces();
      userSettings.set("newsresources_initiated", true)
    }
    
    function addNewsResourcesToTarget (evt) {
      var select = evt.target;
      while (select.firstChild) {
        select.removeChild(select.firstChild);
      }
      //var option = document.createElement("option");
      //option.setAttribute("value", "-2");
      //option.appendChild(document.createTextNode("Nichts anzeigen"));
      //newsSelectionPopup.appendChild(option);
      
      var current = userSettings.get("newsresource");
      
      var option = document.createElement("option");
      option.setAttribute("value", "-1");
      option.appendChild(document.createTextNode(VZ_NETWORK + "-Kasten"));
      if (current == -1) {
        option.setAttribute("selected", "selected");
      }
      select.appendChild(option);

      for (var i = 0; i < newsresources.length; i++) {
        var option = document.createElement("option");
        option.setAttribute("value", "" + i);
        option.appendChild(document.createTextNode(newsresources[i].title));
        if (current == i) {
          option.setAttribute("selected", "selected");
        }
        select.appendChild(option);
      }
    }
    
    function setNewsResourcesToTarget(evt) {
      userSettings.set("newsresource", evt.target.value);
      loadCurrenntResurce()
    }

    //Use "Kasten"
    function initNewsContainer() {
      if (newsContainer != null) {
        return;
      }
      var leftsideBox = document.getElementById("LeftsideBox");
      
      if (!leftsideBox) {
        newsContainer = document.createElement("div");
        //TODO: add to Document...
        kastenData = "";
      } else {
        if (leftsideBox.firstElementChild) {
          newsContainer = leftsideBox.firstElementChild;
        } else {
          newsContainer = leftsideBox;
        }
        kastenData = newsContainer.innerHTML;
      }
      
      //add menu
      var leftsideBoxMenu = document.createElement("div");
      leftsideBoxMenu.className = "leftsideBoxMenu";
      var select = document.createElement("select");
      leftsideBoxMenu.appendChild(select);
      select.addEventListener("popupshowing", addNewsResourcesToTarget, true);
      select.addEventListener("focus", addNewsResourcesToTarget, true);
      select.addEventListener("change", setNewsResourcesToTarget, true);
      addNewsResourcesToTarget({target:select})
      leftsideBox.insertBefore(leftsideBoxMenu, leftsideBox.firstChild);
      
      CSS(".leftsideBoxMenu > select {width:100%; -moz-box-sizing:border-box}")
      
      loadCurrenntResurce()
    }
    function loadCurrenntResurce() {
      displayCurrenntResurce()
      if (userSettings.get("newscache.time") 
            < Date.now() - userSettings.get("newscache.updateIntervall") * 1000
          || userSettings.get("newscache.id")
            != userSettings.get("newsresource")) {
        reloadNewsCache(displayCurrenntResurce);
      }
    }
    function displayCurrenntResurce() {
      if (userSettings.get("newsresource") > -1) {
        var html = userSettings.get("newscache.data");
        newsContainer.innerHTML = html;
      } else if (userSettings.get("newsresource") == -1) {
        newsContainer.innerHTML = kastenData;
      }
      document.getElementById("LeftsideBox").style.display
        = userSettings.get("newsresource") == -2 ? "none" : "";
    }
    function reloadNewsCache() {
      var id = userSettings.get("newsresource");
      var onsuccess = arguments[0] || function(){};
      var onerror = arguments[1] || function(){};
      if (id < 0) {
        userSettings.set("newscache.id", id);
        onsuccess();
        return;
      }
      url = newsresources[id].url;
      debug("Reloading: " + url)
      GM_xmlhttpRequest({
        method: "GET",
        onload : function(response) {
            reciveNews(response, onsuccess, onerror)
          },
        onerror: onerror,
        url: url
      });
    }

    function reciveNews(response, onsuccess, onerror) {
      var regexp = /<item>[\w\W]*?<title>([^<]*)[\w\W]*?<link>([^<]*)[\w\W]*?<description><!\[CDATA\[([\w\W]*?)\]\]>/
      var matches = regexp.exec(response.responseText);
      debug("Blog Empfangen: " +matches);
      if (!matches) {
        onerror();
      } else {           
        var title = matches[1], url = matches[2], text = matches[3];

        userSettings.set("newscache.data", 
            "<b> <a href=\"" + url + "\"> " + title + " </a> </b>" 
            + "<br/> <br/>" + text);
        userSettings.set("newscache.time", Date.now())
        userSettings.set("newscache.id", userSettings.get("newsresource")); //TODO: save in global variable, and prevent from loading two requests simultaiously
        onsuccess()
      }
    }
    initNewsContainer();

    //settings
    var newsSelection = null, newsSelectionPopup = null;
    JautisSettings.addPanel(new JautisSettingsPanel("menu", "Menü",
      getNewsSettings, saveNewsSettings));
    function getNewsSettings(element) {
      var vbox = document.createElementNS(XULNS, "groupbox");
      var label = document.createElementNS(XULNS, "caption");
      label.setAttribute("label", "Kasten / Blog ");
      vbox.appendChild(label);

      newsSelection = document.createElementNS(XULNS, "menulist");
      newsSelectionPopup = document.createElementNS(XULNS, "menupopup");
      renderNewsSelectionPopup();
      newsSelection.appendChild(newsSelectionPopup);
      vbox.appendChild(newsSelection);
      element.appendChild(vbox);
    }
    function renderNewsSelectionPopup() {
      var selected = userSettings.get("newsresource");
      while (newsSelectionPopup.firstChild) {
        newsSelectionPopup.removeChild(firstChild)
      }
      var menuitem = document.createElementNS(XULNS, "menuitem");
      menuitem.setAttribute("value", "-2");
      menuitem.setAttribute("label", "Kein Blog anzeigen");
      if (-2 == selected) {
        menuitem.setAttribute("selected", "true");
      }
      newsSelectionPopup.appendChild(menuitem);
      
      var menuitem = document.createElementNS(XULNS, "menuitem");
      menuitem.setAttribute("value", "-1");
      menuitem.setAttribute("label", "VZ-Kasten anzeigen");
      if (-1 == selected) {
        menuitem.setAttribute("selected", "true");
      }
      newsSelectionPopup.appendChild(menuitem);

      for (var i = 0; i < newsresources.length; i++) {
        var menuitem = document.createElementNS(XULNS, "menuitem");
        menuitem.setAttribute("value", i + "");
        menuitem.setAttribute("label", newsresources[i].title);
        if (i == selected) {
          menuitem.setAttribute("selected", "true");
        }
        newsSelectionPopup.appendChild(menuitem);
      }
    }

    function saveNewsSettings() {
      debug ("Newsquelle" + newsSelection.getAttribute("value"))
      userSettings.set("newsresource", newsSelection.getAttribute("value"));
      loadCurrenntResurce()
    }
})()}catch(e){debug(e)};
//END AREA BLOGNEWS




//BEGIN AREA BBFORMS
try{(function(){
    CSS(".labeledText.hasWysiwyg {position:relative;float:left; width:431px;}");

    CSS("#GroupAdmin label {width:17%; padding: 0;}");
    CSS("#GroupAdmin input[type=text], #GroupAdmin select, "
      + "#GroupAdmin textarea, #GroupAdmin .labeledText.hasWysiwyg {width:80%;-moz-box-sizing:border-box;}");
    CSS("#GroupAdmin textarea, #GroupAdmin iframe {height:15em;}")
    CSS("#GroupAdmin {-moz-box-sizing:border-box; padding: 0 10px; margin: 0;width: 100%;}")
    CSS("#GroupAdmin form,#GroupAdmin fieldset {overflow:visible}")

    function showBBHelp(){
      var dialog = new JautisDialog("BB-Code-Hilfe");
      dialog.sizeTo(window.innerWidth / 2 - 50, window.innerHeight - 100);
      dialog.setLeft(20);
      dialog.setTop(50);
      var html = "<h2>Allgemeines</h2>"
        + "<p>BB-Code kannst du ganz einfach im normalen Text schreiben. "
        + "Er wird dann später in HTML umgewandelt</p>"
        + "<p>Du solltest BB-Code-Tags immer in der umgekehrten Reihenfolge "
        + "schließen wie du sie öffnest: <tt>[b][u]wichtig[/u][/b]</tt> und "
        + "nicht <tt><s>[b][u]wichtig[/b][/u]</s></tt>"
        + "<h2>Texthervorhebungen</h2>"
        + "<table>"
        + "<tr><td><tt>[i]Schräg[/i]</tt></td>          "
        + "<td><i>Schräg</i></td></tr>"
        + "<tr><td><tt>[u]Unterstrichen[/u]</tt></td>   "
        + "<td><u>Unterstrichen</u></td></tr>"
        + "<tr><td><tt>[b]Fett[/b]</tt></td>            "
        + "<td><b>Fett</b></td></tr>"
        + "<tr><td><tt>[s]Durchgestrichen[/s]</tt></td> "
        + "<td><s>Durchgestrichen</s></td></tr>"
        + "<tr><td><tt>[size=+3]Groß[/size]</tt></td>   "
        + "<td><font style=\"font-size:121%\">Groß</font></td></tr>"
        + "<tr><td><tt>[art=Arial]Arial[/art]</tt></td>   "
        + "<td><span style=\"font-family:Arial\">Arial</span></td></tr>"
        + "</table>"

        + "<h2>Elemente zur Textstrukturierung</h2>"
        + "<p>Dies sind Elemente um den Text besser zu strukturieren.</p>"
        + "<table>"
        + "<tr><td><tt>[br]</tt></td>   <td>Fügt einen Abatz ein.</td></tr>"
        + "<tr><td><tt>[hr]</tt></td>   <td>Fügt eine Trennlinie ein.</td></tr>"
        + "<tr><td><tt>[h'2-5']überschrift[/h'2-5']</tt></td>"
        + "<td>Fügt eine Überschrift ein. Für '2-5' setzt man eine Zahl "
        + "zwischen 2 und 5 ein. [h2]1.Rangordnung[/h2] steht für eine "
        + "Überschrift 1. Rangordnung.</td></tr>"
        + "</table>"

        + "<h2>Zitate</h2>"
        + "<p><tt>[quote]Ein Zitat[/quote]</tt>: Ein einfaches Zitat</p>"
        + "<p><tt>[quote=Markus]Ein Zitat von Markus[/quote]</tt>: "
        + "Ein Zitat mit Autor</p>"

        + "<h2>Farben</h2>"
        + "<p>Du kannst Farben mit dem Namen (englisch) oder mit derm "
        + "Hexadezimalen Wert angeben:"
        + "<table>"
        + "<tr><td><tt>[color=red]Roter Text[/color]</tt></td> "
        + "<td><font color=\"red\">Roter Text</font></td></tr>"
        + "<tr><td><tt>[bgcolor=#ff0000]Rot hinterlegter Text[/bgcolor]</tt></td> "
        + "<td><font style=\"background:red\">Rot hinterlegter Text</font></td></tr>"
        + "<tr><td><tt>[colorbox=red]Rot hinterlegter Text[/colorbox]</tt></td>"
        + "<td><div style=\"background:red\">Rot hinterlegter Text</div></td></tr>"
        + "<tr><td><tt>[border=green]Grüner Rahmen[/border]</tt></td> "
        + "<td><div style=\"border:1px solid green\">Grüner Rahmen</div></td></tr>"
        + "</table>"

        + "<h2>Links</h2>"
        + "Einfache Links kannst du ganz normal in den Text schreiben. Andere "
        + "Links wie in Wikipedia: <tt>[Ziel Text]</tt>."
        + "[http://www.google.de Google] wird zu "
        + "<a href=\"http://www.google.de\">Google</a>. Für Links innerhalb von"
        + " SchülerVZ kannst du die Domain (http://schuelervz.net) weglassen."
        + "<h2>Sonstiges</h2>"
        + "<p>Bilder: <tt>[img]http://server.de/bild.jpg[/img]</tt></p>"
        + "<p>Anker: <tt>[anker=name]</tt><br>Zu einem Anker kannst du irgend "
        + "wo anderst auf der Seite einen Link mit "
        + "<tt>[#name Link zum Anker]</tt> machen. Anker müssen nicht "
        + "geschlossen werden.</p>"
        + "<p>Listen: <pre>[list]\n[*] 1. Eintrag \n[*] 2. Eintrag \n[/list]</pre></p>"

        + "<h2>Effekte</h2>"
        + "<tr><td><tt>[blink]blinkend[/blink]</tt></td> "
        + "<td>Der Text blinkt</td></tr>"
        + "<tr><td><tt>[scroll]Lauftext[/scroll]</tt></td> "
        + "<td>Der Text läuft von rechts nach links. Außerdem kann man noch "
        + "<code>=up</code> oder <code>=down</code> nach <code>scroll</code> "
        + "setzen. Dann läuft der Text hoch oder runter.</td></tr>"
        + "<tr><td><tt>[code]CodeText[/code]</tt></td> <td>Bewirkt dass der "
        + "Text <code>so</code> aussieht. Benutzung um Codes zu markieren.</td>"
        + "</tr>"
        + "<tr><td><tt>[backwards]falsch_herum[/backwards]</tt></td> "
        + "<td>Der Text wird falsch herum Angezeigt</td></tr>"

        + "<h2>Sondertags</h2>"
        + "<p>Diese Tags werden vor allen anderen ausgewertet, und du brauchst"
        + " die Schließreihenfolge nicht beachten.</p>"
        + "<table>"
        + "<tr><td><tt>[hidden]Versteckt[/hidden]</tt></td> "
        + "<td>Der Text wird nicht Angezeigt</td></tr>"
        + "<tr><td><tt>[nw]zusammen[/nw]</tt></td> "
        + "<td>Aus dem Text werden alle Leerzeichen gelöscht</td></tr>"
        + "<tr><td><tt>[doenc]verschlüsseln[/doenc]</tt></td> "
        + "<td>Text dazwischen wird beim Speichern verschlüsselt</td></tr>"
        + "<tr><td><tt>[enc1]verschlüsselt[/enc]</tt></td> "
        + "<td>Verschlüsselter Text. Jautis fügt diesen Tag automatisch ein, "
        + "ein Setzen ist nicht empfehlenswert</td></tr>"
        + "</table>"
        + "<h2>Mehr Infos</h2>"
        + "<p><a href=\"http://www.jautis.net/bbcode.html\" target=\"_blank\">"
        + "jautis-Homepage über BB-Code</a> (in neuem Fenster)</p>"
        + "<p><a href=\"http://wiki.svzcom.de/BB-Code\" target=\"_blank\">"
        + "SchülerVZ-Wiki über BB-Code</a> (in neuem Fenster></p>"
        + "<p><a href=\"http://www.schuelervz.net/Groups/Overview/5f92c9e"
        + "fe364bd3d\" target=\"_blank\">jautis-Gruppe (Support)</a> "
        + "(in neuem Fenster></p>"
      dialog.content.innerHTML=html;
    }

    function getHelpButton() {
      var a=document.createElement("a");
      a.href="javascript:;"
      a.addEventListener("click", showBBHelp, true);
      a.appendChild(document.createTextNode("BB-Code Hilfe"))
      return a;
    }

    /**
     * make content form bbcodeable.
     * @author Michael Z.
     * @date 2009-09-28
     */

    var contentform = null;
    ["ProfileEditGeneral", "ProfileEditSchool", "ProfileEditContact",
     "ProfileEditpersonal", "Messages_WriteForm",
     "/*pinnboard*/","GroupAdmin", "/*eintrag bearbeiten*/", "Mod-Groups-NewThreads-Pagelet"]
     .forEach(function(id){
      if (document.getElementById(id)) {
        contentform = document.getElementById(id)
      }
    });
    
    if (contentform == null) {
      return;
    }
    

    /**
     * replaces the input by a textbox
     * @param the input to replace
     * @return the textbox
     */
    function textInputToTextarea(input) {
      var textarea = document.createElement("textrea");
      input.parentNode.replaceChild(textarea, input);
      textarea.className = input.className
          ? input.className + " wasInput" : "wasInput";
      textarea.value = input.value;
      textarea.name = input.name;
      return textarea;
    }

    /* load the rows of the form */
    var rows = contentform.getElementsByClassName("form-row");
    Array.forEach(rows, function(row) {
      var textboxes = row.getElementsByTagName("textarea");
      if (textboxes.length > 0) {
        var textbox = textboxes[0];
      } else {
        var inputs = row.getElementsByTagName("input");
        var textbox = null;
        /*alert("input: " + inputs.length)
        for (var i = 0; i < inputs.length && textbox == null; i++) {
          if (inputs[i].type == "text") {
            textbox = textInputToTextarea(inputs[i]);
          }
        }*/
      }

      if (textbox != null) {
        var outerDiv = document.createElement("div");
        outerDiv.className = "labeledText hasWysiwyg";
        textbox.parentNode.replaceChild(outerDiv, textbox);
        outerDiv.appendChild(textbox);
        new BBCodeableTextarea(textbox);
      }
    });
    return;

    //TODO: add Help button to BBCodeable Textareas
})()}catch(e){debug(e)};
//END AREA BBHELP




//BEGIN AREA NEVERASKAGAIN
try{(function(){
    if(userSettings) {
      userSettings.register("neveraskagain_externallink",0)
      // nicht in jautis_check_link (Sicherheitsfehler...)
      var neveraskagain = userSettings.get("neveraskagain_externallink")
    }

    unsafeWindow.jautis_check_link=function jautis_check_link(url){
      var is_external_link=false;


      if (url.search(/.*schuelervz\.net(\/groups\/leave|\/groups\/join|\/logout|\/Account\/Delete|\/Groups\/Delete)/i)>-1) {
        var pishingmessage = "Achtung!\nDer Link könnte ein Betrugsversuch sein. Er Verweist auf eine Seite die dir bestimmte Aktionen zu Erzwingen versucht, z.B. einer Gruppe beizutreten, oder dich auszuloggen.\n\nMöchtest du den Link wirklich Aufrufen?\n\nLinkziel:\n"+url;
      }

      if (url.search(/^https?:\/\//i)>-1 && url.indexOf(VZ_SERVER)<0){
        if(userSettings && neveraskagain == 1){
          return true;
        }

        var pishingmessage="Dieser Link verweist auf eine externe Seite. Du verlässt hiermit SchülerVZ! Der Betreiber dieser Seite kann die Seite, von der du kommst, sehen.\n\nLinkziel:\n"+url;
        is_external_link = true;
        function handleExternalLink(){
          if(neveraskagaincheckbox){
            if(neveraskagaincheckbox.checked && userSettings)
              userSettings.set("neveraskagain_externallink",1)
          }
        }
      }
      if (pishingmessage){
        if (!JautisDialog)
          return confirm(pishingmessage);
        var dialog=new JautisDialog("Pishing-Warnung")
        var elm=document.createElement("div")
        elm.appendChild(document.createTextNode(pishingmessage))
        elm.style.whiteSpace="-moz-pre-wrap";
        elm.style.whiteSpace="pre-wrap";
        dialog.content.appendChild(elm)

        if(is_external_link){
          var elm=document.createElement("div")
          var neveraskagaincheckbox=document.createElement("input")
          neveraskagaincheckbox.type="checkbox";
          neveraskagaincheckbox.id="cb"+Math.random();
          elm.appendChild(neveraskagaincheckbox);
          var label=document.createElement("label")
          label.appendChild(document.createTextNode("Nicht nochmal Fragen (für alle Domains!)"))
          label.htmlFor=neveraskagaincheckbox.id
          elm.appendChild(label)
          elm.style.margin=".4em"
          dialog.content.appendChild(elm)
        }

        var box=document.createElementNS(XULNS,"hbox");
        box.style.width="100%"
        var button=document.createElementNS(XULNS,"button");
        button.setAttribute("label","Doch nicht")
        button.addEventListener("command",function(){dialog.close()}, true)
        box.appendChild(button);

        var spacer=document.createElementNS(XULNS,"spacer");
        spacer.flex="1"
        box.appendChild(spacer);

        if(is_external_link){}

        var button=document.createElementNS(XULNS,"button");
        button.setAttribute("label","Ich gehe das Risiko ein!");
        var url=url
        button.addEventListener("command",function(){
          try{if(handleExternalLink) {
            handleExternalLink()
          }}catch(e){debug(e)}
          location.href=url
        }, true)
        box.appendChild(button);
        dialog.content.appendChild(box)

        return false;
      }
      return true;
    }
})()}catch(e){debug(e)};
//END AREA NEVERASKAGAIN

//BEGIN AREA LAYOUT
try{(function(){
  /**        LAYOUT
   * improve the layout of SchülerVZ and make it more flexible
   */

  if(!userSettings)
    return;

  userSettings.register("layout.wide", false);
  userSettings.register("layout.menuFixed", false);
  userSettings.register("layout.showLeftSideBox", true);
  userSettings.register("layout.showBlogSelect", true);
  userSettings.register("layout.showKDS", true);
  userSettings.register("layout.showFestivals", true);
  userSettings.register("layout.showGroupSearch", true);
  userSettings.register("layout.showPersonalPages", false);
  userSettings.register("layout.showBuschfunk", true);
  userSettings.register("layout.showNews", true);
  userSettings.register("layout.NoUmbrueche", true);

  /**
   * gets the styles for the whole layout stuff
   * @author Michael Z.
   * @date 2009-03-14
   * @return the css-style for the layout with the current settings.
   */
  function getLayoutStyle() {
    var css="/* Style for the Layout. Automaticaly created by jautis on " + new Date()+"*/\n";

    if (userSettings.get("layout.wide")) {
      css += "#Grid-Wrapper, #Grid-Page {width:auto}";
      css += "body {padding:.7em}";

      //Left Menu
      css += "#Grid-Page-Left {width:13em;position:absolute;left:1em;top:0;float:none}";
      css += "#Grid-Page-Left #Quicksearch, #Grid-Page-Left #LeftsideBox {width:auto;}";
      css += "";

      //Center
      css += "#Grid-Page-Center {width:auto;position:absolute;left:15em;top:0;right:0;}";
      css += "#Grid-Page-Center > * {width:100%;}";
      css += "html #Mod-Groups-Snipplet {width:auto}";
      css += "html #Grid-Page-Center-Header {width:auto;}";

      // Start:
      css += "#startRight {display:none;}";
      css += "#startLeft {width:auto;float:none;margin:0; padding:0 .6em;  -moz-column-gap: 1em;-moz-column-width: 22em;}";
      css += "#startLeft > div.teaserbox {display:inline-block;display:-moz-inline-block;position:relative;width:auto;overflow:visible}";
      css += "#startLeft > div .image {display:none}";
      //css += "#startLeft > div:hover .image {display:block;position:absolute;left:-11em;max-width:11em;width:11em;height:auto;z-index:60}";
      css += "#startLeft > div.teaserbox div.text {width:auto;float:none;overflow:hidden;padding 0 1em;}";
      css += "#startLeft h2 {width:auto;}";

      //Profile
      css += "div.obj-box.twothird#profileRight, div.obj-box.onethird#profileLeft {float:none;width:auto}";
      css += "#profileLeft {-moz-column-gap: 1em;-moz-column-count: 3;}";;
      css += "#profileLeft > * {display:block;display:-moz-inline-block;}";
      css += ".uniListSingle {float:none; max-height:15em;overflow:auto;}";
      css += "#profileLeft .obj-thumbnaillist li + li + li + li {display:none}";//3 Friends
      css += "#Snipplet-Photos-Slider {display:none}";
      css += "#profileImage  + .obj-linklist li {display:none;}";
      css += "#profileImage:hover  + .obj-linklist li, .obj-linklist:hover li {display:block !important;}";
      css += "#profileImage  + .obj-linklist {position:realtive;margin:-2px 0 0;width:auto;left:1em;height:0;z-index:3}";
      css += "div.obj-box.twothird dl.obj-keyValueList dd {width:auto;}";
      css += "#Mod-Groups-Snipplet > ul {-moz-column-gap: 1em;-moz-column-width: 30em;}";
      css += "";
      //Groups
      css += "#Groups_Overview .twothird {width:64%;margin:none;}";
      css += "#Groups_Overview .onethird {width:32%;}";
      css += "#Groups_Overview {padding:.5em}";
      css += ".obj-comment-list li .comment-metainfo span.datetime {display:inline-block}";
      css += ".comment-footer {visibility:hidden}";
      css += "li:hover .comment-footer {visibility:visible}";
      css += "div.obj-box.underlay, div.obj-box.underlay div.innercontent {width:auto;float:none}";
      css += "";
      css += "";

      //Sonstiges
      css += "#Mod-Account {width:auto;}";
      css += "";
      css += "";
      css += "";
      css += "";
    }
    if (userSettings.get("layout.menuFixed")) {
      css += "#Grid-Page-Left{position:fixed;float:none}";
    }
    if (!userSettings.get("layout.showLeftSideBox")) {
      css += "#LeftsideBox {display:none}";
    }
    if (!userSettings.get("layout.showBlogSelect")) {
      css += ".leftsideBoxMenu {display:none}";
    }
    if (!userSettings.get("layout.showKDS")) {
      css += "#Kds {display:none}";
    }
    if (!userSettings.get("layout.showFestivals")) {
      css += "a[href$=/l/meinefestivals] {display:none}";
    }
	if (!userSettings.get("layout.showGroupSearch")) {
      css += "#GroupSearch {display:none}";
    }
	if (!userSettings.get("layout.showBuschfunk")) {
      css += "#Mod-Feedbox-Snipplet {display:none}";
    }
	if (!userSettings.get("layout.showNews")) {
      css += "#news_staticContent {display:none}";
    }

    return cleanCSS(css);
  }

  /**
   * reloads the current layout style and displays it on the page
   * @author Michael Z.
   * @date 2009-03-14
   */

  var reloadLayoutStyle_element = null
  function reloadLayoutStyle() {
    if(reloadLayoutStyle_element ===  null) {
      var style = document.createElement("style");
      document.getElementsByTagName("head")[0].appendChild(style);
      reloadLayoutStyle_element = document.createTextNode("");
      style.appendChild(reloadLayoutStyle_element);
    }
    reloadLayoutStyle_element.data = getLayoutStyle();
  }

   /**
    * Allgemeine Einstellungen zum Layout
    * @author Luhe
    * @author Michael
    * @date 2009-03-14
    * TODO: Code-redundanz vermeiden:
    *   eine Funktion die jeweils die Elemente erstellt.
    */
  JautisSettings.addPanel(new JautisSettingsPanel("appearance", "Aussehen", function(elm){
    var vbox    = document.createElementNS(XULNS, "vbox")
    vbox.setAttribute("flex","1")
    elm.appendChild(vbox)
	var checkboxes = {};
	var groupbox = document.createElementNS(XULNS, "groupbox");
    groupbox.setAttribute("orient", "vertical");
    vbox.appendChild(groupbox)
  

    checkboxes.wide = JautisSettings.checkbox(
      "breites Layout", userSettings.get("layout.wide"));
    groupbox.appendChild(checkboxes.wide);

    checkboxes.menuFixed = JautisSettings.checkbox(
      "komplettes Menü Fixieren, so dass es nicht mitscrollt", userSettings.get("layout.menuFixed"));
    groupbox.appendChild(checkboxes.menuFixed);

    checkboxes.showLeftSideBox = JautisSettings.checkbox(
      "Kasten anzeigen", userSettings.get("layout.showLeftSideBox"));
    groupbox.appendChild(checkboxes.showLeftSideBox);

    checkboxes.showBlogSelect = JautisSettings.checkbox(
      "Möglichkeit zum ändern der Blognews auf der linken Seite anzeigen",
        userSettings.get("layout.showBlogSelect"));
    groupbox.appendChild(checkboxes.showBlogSelect);

    checkboxes.showKDS = JautisSettings.checkbox(
      "Kennst du Schon (Startseite) anzeigen", userSettings.get("layout.showKDS"));
    groupbox.appendChild(checkboxes.showKDS);

    checkboxes.showFestivals = JautisSettings.checkbox(
      "Festivals anzeigen", userSettings.get("layout.showFestivals"));
    groupbox.appendChild(checkboxes.showFestivals);
	  
    checkboxes.showGroupSearch = JautisSettings.checkbox(
       "Gruppensuche anzeigen", userSettings.get("layout.showGroupSearch"));
    groupbox.appendChild(checkboxes.showGroupSearch);
	
    //checkboxes.showPersonalPages = JautisSettings.checkbox(
    //   "Persönliche Seiten anzeigen", userSettings.get("layout.showPersonalPages"));
    //groupbox.appendChild(checkboxes.showPersonalPages);
	
    checkboxes.showBuschfunk = JautisSettings.checkbox(
       "Buschfunk anzeigen", userSettings.get("layout.showBuschfunk"));
    groupbox.appendChild(checkboxes.showBuschfunk);
	
    checkboxes.showNews = JautisSettings.checkbox(
       "Neuigkeiten anzeigen", userSettings.get("layout.showNews"));
    groupbox.appendChild(checkboxes.showNews);
	
    checkboxes.NoUmbrueche = JautisSettings.checkbox(
       "Zusätzliche Zeilenumbrüche in Profilen", userSettings.get("layout.NoUmbrueche"));
    groupbox.appendChild(checkboxes.NoUmbrueche);
    return checkboxes;
  }, function(checkboxes) {
    for(name in checkboxes) {
      userSettings.set("layout." + name,
                    checkboxes[name].getValue());
    }
    reloadLayoutStyle();
  }));

  //Layout laden
  reloadLayoutStyle();
})()}catch(e){debug(e)};
//END AREA LAYOUT



//BEGIN AREA PHOTOCOMMENTS
try{(function(){
/**
 * adds more information about the newest foto comments on album pages.
 */
if (!userSettings) {
  return;
}
/*
 * saves the number of photocomments for each _own_ photo.
 * access by photocomments[albumid][photoid];
 */
userSettings.register("photocomments", {});

var albumContainer = document.getElementById("Mod-Photos-Album");
if (albumContainer) {
  var oldComments = userSettings.get("photocomments");

  function renderPhoto(listElement) {
    var as = listElement.getElementsByTagName("a");
    if (as.length < 2) {
      return;
    }
    var photoPageAdress = as[1].href;
    var tmp = /([-\w]+)\/a\/(\w+)\/i\/(\w+)/.exec(photoPageAdress);
    //count the comments?
    var saveCommentInfo = tmp[1] == USERIDS;
    var albumid = tmp[2];
    var photoid = tmp[3];
    tmp = /\d+/.exec(as[1].textContent);
    var photos = tmp[0];

    //add new Notification
    if (saveCommentInfo && oldComments[albumid] && oldComments[albumid][photoid]
        && oldComments[albumid][photoid] != photos) {
      var diff = photos - oldComments[albumid][photoid];
      as[1].appendChild(document.createTextNode(" ("
        + ((diff < 0) ? diff : "+" + diff)
        + ")"));
    }

    if (saveCommentInfo && oldComments[albumid]) {
      oldComments[albumid][photoid] = photos;
    } else if (saveCommentInfo) {
      oldComments[albumid] = {};
      oldComments[albumid][photoid] = photos;
    }

    var commentsRequested = false;
    var tipp = new Tooltip(listElement, "Kommentare werden geladen");
    tipp.onshow = function() {
      if (commentsRequested) { //don’t load twice
        return;
      }
      commentsRequested = true;
      var request = new XMLHttpRequest();
      request.open("GET", photoPageAdress, true);
      request.addEventListener("load", function() {
        var start = request.responseText.indexOf('<ul  class="obj-comment-list">');
        var text = request.responseText.substr(start)
        tipp.text = text.substr(0, text.indexOf("</ul>") + 5);
      }, true);
      request.send(null);


    }
  }
  var listElements = evaluateXPath(albumContainer,
     "//ul[@class=\"photos\"]/li");
  listElements.forEach(renderPhoto);

  userSettings.set("photocomments", oldComments);
}
var bbinput = document.getElementById("Photos_comment");
if (bbinput) {
  new BBCodeableTextarea(bbinput);
}

})()}catch(e){debug(e)};
//END AREA PHOTOCOMMENTS



//BEGIN AREA LOGIN
try{(function(){
/**  LOGIN
 * improve the login of SVZ so that you return to the page you were before.
 */

if(document.getElementById("Loginbox") && typeof GM_xmlhttpRequest != "undefined") {
  CSS(".loginstatus {background-position:right top; background-repeat:no-repeat; min-height:22px; padding-right:25px;}")
  CSS(".loginstatus_success {background-image:url('{IMG:messagesend-ok.png}')}");
  CSS(".loginstatus_error {background-image:url('{IMG:messagesend-error.png}')}");
  CSS(".loginstatus_sending {background-image:url('{IMG:loading_16.png}')}");
  //TODO: style
  var loginStatusElement = null;
  function setLoginStatus (type, text) {
    if (loginStatusElement == null) {
      loginStatusElement = document.createElement("div");
      loginStatusElement.appendChild(document.createTextNode(" "));
      var form = document.getElementById("Loginbox");
      form.parentNode.insertBefore(loginStatusElement, form);
    }
    loginStatusElement.firstChild.data = text + "";
    loginStatusElement.className = "loginstatus loginstatus_" + type;
  }

  function sendLogin(evt) {
    var form = document.getElementById("Loginbox");
    var data = "email="     + decodeURIComponent(document.getElementById("Login_email").value);
    data    += "&password=" + decodeURIComponent(document.getElementById("Login_password").value);
    data    += "&login=Einloggen&jsEnabled=true";
    data    += "&formkey="  + form.elements.namedItem("formkey").value;
    data    += "&iv="       + form.elements.namedItem("iv").value;
    if (form.elements.namedItem("Login_remind").checked) {
      data  += "&Login_remind=1";
    }
    
    setLoginStatus("sending","am Einloggen");

    //can we use normal ajax here?
    GM_xmlhttpRequest({
      method: "POST",
      url: "https://secure." + VZ_NETWORK + ".net/Login",
      headers:{'Content-type':'application/x-www-form-urlencoded'},
      data:data,
      onload: reciveLogin,
      onerror: reciveLogin
    });

    if(evt) {
      evt.preventDefault();
    }
  }

  function reciveLogin(data) {
    if (data.responseText.indexOf("id=\"Quicksearch\"") > -1) {
      setLoginStatus("success", "Eingeloggt");
      if (location.href.indexOf("Logout") > -1) {
        setTimeout(function() {location.href = "/Start"}, 300)
      } else {
        debug("reloading")
        setTimeout(function(){location.reload()}, 300);
      }
    } else {
      setLoginStatus("error", "Fehler beim Einloggen");
      //TODO: handle this, and do not reload
      setTimeout(location.reload, 500);
    }
  }
  document.getElementById("Loginbox").addEventListener("submit", sendLogin, false);
}
})()}catch(e){debug(e)};
//END AREA LOGIN


/**
 * Version information
 */
//BEGIN AREA VERSION INFORMATION
try{(function(){
/**
 * Update notification
 *
 * @author Michael Z.
 * @date 2009-02-22
 */
if(typeof GM_xmlhttpRequest == "undefined") {
  return;
}
globalSettings.register("lastUpdateCheck", new Date(0));
globalSettings.register("lastUpdateVersion", 0);
globalSettings.register("update.activateCheck", true);
var updateItem = null;

function versioncompare(a, b) {
  function versionToArray(version) {
    return version.toString()
                  .replace(/pre/g, ".-3.")
                  .replace(/b/g, ".-2.")
                  .replace(/rc/g, ".-1.")
                  .replace(/[^\d\.]/g,"")
                  .replace(/\.{2,}/,".").replace(/^\./,".").replace(/\.$/,".")
                  .split(".");
  }
  a = versionToArray(a + "");
  b = versionToArray(b + "");
  for(var i=0; i < Math.min(a.length, b.length); i++){
    if(a[i] > b[i]) return 1;
    if(a[i] < b[i]) return -1;
  }
  if(a.length>b.length) return 1;
  if(a.length<b.length) return -1;
  return 0;
}


function displayUpdateMessage() {
  if(updateItem === null) {
    updateItem = new MenuItem("jautis Aktualisieren");
    mainNavigation.insert(updateItem);
    var tt = new Tooltip(updateItem.element);
    tt.onshow = function() {
      tt.setText("<dl><dt>deine Version</dt><dd> " + JAUTIS_VERSION
          + "</dd><dt>aktuelle Version</dt><dd> "
          + globalSettings.get("lastUpdateVersion").htmlencode()
          + "</dd><dt>Neu in dieser Version:</dt><dd> "
          + globalSettings.get("lastUpdateChanges").htmlencode().replace(/\n/g, "<br/>") + "</dd></dl>");
    }
  }
  updateItem.setLink(globalSettings.get("lastUpdateUrl"));
}

//TODO: split into sub functions, for better reading...
function reloadActualVersion() {
  debug("Downloading version information")
  GM_xmlhttpRequest( {
    method: "POST",
    url: JAUTIS_SERVER + "version.php?packageid=jautis@jautis.net&version=" 
        + decodeURIComponent(JAUTIS_VERSION),
    onload: function(resp) {
      /*try {
        var xml = new XML(resp.responseText.replace(/<\?[^>]*>/g, ""));
        if (xml.package && xml.package.version) {
          var urls = xml.package.version.url;
          var url = null;
          debug(urls);
          for (var i = 0; i < urls.length(); i++) {
            if (urls[i].@type == "user_js") {
              url = urls[i];
            }
          }
          if (url != null) {
            globalSettings.set("lastUpdateVersion", xml.package.version.@id);
            globalSettings.set("lastUpdateUrl", url);
            var changes = xml.package.version.changes.change;
            var str = "";
            for (var i = 0; i < changes.length(); i++) {
              str += (str ? "\n" : "") + changes[i]
            }
            globalSettings.set("lastUpdateChanges", str);
          } else {
            debug("Updateserver seldet keine Updateadresse");
          }
        } else if (xml.error) {
          debug("Updateserver meldet Fehler: " + xml.error);
        } else {
          debug("Updateserver sendet Müll: " + resp.responseText);
        }
      } catch(e) {
        debug ("Parse-Fehler beim herunterladend er Versionsinformation: " + e);
      }*/
      var versionmatch = /<version[^>]*id="([^"]*)"[^>]*>[\w\W].*?<\/version>/
                                        .exec(resp.responseText)
      if (versionmatch) {
        var urlmatch = /<url[^>]*type="user_js"[^>]*>([^>]*)/.exec(versionmatch[0]);
        if (urlmatch) {
          var url = urlmatch[1];
          var versionid = versionmatch[1];
          var changes = [];
          versionmatch[0].replace(/<change[^>]*>([^>]*)<\/change>/, function(all, changetext) {
            changes.push(changetext);
          });
          globalSettings.set("lastUpdateVersion", versionid);
          globalSettings.set("lastUpdateUrl", url);
          globalSettings.set("lastUpdateChanges", changes.join("\n"));
        } else {
          debug("Updateserver seldet keine Updateadresse");
        }
      } else if (resp.responseText.indexOf("<error") > -1) {
        debug("Updateserver meldet Fehler: " + resp.responseText.replace(/<[^>]*>/g, ""));
      } else {
        debug("Updateserver sendet Müll: " + resp.responseText);
      }
      renderUpdateElement()
      if(settingpanelelm) {
        renderSettingsPanel(settingpanelelm, true)
      }
    }
  });
  var now = new Date();
  globalSettings.set("lastUpdateCheck",
      new Date(now.getFullYear(), now.getMonth(), now.getDate()));
}

function renderUpdateElement() {
  if (versioncompare(JAUTIS_VERSION, globalSettings.get("lastUpdateVersion")) == -1) {
    displayUpdateMessage();
  } 

  var lastUpdate = globalSettings.get("lastUpdateCheck");

  if((!lastUpdate.getTime || lastUpdate.getTime() < Date.now() - 24 * 3600000)
      && globalSettings.get("update.activateCheck")) {
    reloadActualVersion();
  }
}

renderUpdateElement();
setInterval(renderUpdateElement, 120000);

var settingpanelelm = null;

function renderSettingsPanel(elm) {
  var data = {};
  var currentlyChecked = arguments[1] == true;
  while(elm.childNodes.length > 0) {
    elm.removeChild(elm.childNodes[0]);
  }

  settingpanelelm = elm;

  var elm2=document.createElementNS(XULNS, "vbox");
  elm.appendChild(elm2);
  elm=elm2;
  
  var updateArea = document.createElementNS(XULNS, "groupbox");
  var caption = document.createElementNS(XULNS, "caption");
  caption.setAttribute("label", "Jautis Version");
  updateArea.appendChild(caption);
  elm.appendChild(updateArea);
  
  var buttons = document.createElementNS(XULNS, "vbox");
  buttons.style.marginTop="1em";
  
  data.activateCB = JautisSettings.checkbox("Automatische Updates aktivieren", globalSettings.get("update.activateCheck"));
  updateArea.appendChild(data.activateCB);

  if(versioncompare(JAUTIS_VERSION, globalSettings.get("lastUpdateVersion")) == -1) {
    var description=document.createElementNS(XULNS, "description");
    description.appendChild(document.createTextNode(
      "Du hast eine alte Version: " + JAUTIS_VERSION + " "
    ));
    updateArea.appendChild(description)
    var description=document.createElementNS(XULNS, "description");
    description.appendChild(document.createTextNode(
      "Die aktuelle Version ist: " + globalSettings.get("lastUpdateVersion")
    ));
    updateArea.appendChild(description)
    
    var actualisationMessage=document.createElementNS(XULNS, "description");
    actualisationMessage.appendChild(document.createTextNode("Die Aktualisierung wird erst nach einem Neuladen der Seite wirksam."));
    actualisationMessage.setAttribute("collapsed", "true");
    updateArea.appendChild(actualisationMessage)

    var button=document.createElementNS(XULNS, "button");
    button.setAttribute("label", "Jautis 0.2 aktualisieren");
    button.setAttribute("flex", "1");
    button.addEventListener("command", function(){
      actualisationMessage.setAttribute("collapsed", "false");
      unsafeWindow.location.href = globalSettings.get("lastUpdateUrl");
    }, true);
    buttons.appendChild(button)
  }
  else {
    var description=document.createElementNS(XULNS, "description");
    description.appendChild(document.createTextNode("Du hast die aktuelle Version: " + JAUTIS_VERSION));
    buttons.appendChild(description)
  }

  if(currentlyChecked ) {
    var description=document.createElementNS(XULNS, "description");
    description.appendChild(document.createTextNode("Suche nach Updates beendet"));
    description.style.marginTop="1em";
    buttons.appendChild(description)
  }
  else {
    var button=document.createElementNS(XULNS, "button");
    button.setAttribute("label", "Nach Updates suchen");
    button.setAttribute("flex", "1");
    button.addEventListener("command", function(evt) {
      reloadActualVersion();
      evt.target.setAttribute("label", "Suche nach Updates ...");
    }, true);
    buttons.appendChild(button)
  }
  updateArea.appendChild(buttons);
  //End of update Area
  
  var teamArea = document.createElementNS(XULNS, "groupbox");
  var caption = document.createElementNS(XULNS, "caption");
  caption.setAttribute("label", "Mitwirkende am Jautis-Projekt");
  teamArea.appendChild(caption);
  elm.appendChild(teamArea);
  
  var list = document.createElement("ul");
  teamArea.appendChild(list);
  ["Michael Z.: Projektleitung", "Lukas Heblik", "Fabian F.", "Dominik T.", "Joel R."].forEach(function(text) {
    var li = document.createElement("li");
    li.appendChild(document.createTextNode(text))
    list.appendChild(li);
  });
  var textdiv = document.createElement("div");
  textdiv.appendChild(document.createTextNode("An jautis haben auch noch einige weitere Personen mitgearbeitet. Eine vollständige Liste des gesamten Teams befindet sich auf "))
  var a = document.createElement("a");
  a.href = "http://www.jautis.net/";
  a.target = "_blank";
  a.appendChild(document.createTextNode("jautis.net"))
  textdiv.appendChild(a);
  textdiv.appendChild(document.createTextNode("."))
  teamArea.appendChild(textdiv);
  var textdiv = document.createElement("div");
  textdiv.appendChild(document.createTextNode("Hife zu jautis erhältst du in der "))
  var a = document.createElement("a");
  a.href = VZ_NETWORK == "schuelervz" ? "/Groups/Overview/5f92c9efe364bd3d"
                                      : "/Groups/Overview/c8e7bd31c63c8cc3";
  a.target = "_blank";
  a.appendChild(document.createTextNode("jautis - Gruppe"))
  textdiv.appendChild(a);
  textdiv.appendChild(document.createTextNode("."))
  teamArea.appendChild(textdiv);
  
  return data;
}
JautisSettings.addPanel( new JautisSettingsPanel("version", "Version", 
                      renderSettingsPanel, function(data) {
  globalSettings.set("update.activateCheck", data.activateCB.getValue())
}) );

//dialog to display after the update
if (userSettings) {
  userSettings.register("currentVersion", "0");
  /**
   * compares two versions
   * @author Michael Z.
   * @date 2009-01-24
   * @param version1 the first version as String
   * @param version2 the second version as String
   * @return 1 if version1 > version2
   *         0 if version1 = version2
   *        -1 if version1 < version2
   */

  var oldVersion = userSettings.get("currentVersion");
  if(oldVersion != JAUTIS_VERSION) {
    var html ="";
    if(oldVersion == "0") {
      html += "<p>Hallo,</p><p>Schön dass du jautis installiert hast. "
        + "Jautis fügt deinem " + VZ_NETWORK.replace("vz", "VZ") + " viele "
        + "Funktionen hinzu, einige erblickst du sofort, andere sind nicht "
        + "so offensichtlich aber trotzdem nützlich.</p>"
        + "<p>Du kannst die Jautis-Einstellungen über das Menü auf der "
        + "Linken Seite erreichen. Dort kannst du zu den Einzelen Bereichen "
        + "die Einstellungen vornehmen. Viele Einstellungen kannst du aber "
        + "auch auf den entsprechenden Seiten machen, wo sie sich auswirken.</p>"
        + "<p>Solltest du irgendwann einmal ohne jautis durchs SchülerVZ "
        + "surfen wollen, kannst du jautis deaktivieren indem du auf den "
        + "bunten Affen in der Statusleite klickst, so dass er grau wird. "
        + "Auf die gleiche Weise kannst du jautis auch wieder aktivieren.</p>"
    } else {
      html += "<p>Hallo,</p><p>jautis wurde erfolgreich aktualisiert.</p>"
        + "<p>Solltest du weitere Fragen haben kannst du dich einfach in der "
        + "<a href=\"/Search/ResultGroups/name/jautis\">jautis-Gruppe</a> "
        + "melden.</p><p>Auf jautis.net findest du eine Liste der Neuerungen "
        + "in deiner "
        + "<a href=\"http://www.jautis.net/versions/jautis%40jautis.net/" 
        + encodeURIComponent(JAUTIS_VERSION) + ".html\">Version " 
        + JAUTIS_VERSION + "</a> und kannst Fehler melden.</p>"
    }

    var elm = document.createElement("div");
    elm.innerHTML = html;
    new JautisDialog("Willkommen bei jautis!", elm);

    userSettings.set("currentVersion", JAUTIS_VERSION);
  }
}// end if(userSettings)


})()}catch(e){debug(e)};
//END AREA VERSION INFORMATION



//BEGIN AREA FAVICON
try{(function(){

//TODO settings

document.title = document.title.replace(/(\w+VZ)\s\|\s(.*)/i, "$2 - $1");

var newFavicon = "";
if (document.getElementById("profileImage")) {
  newFavicon = document.getElementById("profileImage").src
                                              .replace(/\.(gif|jpg)/, "-s.$1");
} else if (document.getElementById("GroupsRight")) {
  newFavicon = document.getElementById("GroupsRight")
           .getElementsByTagName("img")[0].src.replace(/\.(gif|jpg)/, "-m.$1");
}

if(newFavicon) {
  var head = document.getElementsByTagName("head")[0];
  var links = head.getElementsByTagName("link");
  //remove old icon
  for(var i = 0; i < links.length; i++) {
    if(links[i].getAttribute("rel") == "shortcut icon") {
      links[i].parentNode.removeChild(links[i--]);
    }
  }
  //add new one
  var link = document.createElement("link");
  link.setAttribute("rel" , "shortcut icon");
  link.setAttribute("href", newFavicon);
  head.appendChild(link)
}

})()}catch(e){debug(e)};
//END AREA FAVICON




//BEGIN AREA IMAGETOOLTIPS
try{(function(){

if(document.getElementById("GroupMemberImage")){
  var imgs = document.getElementById("GroupMemberImage").getElementsByTagName("img");
  for(var i=0;i<imgs.length;i++)
    new Tooltip(imgs[i], "", imgs[i].src.replace("-s.","."))
}

})()}catch(e){debug(e)};
//END AREA IMAGETOOLTIPS

//BEGIN AREA PROFILETOOLTIPS
if (userSettings.get("allgemein.GroupViewing")) {try{
  (function(){

var div = document.getElementById("Mod-Groups-Snipplet");
if(!div)
  return;

var ul = div.getElementsByTagName("ul")[0]
if(!ul)
  return;

var ladentext="<br>Daten werden geladen...<br>"

function showGrouplistTooltip(tooltip) {
  if(tooltip.text != ladentext)
    return;
  var a=tooltip.element.getElementsByTagName("a")[0];
  tooltip.setText("<b>"+a.firstChild.data+"</b><br><br>Weitere Daten werden geladen...");
  var ajaxrequest=new XMLHttpRequest();
  ajaxrequest.open("GET",a.href, true)
  ajaxrequest.onload=function(){
    var text    = ajaxrequest.responseText, newtext="";
    //name
    var tmp     = /<h1 class="ellipsis" title="([^"]*)/.exec(text) || ["",""]
    newtext    += "<b>"+tmp[1]+"</b><br><dl>";
    //Mitglieder
    var tmp     = /<a href="\/Groups\/Memberlist\/\w+">(\w\d*)/.exec(text) || ["",""]
    newtext    += "<dt>Mitglieder:</dt><dd>"+tmp[1]+"</dd>";
    //Beschreibung
    var tmp     = /<h2>Beschreibung<\/h2>*\s*(.*?(<br\s?\/?>.*?)*?)</.exec(text) || ["",""]
    tmp[1]      = tmp[1].replace(/\n+/,"").replace(/<br\s?\/?>/g,"\n").replace(/^\n+/,"").replace(/\n$/,"")
    if(tmp[1].length>300)
      tmp[1]    = tmp[1].substr(0, 300)+"\n (...)"
    newtext    += "<dt>Beschreibung:</dt><dd><br/>"+new BBCoder().parseString(tmp[1]).replace(/\n/g,"<br>")+"</dd>";
    //aktuelles
    var tmp     = /Aktuelle Infos[\d\D\w\W]*?<div class=\"obj-innerbox[.]*\">\s*(.*?(<br\s?\/?>.*?){0,6})</.exec(text) || ["",""]
    tmp[1]      = tmp[1].replace(/\n+/,"").replace(/<br\s?\/?>/g,"\n").replace(/^\n+/,"").replace(/\n$/,"")
    if(tmp[1].length>300)
      tmp[1]    = tmp[1].substr(0, 300)+"\n (...)"
    newtext    += "<dt>Aktuelles:</dt><dd><br/>"+new BBCoder().parseString(tmp[1]).replace(/\n/g,"<br>")+"</dd>";
    tooltip.setText(newtext+"</dl>");
    //Bild
    var tmp     = /<div class=\"obj-box\sonethird\">[\d\D]+?src=\"([^"]+)\"/.exec(text) || ["",""]
    tooltip.setImage("about:blank")
    tooltip.setImage(tmp[1]);
  }
  ajaxrequest.send(null);
}

var lis = ul.getElementsByTagName("li");
for(var i=0;i<lis.length;i++){
  var tooltip=new Tooltip(lis[i], ladentext)
  tooltip.onshow=showGrouplistTooltip;
}


  })()
  }catch(e){alert(e)}}

//END AREA PROFILETOOLTIPS



//BEGIN AREA Ein/ausblenden von Persönliches auf Profilseiten // LUHE
//TODO
//deleted because of bad programming style. Michael (2009-09-01)
//END AREA Ein/ausblenden von Persönliches auf Profilseiten // LUHE

//BEGIN AREA Experteneinstellungen
try{(function(){

JautisSettings.addPanel(new JautisSettingsPanel("expert", "für Experten",
  function(elm) {
    var deck = document.createElementNS(XULNS, "deck");
    deck.setAttribute("flex", "1");
    elm.appendChild(deck);

    var button = document.createElementNS(XULNS, "button");
    button.addEventListener("command", function(evt) {
      evt.target.parentNode.setAttribute("selectedIndex", "1");
    }, true);
    button.setAttribute("label", "Ich werde vorsichtig sein.");
    button.setAttribute("flex", "1");
    deck.appendChild(button);

    var tree = document.createElementNS(XULNS, "tree");
    deck.appendChild(tree);
    var cols = document.createElementNS(XULNS, "treecols");
//    cols.setAttribute("flex", "1");
    tree.appendChild(cols);

    var col = document.createElementNS(XULNS, "treecol");
    col.setAttribute("id", "advancedSettings-name");
    col.setAttribute("label", "Name");
    cols.appendChild(col);

    var splitter = document.createElementNS(XULNS, "splitter");
    splitter.setAttribute("class", "tree-splitter");
    cols.appendChild(splitter);

    var col = document.createElementNS(XULNS, "treecol");
    col.setAttribute("id", "advancedSettings-forUser");
    col.setAttribute("label", "Nür für diesen Benutzer");
    cols.appendChild(col);

    var splitter = document.createElementNS(XULNS, "splitter");
    splitter.setAttribute("class", "tree-splitter");
    cols.appendChild(splitter);

    var col = document.createElementNS(XULNS, "treecol");
    col.setAttribute("id", "advancedSettings-type");
    col.setAttribute("label", "Typ");
    cols.appendChild(col);

    var splitter = document.createElementNS(XULNS, "splitter");
    splitter.setAttribute("class", "tree-splitter");
    cols.appendChild(splitter);

    var col = document.createElementNS(XULNS, "treecol");
    col.setAttribute("id", "advancedSettings-value");
    col.setAttribute("label", "Wert");
    col.setAttribute("flex", "1");
    cols.appendChild(col);

    var children = document.createElementNS(XULNS, "treechildren");
    tree.appendChild(children);

    var data = [];
    for (var i in userSettings.defaultValues) {
      data.push({name: i, defaultValue: userSettings.defaultValues[i],
        value: userSettings.get(i), forUser: true});
    }
    for (var i in globalSettings.defaultValues) {
      data.push({name: i, defaultValue: globalSettings.defaultValues[i],
        value: globalSettings.get(i), forUser: false});
    }
    for (var i = 0; i < data.length; i++) {
      data[i].orginalValue = data[i].value;
    };
    data.sort(function(a, b) {
      return a.name < b.name ? -1 : a.name == b.name ? 0 : 1;
    });

    /*var treeView = {
      rowCount : data.length,
      getCellText : function(row, column) {
        if (column.id == "advancedSettings-name") {
          return data[row].name;
        } else if (column.id == "advancedSettings-forUser") {
          return data[row].forUser ? "Ja" : "Nein";
        } else if (column.id == "advancedSettings-type") {
          if (typeof value == "string") {
            return "Zeichenkette";
          } else if (typeof value == "number") {
            return "Zahl";
          } else if (typeof value == "boolean") {
            return "Boolischer Wert";
          } else {
            return "Objekt";
          }
        } else if (column.id == "advancedSettings-value") {
          return data[row].value;
        } else {
          return "Spalte falsch";
        }
      },
      setTree: function(treebox){ this.treebox = treebox; },
      isContainer: function(row){ return false; },
      isSeparator: function(row){ return false; },
      isSorted: function(){ return false; },
      getLevel: function(row){ return 0; },
      getImageSrc: function(row,col){ return null; },
      getRowProperties: function(row,props){},
      getCellProperties: function(row,col,props){},
      getColumnProperties: function(colid,col,props){}
    };
    setTimeout(function() {tree.view = treeView;}, 10000);
    //TODO: Doesnt work, use normal dom?*/
    
    for (var i = 0; i < data.length; i++) {
      var item = document.createElementNS(XULNS, "treeitem");
      children.appendChild(item);
      var row = document.createElementNS(XULNS, "treerow");
      item.appendChild(row);
      
      var cell = document.createElementNS(XULNS, "treecell");
      cell.setAttribute("label", data[i].name);
      row.appendChild(cell);      
      
      var cell = document.createElementNS(XULNS, "treecell");
      cell.setAttribute("label", data[i].forUser ? "Benutzer" : "Global");
      row.appendChild(cell);      
      
      var cell = document.createElementNS(XULNS, "treecell");
      cell.setAttribute("label", typeof data[i].value);
      row.appendChild(cell);      
      
      var cell = document.createElementNS(XULNS, "treecell");
      cell.setAttribute("label", data[i].value);
      cell.setAttribute("idx", i);
      //Does not work...
      cell.addEventListener("dblclick", function(evt) {
        var i = evt.target.getAttribute("idx");
        if (typeof data[i].value == "boolean") {
          data[i].value = !data[i].value;
        } else if (typeof data[i].value == "number") {
          data[i].value = parseFloat(prompt("Neuer Wert für " 
              + data[i].name, data[i].value));
        } else if (typeof data[i].value == "string") {
          data[i].value = prompt("Neuer Wert für " 
              + data[i].name, data[i].value);
        }
        evt.target.setAttribute("label", data[i].value);
      }, true)
      row.appendChild(cell);      
    }
    return data;
  }, function(data) {

  }));

})()}catch(e){debug(e)};
//END AREA Experteneinstellungen


//css
_css_element = document.createElement("style");
CSS(_css);
document.getElementsByTagName("head")[0].appendChild(_css_element);

//Uncomment this to enable Firebug speed test
//}).toString() + ")()";