function BBCodeEditor (options)
{
  this.body_id = 'tbMsg';

  this.initialize = function(options)
  {
    this.body_id = options.body_id || this.body_id;
    this.enableWysiwyg = options.enableWysiwyg !== false;
    this.enableAutoGrow = options.enableAutoGrow !== false;

    // List of HTML entities for escaping.
    this.htmlEscapes = {
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#x27;'
    };

    // Regex containing the keys listed immediately above.
    this.htmlEscaper = /[<>"']/g;

    this.isIE = /msie|MSIE/.test(navigator.userAgent);
    this.isTrident = /Trident/.test(navigator.userAgent);
    this.isFirefox = /Firefox/.test(navigator.userAgent);
    this.isChrome = /Chrome/.test(navigator.userAgent);
    this.isSafari = /Safari/.test(navigator.userAgent) && !this.isChrome;
    this.browser = this.isIE || window.opera;
    this.editorVisible = false;

    this.textboxelement = document.getElementById(this.body_id);
    this.textboxelement.setAttribute('class', 'editorBBCODE');
    this.textboxelement.className = "editorBBCODE";

    if (this.enableWysiwyg)
    {
      this.ifm = document.createElement("iframe");
      this.ifm.setAttribute("frameborder", "0");
      this.ifm.style.height = this.textboxelement.style.height;
      this.textboxelement.parentNode.insertBefore(this.ifm, this.textboxelement);
      this.textboxelement.style.display = 'none';

      this.ShowEditor();
    }
  };


  this.rep = function(re, str)
  {
    this.content = this.content.replace(re, str);
  };


  this.ShowEditor = function()
  {
    j$('.BBeditor .editbar').each(function(index, element)
    {
      element.style.display = 'block';
    });
    if (!this.enableWysiwyg) return;

    this.editorVisible = true;
    this.content = document.getElementById(this.body_id).value;
    this.content = this.content.replace(/<br\s*\/?>/gi,"\n");
    this.content = this.EscapeHTML(this.content);
    this.myeditor = this.ifm.contentWindow.document;
    this.bbcode2html();
    this.myeditor.designMode = "on";
    this.myeditor.open();
    this.myeditor.write('<html><head><link href="/?waxtrapp=grwxdzEsHowOvvOhIG&amp;pane=hdtgtekBsHowOvvOhIFYkYpYHiCxC" rel="stylesheet" type="text/css" /></head>');
    this.myeditor.write('<body style="margin: 0;" class="editorWYSIWYG">');
    this.myeditor.write(this.content);
    this.myeditor.write('</body></html>');
    this.myeditor.close();

    this.ifm.onload = function()
    {
      this.myeditor.body.contentEditable = true;

      if (this.myeditor.attachEvent)
      {
        this.myeditor.attachEvent("onkeypress", function(e) { this.kp(e); }.bind(this));
        this.ifm.attachEvent("onblur", function() { this.doCheck(); }.bind(this));
      }
      else if (this.myeditor.addEventListener)
      {
        this.myeditor.addEventListener("keypress", function(e) { this.kp(e); }.bind(this), true);
        this.myeditor.addEventListener("blur", function() { this.doCheck(); }.bind(this), true);
        document.getElementById(this.body_id).form.addEventListener("submit", function() { this.doCheck(); }.bind(this), true);

        if (this.enableAutoGrow)
        {
          this.myeditor.body.style.position = 'fixed';
          this.myeditor.body.style.width = '100%';

          this.myeditor.addEventListener("keyup", function(e) { this.autoGrow(e); }.bind(this), true);
          this.myeditor.addEventListener("focus", function(e) { this.autoGrow(e); }.bind(this), true);
          this.myeditor.addEventListener("paste", function(e) { setTimeout(this.autoGrow.bind(this), 10); }.bind(this), true);
          this.myeditor.body.parentNode.addEventListener("focus", function(e) { this.placeCaretAtEnd(e, this.myeditor.body); }.bind(this), true);
          this.myeditor.body.parentNode.addEventListener("click", function(e) { this.placeCaretAtEnd(e, this.myeditor.body); }.bind(this), true);
        }
      }
    }.bind(this);
  };


  this.SwitchEditor = function()
  {
    if (this.editorVisible)
    {
      this.doCheck();
      this.ifm.style.display = 'none';
      this.textboxelement.style.display = '';
      this.editorVisible = false;
    }
    else
    {
      if (this.enableWysiwyg && this.ifm)
      {
        this.ifm.style.display = '';
        this.textboxelement.style.display = 'none';
        this.ShowEditor();
        this.editorVisible = true;
      }
    }
  };


  this.html2bbcode = function()
  {
    this.rep(/<img\s[^<>]*?src=\"?([^<>]*?)\"?(\s[^<>]*)?\/?>/gi,"[img]$1[/img]");
    this.rep(/<\/(strong|b)>/gi, "[/b]");
    this.rep(/<(strong|b)(\s[^<>]*)?>/gi,"[b]");
    this.rep(/<\/(em|i)>/gi,"[/i]");
    this.rep(/<(em|i)(\s[^<>]*)?>/gi,"[i]");
    this.rep(/<\/u>/gi, "[/u]");
    this.rep(/<\/q><\/blockquote>/gi, "[/quote]");
    this.rep(/<blockquote(\s[^<>]*)?>(\s[^<>]*)?<cite(\s[^<>]*)?>Citaat van ([^<>]*?)\:<\/cite>/gi, "[quote author=$4]");
    this.rep(/<blockquote(\s[^<>]*)?>(\s[^<>]*)?<q(\s[^<>]*)?>/gi, "[quote]");
    this.rep(/\n/gi, " ");
    this.rep(/\r/gi, " ");
    this.rep(/<u(\s[^<>]*)?>/gi, "[u]");
    this.rep(/<div><br(\s[^<>]*)?>/gi, "<div>");//chrome-safari fix to prevent double linefeeds
    this.rep(/<br(\s[^<>]*)?><\/div>$/gi, "<div>");//firefox fix to prevent extra linefeed at the end
    this.rep(/<p><br><\/p>/gi,"\n\n");//ie fix to prevent stripped linefeeds
    this.rep(/<br(\s[^<>]*)?>/gi,"\n");
    this.rep(/<p(\s[^<>]*)?>/gi,"");
    this.rep(/<\/p>/gi, "\n\n");//ie fix by using double \n to prevent stripped linefeeds
    this.rep(/<ul>/gi, "[ul]");
    this.rep(/<\/ul>/gi, "[/ul]");
    this.rep(/<ol>/gi, "[ol]");
    this.rep(/<\/ol>/gi, "[/ol]");
    this.rep(/<li>/gi, "[li]");
    this.rep(/<\/li>/gi, "[/li]");
    this.rep(/<\/div>\s*<div([^<>]*)>/gi, "</span>\n<span$1>");//chrome-safari fix to prevent double linefeeds
    if (this.isChrome || this.isSafari)
    {
      this.rep(/<div([^<>]*)>/gi,"\n<span$1>");//only on chrome-safari the *first* line is not enclosed in a <div> so we need to add a line break before that
    }
    this.rep(/<\/div>/gi,"</span>\n");
    this.rep(/ /gi," ");
    this.rep(/"/gi,"\"");
    this.rep(/&/gi,"&");

    //remove style & script tags
    this.rep(/<script.*?>.*?<\/script>/gi, "");
    this.rep(/<style>.*?<\/style>/gi, "");
	
    var sc, sc2;
    do
    {
      sc = this.content;
      this.rep(/<font\s[^<>]*?color=\"?([^<>]*?)\"?(\s[^<>]*)?>([^<>]*?)<\/font>/gi,"[color=$1]$3[/color]");

      if (sc == this.content)
      {
        this.rep(/<font[^<>]*>([^<>]*?)<\/font>/gi,"$1");
      }
      this.rep(/<a\s[^<>]*?href=\"?([^<>]*?)\"?(\s[^<>]*)?>([^<>]*?)<\/a>/gi,"[url=$1]$3[/url]");
      sc2 = this.content;
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?font-weight: ?bold;?\"?\s*([^<]*?)<\/\1>/gi,"[b]<$1 style=$2</$1>[/b]");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?font-weight: ?normal;?\"?\s*([^<]*?)<\/\1>/gi,"<$1 style=$2</$1>");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?font-style: ?italic;?\"?\s*([^<]*?)<\/\1>/gi,"[i]<$1 style=$2</$1>[/i]");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?font-style: ?normal;?\"?\s*([^<]*?)<\/\1>/gi,"<$1 style=$2</$1>");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?text-decoration: ?underline;?\"?\s*([^<]*?)<\/\1>/gi,"[u]<$1 style=$2</$1>[/u]");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?text-decoration: ?none;?\"?\s*([^<]*?)<\/\1>/gi,"<$1 style=$2</$1>");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?color: ?([^<>]*?);\"?\s*([^<]*?)<\/\1>/gi, "[color=$2]<$1 style=$3</$1>[/color]");
      this.rep(/<(span|blockquote|pre)\s[^<>]*?style=\"?font-family: ?([^<>]*?);\"?\s*([^<]*?)<\/\1>/gi, "[font=$2]<$1 style=$3</$1>[/font]");
      this.rep(/<(blockquote|pre)\s[^<>]*?style=\"?\"? (class=|id=)([^<>]*)>([^<>]*?)<\/\1>/gi, "<$1 $2$3>$4</$1>");
      this.rep(/<pre>([^<>]*?)<\/pre>/gi, "[code]$1[/code]");
      this.rep(/<span\s[^<>]*?style=\"?\"?>([^<>]*?)<\/span>/gi, "$1");

      if (sc2 == this.content)
      {
        this.rep(/<span[^<>]*>([^<>]*?)<\/span>/gi, "$1");
        sc2 = this.content;
      }
    }
    while (sc!=this.content)

    this.rep(/<[^<>]*>/gi,"");
    this.rep(/</gi,"<");
    this.rep(/>/gi,">");
	
    do
    {
      sc = this.content;
      this.rep(/\[(b|i|u)\]\[quote([^\]]*)\]([\s\S]*?)\[\/quote\]\[\/\1\]/gi, "[quote$2][$1]$3[/$1][/quote]");
      this.rep(/\[color=([^\]]*)\]\[quote([^\]]*)\]([\s\S]*?)\[\/quote\]\[\/color\]/gi, "[quote$2][color=$1]$3[/color][/quote]");
      this.rep(/\[(b|i|u)\]\[code\]([\s\S]*?)\[\/code\]\[\/\1\]/gi, "[code][$1]$2[/$1][/code]");
      this.rep(/\[color=([^\]]*)\]\[code\]([\s\S]*?)\[\/code\]\[\/color\]/gi, "[code][color=$1]$2[/color][/code]");
    }
    while(sc!=this.content)

    //clean up empty tags
    do
    {
      sc = this.content;
      this.rep(/\[b\]\[\/b\]/gi, "");
      this.rep(/\[i\]\[\/i\]/gi, "");
      this.rep(/\[u\]\[\/u\]/gi, "");
      this.rep(/\[quote[^\]]*\]\[\/quote\]/gi, "");
      this.rep(/\[code\]\[\/code\]/gi, "");
      this.rep(/\[url=([^\]]+)\]\[\/url\]/gi, "");
      this.rep(/\[img\]\[\/img\]/gi, "");
      this.rep(/\[color=([^\]]*)\]\[\/color\]/gi, "");
    }
    while (sc!=this.content)
  };


  this.bbcode2html = function()
  {
    // example: [b] to <strong>
    this.rep(/\</gi,"<"); //removing html tags
    this.rep(/\>/gi,">");
	
    this.rep(/\n/gi, "<br />");
    this.rep(/\[ul\]/gi, "<ul>");
    this.rep(/\[\/ul\]/gi, "</ul>");
    this.rep(/\[ol\]/gi, "<ol>");
    this.rep(/\[\/ol\]/gi, "</ol>");
    this.rep(/\[li\]/gi, "<li>");
    this.rep(/\[\/li\]/gi, "</li>");

    if (this.browser)
    {
      this.rep(/\[b\]/gi,"<strong>");
      this.rep(/\[\/b\]/gi,"</strong>");
      this.rep(/\[i\]/gi,"<em>");
      this.rep(/\[\/i\]/gi,"</em>");
      this.rep(/\[u\]/gi,"<u>");
      this.rep(/\[\/u\]/gi,"</u>");
    }
    else
    {
      this.rep(/\[b\]/gi,"<span style=\"font-weight: bold;\">");
      this.rep(/\[i\]/gi,"<span style=\"font-style: italic;\">");
      this.rep(/\[u\]/gi,"<span style=\"text-decoration: underline;\">");
      this.rep(/\[\/(b|i|u)\]/gi,"</span>");
    }

    this.rep(/\[img\]([^\"]*?)\[\/img\]/gi,"<img src=\"$1\" />");

    var sc;
    do
    {
      sc = this.content;
      this.rep(/\[url=([^\]]+)\]([\s\S]*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");
      this.rep(/\[url\]([\s\S]*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");
      this.rep(/\[quote author=([^\]]*?)\]([\s\S]*?)\[\/quote\]/gi, "<blockquote><cite>Citaat van $1:</cite><q>$2</q></blockquote>");
      this.rep(/\[quote\]([\s\S]*?)\[\/quote\]/gi, "<blockquote><q>$1</q></blockquote>");

      if (this.browser)
      {
        this.rep(/\[color=([^\]]*?)\]([\s\S]*?)\[\/color\]/gi, "<font color=\"$1\">$2</font>");
        this.rep(/\[font=([^\]]*?)\]([\s\S]*?)\[\/font\]/gi, "<font face=\"$1\">$2</font>");
      }
      else
      {
        this.rep(/\[color=([^\]]*?)\]([\s\S]*?)\[\/color\]/gi, "<span style=\"color: $1;\">$2</span>");
        this.rep(/\[font=([^\]]*?)\]([\s\S]*?)\[\/font\]/gi, "<span style=\"font-family: $1;\">$2</span>");
      }

      this.rep(/\[code\]([\s\S]*?)\[\/code\]/gi,"<pre>$1</pre> ");
    }
    while(sc!=this.content);
  };


  this.doCheck = function()
  {
    if (!this.editorVisible)
    {
      this.ShowEditor();
    }
    this.content = this.myeditor.body.innerHTML;
    this.html2bbcode();
    document.getElementById(this.body_id).value = this.content;
  };


  this.stopEvent = function(evt)
  {
    evt || window.event;
    if (evt.stopPropagation)
    {
      evt.stopPropagation();
      evt.preventDefault();
    }
    else if (typeof evt.cancelBubble != "undefined")
    {
      evt.cancelBubble = true;
      evt.returnValue = false;
    }
    return false;
  };


  this.doQuote = function()
  {
    if (this.editorVisible)
    {
      this.ifm.contentWindow.focus();
      emptyText = "Citaat...";
      if (this.isIE)
      {
        textRange = this.ifm.contentWindow.document.selection.createRange();
        newText = textRange.text;
        if (newText == "")
        {
          newText = emptyText;
        }
        textRange.pasteHTML("<blockquote><q>" + newText + "</q></blockquote>");
      }
      else
      {
        var textRange = this.ifm.contentWindow.getSelection().getRangeAt(0);
        var newText = textRange.toString();
        if (newText == "")
        {
          newText = emptyText;
        }
        textRange.deleteContents();
        textNode = this.ifm.contentWindow.document.createTextNode(newText);
        paragraphNode = this.ifm.contentWindow.document.createElement("q");
        paragraphNode.appendChild(textNode);
        quoteNode = this.ifm.contentWindow.document.createElement("blockquote");
        quoteNode.appendChild(paragraphNode);
        textRange.insertNode(quoteNode);
      }
    }
    else
    {
      this.AddTag('[quote]', '[/quote]');
    }
  };


  this.autoGrow = function(e)
  {
    if (this.enableAutoGrow)
    {
      if ((!(this.minHeight > 0)) &&
          (this.ifm.offsetHeight > 0))
      {
        this.minHeight = this.ifm.offsetHeight-2;
      }

      var curHeight = this.myeditor.body.offsetHeight;
      
      if ((curHeight+50) > this.minHeight)
      {
        this.ifm.style.height = (curHeight+50)+'px';
        this.textboxelement.style.height = (curHeight+50)+'px';
      }
      else
      {
        this.ifm.style.height = this.minHeight+'px';
        this.textboxelement.style.height = this.minHeight+'px';
      }
    }
  };


  this.placeCaretAtEnd = function(e, el)
  {
    if ((e.target !== el) &&
        (!j$.contains(el, e.target)))
    {
      el.focus();
      if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined")
      {
        var range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        var sel = this.ifm.contentWindow.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
      }
      else if (typeof document.body.createTextRange != "undefined")
      {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
      }
    }
  };


  this.kp = function(e)
  {
    if (this.isIE)
    {
      if (e.keyCode == 13)
      {
        var r = this.myeditor.selection.createRange();
        if (r.parentElement().tagName.toLowerCase() != "li")
        {
          r.pasteHTML('<br/>');
          if (r.move('character'))
          {
            r.move('character', -1);
          }
          r.select();
          this.stopEvent(e);
          return false;
        }
      }
    }
  };


  this.InsertText = function(txt)
  {
    if (this.editorVisible)
    {
      this.insertHtml(txt);
    }
    else
    {
      var element = this.textboxelement;

      if (this.isIE)
      {
        if (document.selection)
        {
          element.focus();
          sel = document.selection.createRange();
          sel.text = txt;
        }
      }
      else if (element.selectionStart || element.selectionStart == '0')
      {
        var startPos = element.selectionStart;
        var endPos = element.selectionEnd;
        element.value = element.value.substring(0, startPos) + txt + element.value.substring(endPos, element.value.length);
      }
      else
      {
        element.value += txt;
      }
    }
  };


  this.doClick = function(command)
  {
    if (this.editorVisible)
    {
      this.ifm.contentWindow.focus();
      this.myeditor.execCommand(command, false, null);
    }
    else
    {
      switch (command) {
        case 'bold':
          this.AddTag('[b]', '[/b]'); break;
        case 'italic':
          this.AddTag('[i]', '[/i]'); break;
        case 'underline':
          this.AddTag('[u]', '[/u]'); break;
        case 'InsertUnorderedList':
          this.AddTag('[ul][li]', '[/li][/ul]'); break;
        case 'InsertOrderedList':
          this.AddTag('[ol][li]', '[/li][/ol]'); break;
      }
    }
  };


  this.doLink = function()
  {
    if (this.editorVisible)
    {
      this.ifm.contentWindow.focus();
      var mylink = prompt("Voer een URL in:", "http://");
      if ((mylink != null) && (mylink != ""))
      {
        if (this.isIE)
        { //IE
          var range = this.ifm.contentWindow.document.selection.createRange();
          if (range.text == '')
          {
            range.pasteHTML("<a href='" + mylink + "'>" + mylink + "</a>");
          }
          else
          {
            this.myeditor.execCommand("CreateLink", false, mylink);
          }
        }
        else if (window.getSelection)
        { //FF
          var userSelection = this.ifm.contentWindow.getSelection().getRangeAt(0);
          if (userSelection.toString().length == 0)
          {
            textNode = this.ifm.contentWindow.document.createTextNode(mylink);
            anchorNode = this.ifm.contentWindow.document.createElement("a");
            anchorNode.href = mylink;
            anchorNode.appendChild(textNode);
            userSelection.insertNode(anchorNode);
          }
          else
          {
            this.myeditor.execCommand("CreateLink", false, mylink);
          }
        }
        else
        {
          this.myeditor.execCommand("CreateLink", false, mylink);
        }
      }
    }
    else
    {
      this.AddTag('[url=',']klik hier[/url]');
    }
  };


  this.doImage = function()
  {
    if (this.editorVisible)
    {
      this.ifm.contentWindow.focus();
      myimg = prompt('Voer een URL naar een afbeelding in:', 'http://');

      if ((myimg != null) && (myimg != ""))
      {
        this.myeditor.execCommand('InsertImage', false, myimg);
      }
    }
    else
    {
      this.AddTag('[img]', '[/img]');
    }
  };

  this.insertHtml = function(html)
  {
    this.ifm.contentWindow.focus();
    
    // Indien internet explorer <=9
    if (this.isIE)
    {
      this.ifm.contentWindow.document.selection.createRange().pasteHTML(html);
    }
    else
    {
      // Is dit Internet Explorer 11?
      var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
      if ( isIE11 ) {
        var bbHtml = this.htmlToBBCode(html);
        this.myeditor.execCommand('Paste', false, bbHtml);
        this.SwitchEditor();
        this.SwitchEditor();
      } else {
        this.myeditor.execCommand('InsertHTML', false, html);
      }
    }

    this.autoGrow();
  };
  
  this.htmlToBBCode = function(html)
  {
    html = html.replace(/<pre(.*?)>(.*?)<\/pre>/gmi, "[code]$2[/code]");

    html = html.replace(/<h[1-7](.*?)>(.*?)<\/h[1-7]>/, "\n[h]$2[/h]\n");

    //paragraph handling:
    //- if a paragraph opens on the same line as another one closes, insert an extra blank line
    //- opening tag becomes two line breaks
    //- closing tags are just removed
    // html += html.replace(/<\/p><p/<\/p>\n<p/gi;
    // html += html.replace(/<p[^>]*>/\n\n/gi;
    // html += html.replace(/<\/p>//gi;

    html = html.replace(/<br(.*?)>/gi, "\n\r");
    html = html.replace(/<textarea(.*?)>(.*?)<\/textarea>/gmi, "\[code]$2\[\/code]");
    html = html.replace(/<b>/gi, "[b]");
    html = html.replace(/<i>/gi, "[i]");
    html = html.replace(/<u>/gi, "[u]");
    html = html.replace(/<\/b>/gi, "[/b]");
    html = html.replace(/<\/i>/gi, "[/i]");
    html = html.replace(/<\/u>/gi, "[/u]");
    html = html.replace(/<em>/gi, "[b]");
    html = html.replace(/<\/em>/gi, "[/b]");
    html = html.replace(/<strong>/gi, "[b]");
    html = html.replace(/<\/strong>/gi, "[/b]");
    html = html.replace(/<cite>/gi, "[i]");
    html = html.replace(/<\/cite>/gi, "[/i]");
    html = html.replace(/<font color="(.*?)">(.*?)<\/font>/gmi, "[color=$1]$2[/color]");
    html = html.replace(/<font color=(.*?)>(.*?)<\/font>/gmi, "[color=$1]$2[/color]");
    html = html.replace(/<link(.*?)>/gi, "");
    html = html.replace(/<li(.*?)>(.*?)<\/li>/gi, "[*]$2");
    html = html.replace(/<ul(.*?)>/gi, "[list]");
    html = html.replace(/<\/ul>/gi, "[/list]");
    html = html.replace(/<div>/gi, "\n");
    html = html.replace(/<\/div>/gi, "\n");
    html = html.replace(/<td(.*?)>/gi, " ");
    html = html.replace(/<tr(.*?)>/gi, "\n");

    html = html.replace(/<img(.*?)src="(.*?)"(.*?)>/gi, "[img]$2[/img]");
    html = html.replace(/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/gi, "[url=$2]$4[/url]");

    html = html.replace(/<head>(.*?)<\/head>/gmi, "");
    html = html.replace(/<object>(.*?)<\/object>/gmi, "");
    html = html.replace(/<script(.*?)>(.*?)<\/script>/gmi, "");
    html = html.replace(/<style(.*?)>(.*?)<\/style>/gmi, "");
    html = html.replace(/<title>(.*?)<\/title>/gmi, "");
    html = html.replace(/<!--(.*?)-->/gmi, "\n");

    html = html.replace(/\/\//gi, "/");
    html = html.replace(/http:\//gi, "http://");

    html = html.replace(/<(?:[^>'"]*|(['"]).*?\1)*>/gmi, "");
    html = html.replace(/\r\r/gi, ""); 
    html = html.replace(/\[img]\//gi, "[img]");
    html = html.replace(/\[url=\//gi, "[url=");

    html = html.replace(/(\S)\n/gi, "$1 ");

    return html;
  }

  //textarea-mode functions
  this.MozillaInsertText = function(element, text, pos)
  {
    element.value = element.value.slice(0, pos) + text + element.value.slice(pos);
  };


  this.AddTag = function(t1, t2)
  {
    var element = this.textboxelement;
    if (this.isIE)
    {
      if (document.selection)
      {
        element.focus();

        var txt = element.value;
        var str = document.selection.createRange();

        if (str.text == "")
        {
          str.text = t1 + t2;
        }
        else if (txt.indexOf(str.text) >= 0)
        {
          str.text = t1 + str.text + t2;
        }
        else
        {
          element.value = txt + t1 + t2;
        }

        str.select();
      }
    }
    else if (typeof(element.selectionStart) != 'undefined')
    {
      var sel_start = element.selectionStart;
      var sel_end = element.selectionEnd;
      this.MozillaInsertText(element, t1, sel_start);
      this.MozillaInsertText(element, t2, sel_end + t1.length);
      element.selectionStart = sel_start;
      element.selectionEnd = sel_end + t1.length + t2.length;
      element.focus();
    }
    else
    {
      element.value = element.value + t1 + t2;
    }
  };


  // Escape a string for HTML interpolation.
  this.EscapeHTML = function(string)
  {
    return ('' + string).replace(this.htmlEscaper, function(match) {
      return this.htmlEscapes[match];
    }.bind(this));
  };


  this.initialize(options);
}

