From 95420164ae796977e93715665ccf075aee4cd3c2 Mon Sep 17 00:00:00 2001
From: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date: Fri, 21 Oct 2011 11:49:29 +0200
Subject: [PATCH] replace some css and javascript with compressed ones.

---
 .../erp5_xinha_editor/xinha/Xinha.css.xml     |  480 +-
 .../erp5_xinha_editor/xinha/XinhaCore.js.xml  | 8304 +----------------
 bt5/erp5_xinha_editor/bt/revision             |    2 +-
 3 files changed, 9 insertions(+), 8777 deletions(-)

diff --git a/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/Xinha.css.xml b/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/Xinha.css.xml
index 3b384071f6..aaad548707 100644
--- a/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/Xinha.css.xml
+++ b/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/Xinha.css.xml
@@ -28,484 +28,8 @@
         </item>
         <item>
             <key> <string>raw</string> </key>
-            <value> <string>.htmlarea { background: #fff; }\n
-.htmlarea td { margin:0;padding:0; }\n
-\n
-.htmlarea .toolbarRow {\n
-  width:1px;\n
-}\n
-\n
-.htmlarea .toolbar {\n
-  cursor: default;\n
-  background: ButtonFace;\n
-  padding: 3px;\n
-  border: 1px solid;\n
-  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;\n
-}\n
-.htmlarea .toolbar table { margin: 0; font-family: Tahoma, Verdana,sans-serif; font-size: 11px; }\n
-.htmlarea .toolbar img { border: none; vertical-align: top; }\n
-.htmlarea .toolbar .label { padding: 0 3px; }\n
-\n
-.htmlarea .toolbar .button {\n
-  background: ButtonFace;\n
-  color: ButtonText;\n
-  border: 1px solid ButtonFace;\n
-  padding: 1px;\n
-  margin: 0;\n
-  width: 18px;\n
-  height: 18px;\n
-}\n
-.htmlarea .toolbar a.button:hover {\n
-  border: 1px solid;\n
-  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;\n
-}\n
-.htmlarea .toolbar a.buttonDisabled:hover {\n
-  border-color: ButtonFace;\n
-}\n
-.htmlarea .toolbar .buttonActive,\n
-.htmlarea .toolbar .buttonPressed\n
-{\n
-  padding: 2px 0 0 2px;\n
-  border: 1px solid;\n
-  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;\n
-}\n
-.htmlarea .toolbar .buttonPressed {\n
-  background: ButtonHighlight;\n
-}\n
-.htmlarea .toolbar .indicator {\n
-  padding: 0 3px;\n
-  overflow: hidden;\n
-  width: 20px;\n
-  text-align: center;\n
-  cursor: default;\n
-  border: 1px solid ButtonShadow;\n
-}\n
-\n
-.htmlarea .toolbar .buttonDisabled img {\n
-  filter: gray() alpha(opacity = 25);\n
-  -moz-opacity: 0.25;\n
-  opacity: 0.25;\n
-}\n
-\n
-.htmlarea .toolbar .separator {\n
-  /*position: relative;*/\n
-  margin:0 3px;\n
-  border-left: 1px solid ButtonShadow;\n
-  border-right: 1px solid ButtonHighlight;\n
-  width: 0;\n
-  height: 18px;\n
-  padding: 0;\n
-}\n
-\n
-.htmlarea .toolbar .space { width: 5px; }\n
-\n
-.htmlarea .toolbar select, .htmlarea .toolbar option { font: 11px Tahoma,Verdana,sans-serif;}\n
-\n
-.htmlarea .toolbar select,\n
-.htmlarea .toolbar select:hover,\n
-.htmlarea .toolbar select:active { \n
-  position:relative;\n
-  top:-2px;\n
-  margin-bottom:-2px;\n
-  color: ButtonText;\n
-}\n
-\n
-.htmlarea iframe.xinha_iframe, .htmlarea textarea.xinha_textarea\n
-{\n
-  border: none; /*1px solid;*/\n
-}\n
-\n
-.htmlarea .statusBar {\n
-  border: 1px solid;\n
-  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;\n
-  padding: 2px 4px;\n
-  background-color: ButtonFace;\n
-  color: ButtonText;\n
-  font: 11px Tahoma,Verdana,sans-serif;\n
-  height:16px;\n
-  overflow: hidden;\n
-}\n
-\n
-.htmlarea .statusBar .statusBarTree a {\n
-  padding: 2px 5px;\n
-  color: #00f;\n
-}\n
-\n
-.htmlarea .statusBar .statusBarTree a:visited { color: #00f; }\n
-.htmlarea .statusBar .statusBarTree a:hover {\n
-  background-color: Highlight;\n
-  color: HighlightText;\n
-  padding: 1px 4px;\n
-  border: 1px solid HighlightText;\n
-}\n
-\n
-.statusBarWidgetContainer {\n
-  background-color: ButtonFace;\n
-}\n
-\n
-/* popup dialogs */\n
-\n
-.dialog {\n
-  color: ButtonText;\n
-  background: ButtonFace; \n
-  border: 1px outset; \n
-  border-color: WindowFrame;\n
-}\n
-div.dialog {\n
-  padding-bottom:10px;\n
-  border-radius: 8px 8px 0 0;\n
-  -moz-border-radius: 8px 8px 0 0;\n
-  -webkit-border-top-left-radius: 8px;\n
-  -webkit-border-top-right-radius: 8px;\n
-  \n
-  box-shadow: 9px 9px 10px #444;\n
-  -moz-box-shadow: 9px 9px 10px #444;\n
-  -webkit-box-shadow: 9px 9px 10px #444;\n
-}\n
-div.dialog.modeless {\n
-  box-shadow: 4px 4px 5px #888;\n
-  -moz-box-shadow: 4px 4px 5px #888;\n
-  -webkit-box-shadow: 4px 4px 5px #888;\n
-}\n
-div.dialog.chrome {\n
-  -webkit-box-shadow: none !IMPORTANT;\n
-}\n
-.panels div.dialog.panel {\n
-  border-radius:0;\n
-  -moz-border-radius: 0;\n
-  -webkit-border-radius:0;\n
-  \n
-  box-shadow: none;\n
-  -moz-box-shadow: none;\n
-  -webkit-box-shadow: none;\n
-}\n
-.xinha_dialog_background {\n
-  filter: alpha(opacity=0);\n
-  -moz-opacity: 0;\n
-  opacity: 0;\n
-  border:none;\n
-}\n
-.xinha_dialog_background_modal_greyout {\n
-  background-color:#666;\n
-  filter: alpha(opacity=70) !IMPORTANT;\n
-  -moz-opacity: 0.7;\n
-  opacity: 0.7;\n
-}\n
-.xinha_dialog_background_modal {\n
-  filter: alpha(opacity=0) !IMPORTANT;\n
-  -moz-opacity: 0;\n
-  opacity: 0;\n
-  border:none;\n
-}\n
-body.xinha_dialog_background_modal_greyout {\n
-  filter: alpha(opacity=100) !IMPORTANT;\n
-}\n
-body.xinha_dialog_background_modal {\n
-  filter: alpha(opacity=0);\n
-}\n
-.dialog .content { padding: 2px; }\n
-\n
-.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table {\n
-  font: 11px Tahoma,Verdana,sans-serif;\n
-}\n
-\n
-.dialog table { border-collapse: collapse; }\n
-\n
-.dialog .title, .dialog h1\n
-{\n
-  background: ActiveCaption;\n
-  color: CaptionText;\n
-  border-bottom: 1px solid #000;\n
-  padding: 1px 0 2px 5px;\n
-  font-size: 12px;\n
-  font-weight: bold;\n
-  cursor: default;\n
-  letter-spacing: 0.01em;\n
-}\n
-.dialog h1 { \n
-  padding-left:22px;\n
-  margin:0;\n
-  border-radius: 8px 8px 0 0;\n
-  -moz-border-radius: 8px 8px 0 0;\n
-  -webkit-border-top-left-radius: 8px;\n
-  -webkit-border-top-right-radius: 8px;\n
-}\n
-.panels .dialog.panel h1 { \n
-  -moz-border-radius: 0;\n
-  -webkit-border-radius:0;\n
-}\n
-\n
-.dialog .title .button {\n
-  float: right;\n
-  border: 1px solid #66a;\n
-  padding: 0 1px 0 2px;\n
-  margin-right: 1px;\n
-  color: #fff;\n
-  text-align: center;\n
-}\n
-\n
-.dialog .title .button-hilite { border-color: #88f; background: #44c; }\n
-\n
-.dialog button {\n
-  width: 5.5em;\n
-  padding: 0;\n
-}\n
-.dialog .closeButton {\n
-  padding: 0;\n
-  cursor: default;\n
-  border: 1px solid;\n
-  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;\n
-  height : 11px;\n
-  width : 11px;\n
-  vertical-align : top;\n
-  position : absolute;\n
-  top : 3px;\n
-  right : 2px;\n
-  background-color: ButtonFace;\n
-  color: ButtonText;\n
-  font-size: 13px;\n
-  font-family: Tahoma,Verdana,sans-serif;\n
-  text-align:center;\n
-  letter-spacing:0;\n
-  overflow:hidden;\n
-}\n
-.dialog .buttonColor {\n
-  width :1em;\n
-  padding: 1px;\n
-  cursor: default;\n
-  border: 1px solid;\n
-  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;\n
-}\n
-\n
-.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor {\n
-  height: 0.6em;\n
-  border: 1px solid;\n
-  padding: 0 1em;\n
-  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;\n
-}\n
-\n
-.dialog .buttonClick {\n
-  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;\n
-}\n
-.dialog .buttonColor-hilite {\n
-   border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;\n
-}\n
-\n
-.dialog .buttonColor .nocolor { padding: 0; }\n
-.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; }\n
-\n
-.dialog .label { text-align: right; width: 6em; }\n
-.dialog .value input { width: 100%; }\n
-\n
-.dialog legend { font-weight: bold; }\n
-.dialog fieldset table { margin: 2px 0; }\n
- \n
-.dialog  .buttons {\n
-\n
-      padding: 1em; \n
-      text-align: center;\n
-}\n
-.dialog .resizeHandle {\n
-    -moz-appearance : resizer;\n
-    width: 12px;\n
-    height: 12px;\n
-    border-bottom: 2px solid #000;\n
-    border-right: 2px solid #000;\n
-    cursor : se-resize;\n
-}\n
-.popupwin {\n
-  padding: 0;\n
-  margin: 0;\n
-}\n
-\n
-.popupwin .title {\n
-  background: #fff;\n
-  color: #000;\n
-  font-weight: bold;\n
-  font-size: 120%;\n
-  padding: 3px 10px;\n
-  margin-bottom: 10px;\n
-  border-bottom: 1px solid black;\n
-  letter-spacing: 2px;\n
-}\n
-\n
-form { margin: 0; border: none; }\n
-\n
-\n
-/** Panels **/\n
-.htmlarea .panels_top\n
-{\n
-  border-bottom : 1px solid;\n
-  border-color: ButtonShadow;\n
-}\n
-\n
-.htmlarea .panels_right\n
-{\n
-  border-left : 1px solid;\n
-  border-color: ButtonShadow;\n
-}\n
-\n
-.htmlarea .panels_left\n
-{\n
-  border-right : 1px solid;\n
-  border-color: ButtonShadow;\n
-}\n
-\n
-.htmlarea .panels_bottom\n
-{\n
-  border-top : 1px solid;\n
-  border-color: ButtonShadow;\n
-}\n
-\n
-.htmlarea .panel h1 {\n
-  clear:left;\n
-  font-size:0.9em;\n
-}\n
-\n
-.htmlarea .panel { \n
-  overflow:hidden; \n
-  background-color:white;\n
-  padding-bottom:0 !IMPORTANT;\n
-  border: none !IMPORTANT;\n
-}\n
-.htmlarea .panels_left  .panel { border-right:none; border-left:none; }\n
-.htmlarea .panels_left  h1     { border-right:none;  }\n
-.htmlarea .panels_right .panel { border-right:none; border-left:none; }\n
-.htmlarea .panels_left  h1     { border-left:none;  }\n
-.htmlarea { border: 1px solid black; }\n
-\n
-.loading\n
-{\n
-  font-family:sans-serif;\n
-  position:absolute;\n
-  z-index:998;\n
-  text-align:center;\n
-  width:212px;\n
-  padding: 55px 0 5px 0;\n
-  border:2px solid #ccc;\n
-  /* border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;*/\n
-  background: url(images/xinha_logo.gif) no-repeat #fff center 5px;\n
-}\n
-.loading_main\n
-{\n
-  font-size:11px;\n
-  color:#000;\n
- \n
-}\n
-.loading_sub\n
-{\n
-  font-size:9px;\n
-  color:#666;\n
-  text-align:center;\n
-}\n
-/* Classes for filemanager styles in a dialog. */\n
-.dialog a img\n
-{\n
-border: 0 none transparent;\n
-}\n
-\n
-.dialog fieldset.collapsed {\n
-border: 0 none transparent;\n
-}\n
-\n
-.dialog fieldset.collapsed form {\n
-display: none;\n
-}\n
-\n
-.hidden\n
-{\n
-display: none;\n
-}\n
-\n
-.placesmanager\n
-{\n
-  width: 95%;\n
-  overflow: auto;\n
-}\n
-\n
-.filemanager\n
-{\n
-  width: 95%;\n
-  height: 200px;\n
-  overflow: auto;\n
-  background-color: #fff;\n
-}\n
-.filemanager div.file\n
-{\n
-  min-width: 80px;\n
-  height: 100px;\n
-  position: relative;\n
-  float: left;\n
-  border: 1px outset #666;\n
-  margin: 4px;\n
-}\n
-.placesmanager div.file\n
-{\n
-  min-width: 60px;\n
-  height: 70px;\n
-  position: relative;\n
-  float: left;\n
-  border: 1px outset #666;\n
-  margin: 4px;\n
-}\n
-.filemanager div.file:hover,\n
-.placesmanager div.file:hover\n
-{\n
-  border: 1px solid #333;\n
-  background: #fffff3;\n
-}\n
-\n
-.filemanager div.selected,\n
-.filemanager div.selected:hover,\n
-.placesmanager div.selected,\n
-.placesmanager div.selected:hover\n
-{\n
-  background: #ffffda;\n
-  border: 1px solid #000;\n
-}\n
-.filemanager .filename {\n
-\tmargin: 0.5em;\n
-\tcolor: #222;\n
-}\n
-.filemanager div.selected .filename {\n
-  color: #000;\n
-}\n
-.filemanager img.thumb\n
-{\n
-  width: 50px;\n
-  height: 50px;\n
-  position: absolute;\n
-  top: 50%;\n
-  left: 50%;\n
-  margin: -25px 0 0 -25px;\n
-  border: 1px solid black;\n
-}\n
-.filemanager img.icon\n
-{\n
-  width: 32px;\n
-  height: 32px;\n
-  position: absolute;\n
-  top: 50%;\n
-  left: 50%;\n
-  margin: -16px 0 0 -16px;\n
-}\n
-.filemanager img.action\n
-{\n
-  width: 15px;\n
-  height: 15px;\n
-  position: absolute;\n
-}\n
-.filemanager img.delete\n
-{\n
-  bottom: 3px;\n
-  left: 20px;\n
-}\n
-.filemanager img.copy\n
-{\n
-  bottom: 3px;\n
-  left: 3px;\n
-}\n
-</string> </value>
+            <value> <string>/* This compressed file is part of Xinha. For uncompressed sources, forum, and bug reports, go to xinha.org */\n
+.htmlarea{background:#fff;}.htmlarea td{margin:0;padding:0;}.htmlarea .toolbarRow{width:1px;}.htmlarea .toolbar{cursor:default;background:ButtonFace;padding:3px;border:1px solid;border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;}.htmlarea .toolbar table{margin:0;font-family:Tahoma,Verdana,sans-serif;font-size:11px;}.htmlarea .toolbar img{border:none;vertical-align:top;}.htmlarea .toolbar .label{padding:0 3px;}.htmlarea .toolbar .button{background:ButtonFace;color:ButtonText;border:1px solid ButtonFace;padding:1px;margin:0;width:18px;height:18px;}.htmlarea .toolbar a.button:hover{border:1px solid;border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;}.htmlarea .toolbar a.buttonDisabled:hover{border-color:ButtonFace;}.htmlarea .toolbar .buttonActive,.htmlarea .toolbar .buttonPressed{padding:2px 0 0 2px;border:1px solid;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;}.htmlarea .toolbar .buttonPressed{background:ButtonHighlight;}.htmlarea .toolbar .indicator{padding:0 3px;overflow:hidden;width:20px;text-align:center;cursor:default;border:1px solid ButtonShadow;}.htmlarea .toolbar .buttonDisabled img{filter:gray() alpha(opacity = 25);-moz-opacity:.25;opacity:.25;}.htmlarea .toolbar .separator{margin:0 3px;border-left:1px solid ButtonShadow;border-right:1px solid ButtonHighlight;width:0;height:18px;padding:0;}.htmlarea .toolbar .space{width:5px;}.htmlarea .toolbar select,.htmlarea .toolbar option{font:11px Tahoma,Verdana,sans-serif;}.htmlarea .toolbar select,.htmlarea .toolbar select:hover,.htmlarea .toolbar select:active{position:relative;top:-2px;margin-bottom:-2px;color:ButtonText;}.htmlarea iframe.xinha_iframe,.htmlarea textarea.xinha_textarea{border:none;}.htmlarea .statusBar{border:1px solid;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;padding:2px 4px;background-color:ButtonFace;color:ButtonText;font:11px Tahoma,Verdana,sans-serif;height:16px;overflow:hidden;}.htmlarea .statusBar .statusBarTree a{padding:2px 5px;color:#00f;}.htmlarea .statusBar .statusBarTree a:visited{color:#00f;}.htmlarea .statusBar .statusBarTree a:hover{background-color:Highlight;color:HighlightText;padding:1px 4px;border:1px solid HighlightText;}.statusBarWidgetContainer{background-color:ButtonFace;}.dialog{color:ButtonText;background:ButtonFace;border:1px outset;border-color:WindowFrame;}div.dialog{padding-bottom:10px;border-radius:8px 8px 0 0;-moz-border-radius:8px 8px 0 0;-webkit-border-top-left-radius:8px;-webkit-border-top-right-radius:8px;box-shadow:9px 9px 10px #444;-moz-box-shadow:9px 9px 10px #444;-webkit-box-shadow:9px 9px 10px #444;}div.dialog.modeless{box-shadow:4px 4px 5px #888;-moz-box-shadow:4px 4px 5px #888;-webkit-box-shadow:4px 4px 5px #888;}div.dialog.chrome{-webkit-box-shadow:none!IMPORTANT;}.panels div.dialog.panel{border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;box-shadow:none;-moz-box-shadow:none;-webkit-box-shadow:none;}.xinha_dialog_background{filter:alpha(opacity=0);-moz-opacity:0;opacity:0;border:none;}.xinha_dialog_background_modal_greyout{background-color:#666;filter:alpha(opacity=70)!IMPORTANT;-moz-opacity:.7;opacity:.7;}.xinha_dialog_background_modal{filter:alpha(opacity=0)!IMPORTANT;-moz-opacity:0;opacity:0;border:none;}body.xinha_dialog_background_modal_greyout{filter:alpha(opacity=100)!IMPORTANT;}body.xinha_dialog_background_modal{filter:alpha(opacity=0);}.dialog .content{padding:2px;}.dialog,.dialog button,.dialog input,.dialog select,.dialog textarea,.dialog table{font:11px Tahoma,Verdana,sans-serif;}.dialog table{border-collapse:collapse;}.dialog .title,.dialog h1{background:ActiveCaption;color:CaptionText;border-bottom:1px solid #000;padding:1px 0 2px 5px;font-size:12px;font-weight:bold;cursor:default;letter-spacing:.01em;}.dialog h1{padding-left:22px;margin:0;border-radius:8px 8px 0 0;-moz-border-radius:8px 8px 0 0;-webkit-border-top-left-radius:8px;-webkit-border-top-right-radius:8px;}.panels .dialog.panel h1{-moz-border-radius:0;-webkit-border-radius:0;}.dialog .title .button{float:right;border:1px solid #66a;padding:0 1px 0 2px;margin-right:1px;color:#fff;text-align:center;}.dialog .title .button-hilite{border-color:#88f;background:#44c;}.dialog button{width:5.5em;padding:0;}.dialog .closeButton{padding:0;cursor:default;border:1px solid;border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;height:11px;width:11px;vertical-align:top;position:absolute;top:3px;right:2px;background-color:ButtonFace;color:ButtonText;font-size:13px;font-family:Tahoma,Verdana,sans-serif;text-align:center;letter-spacing:0;overflow:hidden;}.dialog .buttonColor{width:1em;padding:1px;cursor:default;border:1px solid;border-color:ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;}.dialog .buttonColor .chooser,.dialog .buttonColor .nocolor{height:.6em;border:1px solid;padding:0 1em;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;}.dialog .buttonClick{border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;}.dialog .buttonColor-hilite{border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;}.dialog .buttonColor .nocolor{padding:0;}.dialog .buttonColor .nocolor-hilite{background-color:#fff;color:#f00;}.dialog .label{text-align:right;width:6em;}.dialog .value input{width:100%;}.dialog legend{font-weight:bold;}.dialog fieldset table{margin:2px 0;}.dialog .buttons{padding:1em;text-align:center;}.dialog .resizeHandle{-moz-appearance:resizer;width:12px;height:12px;border-bottom:2px solid #000;border-right:2px solid #000;cursor:se-resize;}.popupwin{padding:0;margin:0;}.popupwin .title{background:#fff;color:#000;font-weight:bold;font-size:120%;padding:3px 10px;margin-bottom:10px;border-bottom:1px solid black;letter-spacing:2px;}form{margin:0;border:none;}.htmlarea .panels_top{border-bottom:1px solid;border-color:ButtonShadow;}.htmlarea .panels_right{border-left:1px solid;border-color:ButtonShadow;}.htmlarea .panels_left{border-right:1px solid;border-color:ButtonShadow;}.htmlarea .panels_bottom{border-top:1px solid;border-color:ButtonShadow;}.htmlarea .panel h1{clear:left;font-size:.9em;}.htmlarea .panel{overflow:hidden;background-color:white;padding-bottom:0!IMPORTANT;border:none!IMPORTANT;}.htmlarea .panels_left .panel{border-right:none;border-left:none;}.htmlarea .panels_left h1{border-right:none;}.htmlarea .panels_right .panel{border-right:none;border-left:none;}.htmlarea .panels_left h1{border-left:none;}.htmlarea{border:1px solid black;}.loading{font-family:sans-serif;position:absolute;z-index:998;text-align:center;width:212px;padding:55px 0 5px 0;border:2px solid #ccc;background:url(images/xinha_logo.gif) no-repeat #fff center 5px;}.loading_main{font-size:11px;color:#000;}.loading_sub{font-size:9px;color:#666;text-align:center;}.dialog a img{border:0 none transparent;}.dialog fieldset.collapsed{border:0 none transparent;}.dialog fieldset.collapsed form{display:none;}.hidden{display:none;}.placesmanager{width:95%;overflow:auto;}.filemanager{width:95%;height:200px;overflow:auto;background-color:#fff;}.filemanager div.file{min-width:80px;height:100px;position:relative;float:left;border:1px outset #666;margin:4px;}.placesmanager div.file{min-width:60px;height:70px;position:relative;float:left;border:1px outset #666;margin:4px;}.filemanager div.file:hover,.placesmanager div.file:hover{border:1px solid #333;background:#fffff3;}.filemanager div.selected,.filemanager div.selected:hover,.placesmanager div.selected,.placesmanager div.selected:hover{background:#ffffda;border:1px solid #000;}.filemanager .filename{margin:.5em;color:#222;}.filemanager div.selected .filename{color:#000;}.filemanager img.thumb{width:50px;height:50px;position:absolute;top:50%;left:50%;margin:-25px 0 0 -25px;border:1px solid black;}.filemanager img.icon{width:32px;height:32px;position:absolute;top:50%;left:50%;margin:-16px 0 0 -16px;}.filemanager img.action{width:15px;height:15px;position:absolute;}.filemanager img.delete{bottom:3px;left:20px;}.filemanager img.copy{bottom:3px;left:3px;}</string> </value>
         </item>
         <item>
             <key> <string>title</string> </key>
diff --git a/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/XinhaCore.js.xml b/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/XinhaCore.js.xml
index b5a057c25d..d949da1a0a 100644
--- a/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/XinhaCore.js.xml
+++ b/bt5/erp5_xinha_editor/SkinTemplateItem/portal_skins/erp5_xinha_editor/xinha/XinhaCore.js.xml
@@ -30,8315 +30,23 @@
             <key> <string>raw</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
- \n
-  /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--\n
+/* This compressed file is part of Xinha. For uncompressed sources, forum, and bug reports, go to xinha.org */\n
+/* The URL of the most recent uncompressed version of this file is http://svn.xinha.org/trunk/XinhaCore.js */\n
+  /*--------------------------------------------------------------------------\n
     --  Xinha (is not htmlArea) - http://xinha.org\n
     --\n
     --  Use of Xinha is granted by the terms of the htmlArea License (based on\n
     --  BSD license)  please read license.txt in this package for details.\n
     --\n
-    --  Copyright (c) 2005-2008 Xinha Developer Team and contributors\n
+    --  Copyright (c) 2005-2010 Xinha Developer Team and contributors\n
     --  \n
     --  Xinha was originally based on work by Mihai Bazon which is:\n
     --      Copyright (c) 2003-2004 dynarch.com.\n
     --      Copyright (c) 2002-2003 interactivetools.com, inc.\n
     --      This copyright notice MUST stay intact for use.\n
-    --\n
-    --  Developers - Coding Style: \n
-    --         Before you are going to work on Xinha code, please see http://trac.xinha.org/wiki/Documentation/StyleGuide\n
-    --\n
-    --  $HeadURL: http://svn.xinha.org/trunk/XinhaCore.js $\n
-    --  $LastChangedDate: 2010-05-12 09:40:06 +1200 (Wed, 12 May 2010) $\n
-    --  $LastChangedRevision: 1263 $\n
-    --  $LastChangedBy: gogo $\n
-    --------------------------------------------------------------------------*/\n
-/*jslint regexp: false, rhino: false, browser: true, bitwise: false, forin: true, adsafe: false, evil: true, nomen: false, \n
-glovar: false, debug: false, eqeqeq: false, passfail: false, sidebar: false, laxbreak: false, on: false, cap: true, \n
-white: false, widget: false, undef: true, plusplus: false*/\n
-/*global  Dialog , _editor_css , _editor_icons, _editor_lang , _editor_skin , _editor_url, dumpValues, ActiveXObject, HTMLArea, _editor_lcbackend*/\n
-\n
-/** Information about the Xinha version \n
- * @type Object\n
- */\n
-Xinha.version =\n
-{\n
-  \'Release\'   : \'Trunk\',\n
-  \'Head\'      : \'$HeadURL: http://svn.xinha.org/trunk/XinhaCore.js $\'.replace(/^[^:]*:\\s*(.*)\\s*\\$$/, \'$1\'),\n
-  \'Date\'      : \'$LastChangedDate: 2010-05-12 09:40:06 +1200 (Wed, 12 May 2010) $\'.replace(/^[^:]*:\\s*([0-9\\-]*) ([0-9:]*) ([+0-9]*) \\((.*)\\)\\s*\\$/, \'$4 $2 $3\'),\n
-  \'Revision\'  : \'$LastChangedRevision: 1263 $\'.replace(/^[^:]*:\\s*(.*)\\s*\\$$/, \'$1\'),\n
-  \'RevisionBy\': \'$LastChangedBy: gogo $\'.replace(/^[^:]*:\\s*(.*)\\s*\\$$/, \'$1\')\n
-};\n
-\n
-//must be here. it is called while converting _editor_url to absolute\n
-Xinha._resolveRelativeUrl = function( base, url )\n
-{\n
-  if(url.match(/^([^:]+\\:)?\\/\\//))\n
-  {\n
-    return url;\n
-  }\n
-  else\n
-  {\n
-    var b = base.split("/");\n
-    if(b[b.length - 1] === "")\n
-    {\n
-      b.pop();\n
-    }\n
-    var p = url.split("/");\n
-    if(p[0] == ".")\n
-    {\n
-      p.shift();\n
-    }\n
-    while(p[0] == "..")\n
-    {\n
-      b.pop();\n
-      p.shift();\n
-    }\n
-    return b.join("/") + "/" + p.join("/");\n
-  }\n
-};\n
-\n
-if ( typeof _editor_url == "string" )\n
-{\n
-  // Leave exactly one backslash at the end of _editor_url\n
-  _editor_url = _editor_url.replace(/\\x2f*$/, \'/\');\n
-  \n
-  // convert _editor_url to absolute\n
-  if(!_editor_url.match(/^([^:]+\\:)?\\//))\n
-  {\n
-    (function()\n
-    {\n
-      var tmpPath = window.location.toString().replace(/\\?.*$/,\'\').split("/");\n
-      tmpPath.pop();\n
-      _editor_url = Xinha._resolveRelativeUrl(tmpPath.join("/"), _editor_url);\n
-    })();\n
-  }\n
-}\n
-else\n
-{\n
-  alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in \'/xinha/\', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we\'ll probably fail.");\n
-  _editor_url = \'\';\n
-}\n
-\n
-// make sure we have a language\n
-if ( typeof _editor_lang == "string" )\n
-{\n
-  _editor_lang = _editor_lang.toLowerCase();\n
-}\n
-else\n
-{\n
-  _editor_lang = "en";\n
-}\n
-\n
-// skin stylesheet to load\n
-if ( typeof _editor_skin !== "string" )\n
-{\n
-  _editor_skin = "";\n
-}\n
-\n
-if ( typeof _editor_icons !== "string" )\n
-{\n
-  _editor_icons = "";\n
-}\n
-/**\n
-* The list of Xinha editors on the page. May be multiple editors.\n
-* You can access each editor object through this global variable.\n
-*\n
-* Example:<br />\n
-* <code>\n
-*\tvar html = __xinhas[0].getEditorContent(); // gives you the HTML of the first editor in the page\n
-* </code>\n
-*/\n
-var __xinhas = [];\n
-\n
-// browser identification\n
-/** Cache the user agent for the following checks\n
- * @type String\n
- * @private\n
- */\n
-Xinha.agt       = navigator.userAgent.toLowerCase();\n
-/** Browser is Microsoft Internet Explorer\n
- * @type Boolean \n
- */\n
-Xinha.is_ie    = ((Xinha.agt.indexOf("msie") != -1) && (Xinha.agt.indexOf("opera") == -1));\n
-/** Version Number, if browser is Microsoft Internet Explorer\n
- * @type Float \n
- */\n
-Xinha.ie_version= parseFloat(Xinha.agt.substring(Xinha.agt.indexOf("msie")+5));\n
-/** Browser is Opera\n
- * @type Boolean \n
- */\n
-Xinha.is_opera  = (Xinha.agt.indexOf("opera") != -1);\n
-/** Version Number, if browser is Opera \n
-  * @type Float \n
-  */\n
-if(Xinha.is_opera && Xinha.agt.match(/opera[\\/ ]([0-9.]+)/))\n
-{\n
-  Xinha.opera_version = parseFloat(RegExp.$1);\n
-}\n
-else\n
-{\n
-  Xinha.opera_version = 0;\n
-}\n
-/** Browserengine is KHTML (Konqueror, Safari)\n
- * @type Boolean \n
- */\n
-Xinha.is_khtml  = (Xinha.agt.indexOf("khtml") != -1);\n
-/** Browser is WebKit\n
- * @type Boolean \n
- */\n
-Xinha.is_webkit  = (Xinha.agt.indexOf("applewebkit") != -1);\n
-/** Webkit build number\n
- * @type Integer\n
- */\n
-Xinha.webkit_version = parseInt(navigator.appVersion.replace(/.*?AppleWebKit\\/([\\d]).*?/,\'$1\'), 10);\n
-\n
-/** Browser is Safari\n
- * @type Boolean \n
- */\n
-Xinha.is_safari  = (Xinha.agt.indexOf("safari") != -1);\n
-\n
-/** Browser is Google Chrome\n
- * @type Boolean \n
- */\n
-Xinha.is_chrome = (Xinha.agt.indexOf("chrome") != -1);\n
-\n
-/** OS is MacOS\n
- * @type Boolean \n
- */\n
-Xinha.is_mac\t   = (Xinha.agt.indexOf("mac") != -1);\n
-/** Browser is Microsoft Internet Explorer Mac\n
- * @type Boolean \n
- */\n
-Xinha.is_mac_ie = (Xinha.is_ie && Xinha.is_mac);\n
-/** Browser is Microsoft Internet Explorer Windows\n
- * @type Boolean \n
- */\n
-Xinha.is_win_ie = (Xinha.is_ie && !Xinha.is_mac);\n
-/** Browser engine is Gecko (Mozilla), applies also to Safari and Opera which work\n
- *  largely similar.\n
- *@type Boolean \n
- */\n
-Xinha.is_gecko  = (navigator.product == "Gecko") || Xinha.is_opera;\n
-/** Browser engine is really Gecko, i.e. Browser is Firefox (or Netscape, SeaMonkey, Flock, Songbird, Beonex, K-Meleon, Camino, Galeon, Kazehakase, Skipstone, or whatever derivate might exist out there...)\n
- * @type Boolean \n
- */\n
-Xinha.is_real_gecko = (navigator.product == "Gecko" && !Xinha.is_webkit);\n
-\n
-/** Gecko version lower than 1.9\n
- * @type Boolean \n
- */\n
-Xinha.is_ff2 = Xinha.is_real_gecko && parseInt(navigator.productSub.substr(0,10), 10) < 20071210;\n
-\n
-/** File is opened locally opened ("file://" protocol)\n
- * @type Boolean\n
- * @private\n
- */\n
-Xinha.isRunLocally = document.URL.toLowerCase().search(/^file:/) != -1;\n
-/** Editing is enabled by document.designMode (Gecko, Opera), as opposed to contenteditable (IE)\n
- * @type Boolean\n
- * @private\n
- */\n
-Xinha.is_designMode = (typeof document.designMode != \'undefined\' && !Xinha.is_ie); // IE has designMode, but we\'re not using it\n
-\n
-/** Check if Xinha can run in the used browser, otherwise the textarea will be remain unchanged\n
- * @type Boolean\n
- * @private\n
- */\n
-Xinha.checkSupportedBrowser = function()\n
-{\n
-  return Xinha.is_real_gecko || (Xinha.is_opera && Xinha.opera_version >= 9.2) || Xinha.ie_version >= 5.5 || Xinha.webkit_version >= 522;\n
-};\n
-/** Cache result of checking for browser support\n
- * @type Boolean\n
- * @private\n
- */\n
-Xinha.isSupportedBrowser = Xinha.checkSupportedBrowser();\n
-\n
-if ( Xinha.isRunLocally && Xinha.isSupportedBrowser)\n
-{\n
-  alert(\'Xinha *must* be installed on a web server. Locally opened files (those that use the "file://" protocol) cannot properly function. Xinha will try to initialize but may not be correctly loaded.\');\n
-}\n
-\n
-/** Creates a new Xinha object\n
- * @version $Rev: 1263 $ $LastChangedDate: 2010-05-12 09:40:06 +1200 (Wed, 12 May 2010) $\n
- * @constructor\n
- * @param {String|DomNode}   textarea the textarea to replace; can be either only the id or the DOM object as returned by document.getElementById()\n
- * @param {Xinha.Config} config optional if no Xinha.Config object is passed, the default config is used\n
- */\n
-function Xinha(textarea, config)\n
-{ \n
-  if ( !Xinha.isSupportedBrowser )\n
-  {\n
-    return;\n
-  }\n
-  \n
-  if ( !textarea )\n
-  {\n
-    throw new Error ("Tried to create Xinha without textarea specified.");\n
-  }\n
-\n
-  if ( typeof config == "undefined" )\n
-  {\n
-\t\t/** The configuration used in the editor\n
-\t\t * @type Xinha.Config\n
-\t\t */\n
-    this.config = new Xinha.Config();\n
-  }\n
-  else\n
-  {\n
-    this.config = config;\n
-  }\n
-\n
-  if ( typeof textarea != \'object\' )\n
-  {\n
-    textarea = Xinha.getElementById(\'textarea\', textarea);\n
-  }\n
-  /** This property references the original textarea, which is at the same time the editor in text mode\n
-   * @type DomNode textarea\n
-   */\n
-  this._textArea = textarea;\n
-  this._textArea.spellcheck = false;\n
-  Xinha.freeLater(this, \'_textArea\');\n
-  \n
-  // \n
-  /** Before we modify anything, get the initial textarea size\n
-   * @private\n
-   * @type Object w,h \n
-   */\n
-  this._initial_ta_size =\n
-  {\n
-    w: textarea.style.width  ? textarea.style.width  : ( textarea.offsetWidth  ? ( textarea.offsetWidth  + \'px\' ) : ( textarea.cols + \'em\') ),\n
-    h: textarea.style.height ? textarea.style.height : ( textarea.offsetHeight ? ( textarea.offsetHeight + \'px\' ) : ( textarea.rows + \'em\') )\n
-  };\n
-\n
-  if ( document.getElementById("loading_" + textarea.id) || this.config.showLoading )\n
-  {\n
-    if (!document.getElementById("loading_" + textarea.id))\n
-    {\n
-      Xinha.createLoadingMessage(textarea);\n
-    }\n
-    this.setLoadingMessage(Xinha._lc("Constructing object"));\n
-  }\n
-\n
-  /** the current editing mode\n
-  * @private \n
-  * @type string "wysiwyg"|"text"\n
-  */\n
-  this._editMode = "wysiwyg";\n
-  /** this object holds the plugins used in the editor\n
-  * @private \n
-  * @type Object\n
-  */\n
-  this.plugins = {};\n
-  /** periodically updates the toolbar\n
-  * @private \n
-  * @type timeout\n
-  */\n
-  this._timerToolbar = null;\n
-  /** periodically takes a snapshot of the current editor content\n
-  * @private \n
-  * @type timeout\n
-  */\n
-  this._timerUndo = null;\n
-  /** holds the undo snapshots\n
-  * @private \n
-  * @type Array\n
-  */\n
-  this._undoQueue = [this.config.undoSteps];\n
-  /** the current position in the undo queue \n
-  * @private \n
-  * @type integer\n
-  */\n
-  this._undoPos = -1;\n
-  /** use our own undo implementation (true) or the browser\'s (false) \n
-  * @private \n
-  * @type Boolean\n
-  */\n
-  this._customUndo = true;\n
-  /** the document object of the page Xinha is embedded in\n
-  * @private \n
-  * @type document\n
-  */\n
-  this._mdoc = document; // cache the document, we need it in plugins\n
-  /** doctype of the edited document (fullpage mode)\n
-  * @private \n
-  * @type string\n
-  */\n
-  this.doctype = \'\';\n
-  /** running number that identifies the current editor\n
-  * @public \n
-  * @type integer\n
-  */\n
-  this.__htmlarea_id_num = __xinhas.length;\n
-  __xinhas[this.__htmlarea_id_num] = this;\n
-\t\n
-  /** holds the events for use with the notifyOn/notifyOf system\n
-  * @private \n
-  * @type Object\n
-  */\n
-  this._notifyListeners = {};\n
-\n
-  // Panels\n
-  var panels = \n
-  {\n
-    right:\n
-    {\n
-      on: true,\n
-      container: document.createElement(\'td\'),\n
-      panels: []\n
-    },\n
-    left:\n
-    {\n
-      on: true,\n
-      container: document.createElement(\'td\'),\n
-      panels: []\n
-    },\n
-    top:\n
-    {\n
-      on: true,\n
-      container: document.createElement(\'td\'),\n
-      panels: []\n
-    },\n
-    bottom:\n
-    {\n
-      on: true,\n
-      container: document.createElement(\'td\'),\n
-      panels: []\n
-    }\n
-  };\n
-\n
-  for ( var i in panels )\n
-  {\n
-    if(!panels[i].container) { continue; } // prevent iterating over wrong type\n
-    panels[i].div = panels[i].container; // legacy\n
-    panels[i].container.className = \'panels panels_\' + i;\n
-    Xinha.freeLater(panels[i], \'container\');\n
-    Xinha.freeLater(panels[i], \'div\');\n
-  }\n
-  /** holds the panels\n
-  * @private \n
-  * @type Array\n
-  */\n
-  // finally store the variable\n
-  this._panels = panels;\n
-\t\n
-  // Init some properties that are defined later\n
-  /** The statusbar container\n
-   * @type DomNode statusbar div\n
-   */\n
-  this._statusBar = null;\n
-  /** The DOM path that is shown in the statusbar in wysiwyg mode\n
-   * @private\n
-   * @type DomNode\n
-   */\n
-  this._statusBarTree = null;\n
-  /** The message that is shown in the statusbar in text mode\n
-   * @private\n
-   * @type DomNode\n
-   */\n
-  this._statusBarTextMode = null;\n
-  /** Holds the items of the DOM path that is shown in the statusbar in wysiwyg mode\n
-   * @private\n
-   * @type Array tag names\n
-   */\n
-  this._statusBarItems = [];\n
-  /** Holds the parts (table cells) of the UI (toolbar, panels, statusbar)\n
-\n
-   * @type Object framework parts\n
-   */\n
-  this._framework = {};\n
-  /** Them whole thing (table)\n
-   * @private\n
-   * @type DomNode\n
-   */\n
-  this._htmlArea = null;\n
-  /** This is the actual editable area.<br />\n
-   *  Technically it\'s an iframe that\'s made editable using window.designMode = \'on\', respectively document.body.contentEditable = true (IE).<br />\n
-   *  Use this property to get a grip on the iframe\'s window features<br />\n
-   *\n
-   * @type window\n
-   */\n
-  this._iframe = null;\n
-  /** The document object of the iframe.<br />\n
-  *   Use this property to perform DOM operations on the edited document\n
-  * @type document\n
-  */\n
-  this._doc = null;\n
-  /** The toolbar\n
-   *  @private\n
-   *  @type DomNode \n
-   */\n
-  this._toolBar = this._toolbar = null; //._toolbar is for legacy, ._toolBar is better thanks.\n
-  /** Holds the botton objects\n
-   *  @private\n
-   *  @type Object\n
-   */\n
-  this._toolbarObjects = {};\n
-  \n
-  //hook in config.Events as as a "plugin"\n
-  this.plugins.Events = \n
-  {\n
-    name: \'Events\',\n
-    developer : \'The Xinha Core Developer Team\',\n
-    instance: config.Events\n
-  };\n
-};\n
-// ray: What is this for? Do we need it?\n
-Xinha.onload = function() { };\n
-Xinha.init = function() { Xinha.onload(); };\n
-\n
-// cache some regexps\n
-/** Identifies HTML tag names\n
-* @type RegExp\n
-*/\n
-Xinha.RE_tagName  = /(<\\/|<)\\s*([^ \\t\\n>]+)/ig;\n
-/** Exracts DOCTYPE string from HTML\n
-* @type RegExp\n
-*/\n
-Xinha.RE_doctype  = /(<!doctype((.|\\n)*?)>)\\n?/i;\n
-/** Finds head section in HTML\n
-* @type RegExp\n
-*/\n
-Xinha.RE_head     = /<head>((.|\\n)*?)<\\/head>/i;\n
-/** Finds body section in HTML\n
-* @type RegExp\n
-*/\n
-Xinha.RE_body     = /<body[^>]*>((.|\\n|\\r|\\t)*?)<\\/body>/i;\n
-/** Special characters that need to be escaped when dynamically creating a RegExp from an arbtrary string\n
-* @private\n
-* @type RegExp\n
-*/\n
-Xinha.RE_Specials = /([\\/\\^$*+?.()|{}\\[\\]])/g;\n
-/** When dynamically creating a RegExp from an arbtrary string, some charactes that have special meanings in regular expressions have to be escaped.\n
-*   Run any string through this function to escape reserved characters.\n
-* @param {string} string the string to be escaped\n
-* @returns string\n
-*/\n
-Xinha.escapeStringForRegExp = function (string)\n
-{\n
-  return string.replace(Xinha.RE_Specials, \'\\\\$1\');\n
-};\n
-/** Identifies email addresses\n
-* @type RegExp\n
-*/\n
-Xinha.RE_email    = /^[_a-z\\d\\-\\.]{3,}@[_a-z\\d\\-]{2,}(\\.[_a-z\\d\\-]{2,})+$/i;\n
-/** Identifies URLs\n
-* @type RegExp\n
-*/\n
-Xinha.RE_url      = /(https?:\\/\\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_\\-]{2,}(\\.[a-z0-9_\\-]{2,}){2,}(:[0-9]+)?(\\/\\S+)*)/i;\n
-\n
-\n
-\n
-/**\n
- * This class creates an object that can be passed to the Xinha constructor as a parameter.\n
- * Set the object\'s properties as you need to configure the editor (toolbar etc.)\n
- * @version $Rev: 1263 $ $LastChangedDate: 2010-05-12 09:40:06 +1200 (Wed, 12 May 2010) $\n
- * @constructor\n
- */\n
-Xinha.Config = function()\n
-{\n
-  /** The svn revision number \n
-   * @type Number\n
-   */\n
-  this.version = Xinha.version.Revision;\n
-  \n
- /** This property controls the width of the editor.<br />\n
-  *  Allowed values are \'auto\', \'toolbar\' or a numeric value followed by "px".<br />\n
-  *  <code>auto</code>: let Xinha choose the width to use.<br />\n
-  *  <code>toolbar</code>: compute the width size from the toolbar width.<br />\n
-  *  <code>numeric value</code>: forced width in pixels (\'600px\').<br />\n
-  * \n
-  *  Default: <code>"auto"</code>\n
-  * @type String\n
-  */\n
-  this.width  = "auto";\n
- /** This property controls the height of the editor.<br />\n
-  *  Allowed values are \'auto\' or a numeric value followed by px.<br />\n
-  *  <code>"auto"</code>: let Xinha choose the height to use.<br />\n
-  *  <code>numeric value</code>: forced height in pixels (\'200px\').<br />\n
-  *  Default: <code>"auto"</code> \n
-  * @type String\n
-  */\n
-  this.height = "auto";\n
-\n
- /** Specifies whether the toolbar should be included\n
-  *  in the size, or are extra to it.  If false then it\'s recommended\n
-  *  to have the size set as explicit pixel sizes (either in Xinha.Config or on your textarea)<br />\n
-  *\n
-  *  Default: <code>true</code>\n
-  *\n
-  *  @type Boolean\n
-  */\n
-  this.sizeIncludesBars = true;\n
- /**\n
-  * Specifies whether the panels should be included\n
-  * in the size, or are extra to it.  If false then it\'s recommended\n
-  * to have the size set as explicit pixel sizes (either in Xinha.Config or on your textarea)<br />\n
-  *  \n
-  *  Default: <code>true</code>\n
-  *\n
-  *  @type Boolean\n
-  */\n
-  this.sizeIncludesPanels = true;\n
-\n
- /**\n
-  * each of the panels has a dimension, for the left/right it\'s the width\n
-  * for the top/bottom it\'s the height.\n
-  *\n
-  * WARNING: PANEL DIMENSIONS MUST BE SPECIFIED AS PIXEL WIDTHS<br />\n
-  *Default values:  \n
-  *<pre>\n
-  *\t  xinha_config.panel_dimensions =\n
-  *   {\n
-  *\t    left:   \'200px\', // Width\n
-  *\t    right:  \'200px\',\n
-  *\t    top:    \'100px\', // Height\n
-  *\t    bottom: \'100px\'\n
-  *\t  }\n
-  *</pre>\n
-  *  @type Object\n
-  */\n
-  this.panel_dimensions =\n
-  {\n
-    left:   \'200px\', // Width\n
-    right:  \'200px\',\n
-    top:    \'100px\', // Height\n
-    bottom: \'100px\'\n
-  };\n
-\n
- /**  To make the iframe width narrower than the toolbar width, e.g. to maintain\n
-  *   the layout when editing a narrow column of text, set the next parameter (in pixels).<br />\n
-  *\n
-  *  Default: <code>true</code>\n
-  *\n
-  *  @type Integer|null\n
-  */\n
-  this.iframeWidth = null;\n
- \n
- /** Enable creation of the status bar?<br />\n
-  *\n
-  *  Default: <code>true</code>\n
-  *\n
-  *  @type Boolean \n
-  */\n
-  this.statusBar = true;\n
-\n
- /** Intercept ^V and use the Xinha paste command\n
-  *  If false, then passes ^V through to browser editor widget, which is the only way it works without problems in Mozilla<br />\n
-  *\n
-  *  Default: <code>false</code>\n
-  *\n
-  *  @type Boolean\n
-  */\n
-  this.htmlareaPaste = false;\n
-  \n
- /** <strong>Gecko only:</strong> Let the built-in routine for handling the <em>return</em> key decide if to enter <em>br</em> or <em>p</em> tags,\n
-  *  or use a custom implementation.<br />\n
-  *  For information about the rules applied by Gecko, <a href="http://www.mozilla.org/editor/rules.html">see Mozilla website</a> <br />\n
-  *  Possible values are <em>built-in</em> or <em>best</em><br />\n
-  *\n
-  *  Default: <code>"best"</code>\n
-  *\n
-  *  @type String\n
-  */\n
-  this.mozParaHandler = \'best\'; \n
-  \n
- /** This determines the method how the HTML output is generated.\n
-  *  There are two choices:\n
-  * \n
-  *<table border="1">\n
-  *   <tr>\n
-  *       <td><em>DOMwalk</em></td>\n
-  *       <td>This is the classic and proven method. It recusively traverses the DOM tree \n
-  *           and builds the HTML string "from scratch". Tends to be a bit slow, especially in IE.</td>\n
-  *   </tr>\n
-  *   <tr>\n
-  *       <td><em>TransformInnerHTML</em></td>\n
-  *       <td>This method uses the JavaScript innerHTML property and relies on Regular Expressions to produce\n
-  *            clean XHTML output. This method is much faster than the other one.</td>\n
-  *     </tr>\n
-  * </table>\n
-  *\n
-  *  Default: <code>"DOMwalk"</code>\n
-  *\n
-  * @type String\n
-  */\n
-  this.getHtmlMethod = \'DOMwalk\';\n
-  \n
-  /** Maximum size of the undo queue<br />\n
-   *  Default: <code>20</code>\n
-   *  @type Integer\n
-   */\n
-  this.undoSteps = 20;\n
-\n
-  /** The time interval at which undo samples are taken<br />\n
-   *  Default: <code>500</code> (1/2 sec)\n
-   *  @type Integer milliseconds\n
-   */\n
-  this.undoTimeout = 500;\n
-\n
-  /** Set this to true if you want to explicitly right-justify when setting the text direction to right-to-left<br />\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-  this.changeJustifyWithDirection = false;\n
-\n
-  /** If true then Xinha will retrieve the full HTML, starting with the &lt;HTML&gt; tag.<br />\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-  this.fullPage = false;\n
-\n
-  /** Raw style definitions included in the edited document<br />\n
-   *  When a lot of inline style is used, perhaps it is wiser to use one or more external stylesheets.<br />\n
-   *  To set tags P in red, H1 in blue andn A not underlined, we may do the following\n
-   *<pre>\n
-   * xinha_config.pageStyle =\n
-   *  \'p { color:red; }\\n\' +\n
-   *  \'h1 { color:bleu; }\\n\' +\n
-   *  \'a {text-decoration:none; }\';\n
-   *</pre>\n
-   *  Default: <code>""</code> (empty)\n
-   *  @type String\n
-   */\n
-  this.pageStyle = "";\n
-\n
-  /** Array of external stylesheets to load. (Reference these absolutely)<br />\n
-   *  Example<br />\n
-   *  <pre>xinha_config.pageStyleSheets = ["/css/myPagesStyleSheet.css","/css/anotherOne.css"];</pre>\n
-   *  Default: <code>[]</code> (empty)\n
-   *  @type Array\n
-   */\n
-  this.pageStyleSheets = [];\n
-\n
-  // specify a base href for relative links\n
-  /** Specify a base href for relative links<br />\n
-   *  ATTENTION: this does not work as expected and needs t be changed, see Ticket #961 <br />\n
-   *  Default: <code>null</code>\n
-   *  @type String|null\n
-   */\n
-  this.baseHref = null;\n
-\n
-  /** If true, relative URLs (../) will be made absolute. \n
-   *  When the editor is in different directory depth \n
-   *  as the edited page relative image sources will break the display of your images.\n
-   *  this fixes an issue where Mozilla converts the urls of images and links that are on the same server \n
-   *  to relative ones (../) when dragging them around in the editor (Ticket #448)<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.expandRelativeUrl = true;\n
-  \n
- /**  We can strip the server part out of URL to make/leave them semi-absolute, reason for this\n
-   *  is that the browsers will prefix  the server to any relative links to make them absolute, \n
-   *  which isn\'t what you want most the time.<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.stripBaseHref = true;\n
-\n
-   /**  We can strip the url of the editor page from named links (eg &lt;a href="#top"&gt;...&lt;/a&gt;) and links \n
-   *  that consist only of URL parameters (eg &lt;a href="?parameter=value"&gt;...&lt;/a&gt;)\n
-   *  reason for this is that browsers tend to prefixe location.href to any href that\n
-   *  that don\'t have a full url<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.stripSelfNamedAnchors = true;\n
-\n
-  /** In URLs all characters above ASCII value 127 have to be encoded using % codes<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.only7BitPrintablesInURLs = true;\n
-\n
- \n
-  /** If you are putting the HTML written in Xinha into an email you might want it to be 7-bit\n
-   *  characters only.  This config option will convert all characters consuming\n
-   *  more than 7bits into UNICODE decimal entity references (actually it will convert anything\n
-   *  below <space> (chr 20) except cr, lf and tab and above <tilde> (~, chr 7E))<br />\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-  this.sevenBitClean = false;\n
-\n
-\n
-  /** Sometimes we want to be able to replace some string in the html coming in and going out\n
-   *  so that in the editor we use the "internal" string, and outside and in the source view\n
-   *  we use the "external" string  this is useful for say making special codes for\n
-   *  your absolute links, your external string might be some special code, say "{server_url}"\n
-   *  an you say that the internal represenattion of that should be http://your.server/<br />\n
-   *  Example:  <code>{ \'html_string\' : \'wysiwyg_string\' }</code><br />\n
-   *  Default: <code>{}</code> (empty)\n
-   *  @type Object\n
-   */\n
-  this.specialReplacements = {}; //{ \'html_string\' : \'wysiwyg_string\' }\n
-  \n
-  /** A filter function for the HTML used inside the editor<br />\n
-   * Default: function (html) { return html }\n
-   * \n
-   * @param {String} html The whole document\'s HTML content\n
-   * @return {String} The processed HTML \n
-   */\n
-  this.inwardHtml = function (html) { return html; };\n
-  \n
-  /** A filter function for the generated HTML<br />\n
-   * Default: function (html) { return html }\n
-   * \n
-   * @param {String} html The whole document\'s HTML content\n
-   * @return {String} The processed HTML \n
-   */\n
-  this.outwardHtml = function (html) { return html; };\n
-  \n
-  /** This setting determines whether or not the editor will be automatically activated and focused when the page loads. \n
-   *  If the page contains only a single editor, autofocus can be set to true to focus it. \n
-   *  Alternatively, if the page contains multiple editors, autofocus may be set to the ID of the text area of the editor to be focused. \n
-   *  For example, the following setting would focus the editor attached to the text area whose ID is "myTextArea": \n
-   *  <code>xinha_config.autofocus = "myTextArea";</code>\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean|String\n
-   */\n
-  this.autofocus = false;\n
-  \n
- /** Set to true if you want Word code to be cleaned upon Paste. This only works if \n
-   * you use the toolbr button to paste, not ^V. This means that due to the restrictions\n
-   * regarding pasting, this actually has no real effect in Mozilla <br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.killWordOnPaste = true;\n
-\n
-  /** Enable the \'Target\' field in the Make Link dialog. Note that the target attribute is invalid in (X)HTML strict<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.makeLinkShowsTarget = true;\n
-\n
-  /** CharSet of the iframe, default is the charset of the document\n
-   *  @type String\n
-   */\n
-  this.charSet = (typeof document.characterSet != \'undefined\') ? document.characterSet : document.charset;\n
-\n
- /** Whether the edited document should be rendered in Quirksmode or Standard Compliant (Strict) Mode.<br />\n
-   * This is commonly known as the "doctype switch"<br />\n
-   * for details read here http://www.quirksmode.org/css/quirksmode.html\n
-   *\n
-   * Possible values:<br />\n
-   *    true     :  Quirksmode is used<br />\n
-   *    false    :  Strict mode is used<br />\n
-   *    null (default):  the mode of the document Xinha is in is used\n
-   * @type Boolean|null\n
-   */\n
-  this.browserQuirksMode = null;\n
-\n
-  // URL-s\n
-  this.imgURL = "images/";\n
-  this.popupURL = "popups/";\n
-\n
-  /** RegExp allowing to remove certain HTML tags when rendering the HTML.<br />\n
-   *  Example: remove span and font tags\n
-   *  <code>\n
-   *    xinha_config.htmlRemoveTags = /span|font/;\n
-   *  </code>\n
-   *  Default: <code>null</code>\n
-   *  @type RegExp|null\n
-   */\n
-  this.htmlRemoveTags = null;\n
-\n
- /** Turning this on will turn all "linebreak" and "separator" items in your toolbar into soft-breaks,\n
-   * this means that if the items between that item and the next linebreak/separator can\n
-   * fit on the same line as that which came before then they will, otherwise they will\n
-   * float down to the next line.\n
-\n
-   * If you put a linebreak and separator next to each other, only the separator will\n
-   * take effect, this allows you to have one toolbar that works for both flowToolbars = true and false\n
-   * infact the toolbar below has been designed in this way, if flowToolbars is false then it will\n
-   * create explictly two lines (plus any others made by plugins) breaking at justifyleft, however if\n
-   * flowToolbars is false and your window is narrow enough then it will create more than one line\n
-   * even neater, if you resize the window the toolbars will reflow.  <br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.flowToolbars = true;\n
-  \n
-  /** Set to center or right to change button alignment in toolbar\n
-   *  @type String\n
-   */\n
-  this.toolbarAlign = "left";\n
-  \n
-  /** Set to true to display the font names in the toolbar font select list in their actual font.\n
-   *  Note that this doesn\'t work in IE, but doesn\'t hurt anything either.\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-   this.showFontStylesInToolbar = false;\n
-  \n
-  /** Set to true if you want the loading panel to show at startup<br />\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-  this.showLoading = false;\n
-  \n
-  /** Set to false if you want to allow JavaScript in the content, otherwise &lt;script&gt; tags are stripped out.<br />\n
-   *  This currently only affects the "DOMwalk" getHtmlMethod.<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-  this.stripScripts = true;\n
-\n
- /** See if the text just typed looks like a URL, or email address\n
-   * and link it appropriatly\n
-   * Note: Setting this option to false only affects Mozilla based browsers.\n
-   * In InternetExplorer this is native behaviour and cannot be turned off.<br />\n
-   *  Default: <code>true</code>\n
-   *  @type Boolean\n
-   */\n
-   this.convertUrlsToLinks = true;\n
-\n
-\n
- /** Size of color picker cells<br />\n
-   * Use number + "px"<br />\n
-   *  Default: <code>"6px"</code>\n
-   *  @type String\n
-   */\n
-  this.colorPickerCellSize = \'6px\';\n
- /** Granularity of color picker cells (number per column/row)<br />\n
-   *  Default: <code>18</code>\n
-   *  @type Integer\n
-   */\n
-  this.colorPickerGranularity = 18;\n
- /** Position of color picker from toolbar button<br />\n
-   *  Default: <code>"bottom,right"</code>\n
-   *  @type String\n
-   */\n
-  this.colorPickerPosition = \'bottom,right\';\n
-  /** Set to true to show only websafe checkbox in picker<br />\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-  this.colorPickerWebSafe = false;\n
- /** Number of recent colors to remember<br />\n
-   *  Default: <code>20</code>\n
-   *  @type Integer\n
-   */\n
-  this.colorPickerSaveColors = 20;\n
-\n
-  /** Start up the editor in fullscreen mode<br />\n
-   *  Default: <code>false</code>\n
-   *  @type Boolean\n
-   */\n
-  this.fullScreen = false;\n
-  \n
- /** You can tell the fullscreen mode to leave certain margins on each side.<br />\n
-   *  The value is an array with the values for <code>[top,right,bottom,left]</code> in that order<br />\n
-   *  Default: <code>[0,0,0,0]</code>\n
-   *  @type Array\n
-   */\n
-  this.fullScreenMargins = [0,0,0,0];\n
-  \n
-  \n
-  /** Specify the method that is being used to calculate the editor\'s size<br/>\n
-    * when we return from fullscreen mode.\n
-    *  There are two choices:\n
-    * \n
-    * <table border="1">\n
-    *   <tr>\n
-    *       <td><em>initSize</em></td>\n
-    *       <td>Use the internal Xinha.initSize() method to calculate the editor\'s \n
-    *       dimensions. This is suitable for most usecases.</td>\n
-    *   </tr>\n
-    *   <tr>\n
-    *       <td><em>restore</em></td>\n
-    *       <td>The editor\'s dimensions will be stored before going into fullscreen\n
-    *       mode and restored when we return to normal mode, taking a possible\n
-    *       window resize during fullscreen in account.</td>\n
-    *     </tr>\n
-    * </table>\n
-    *\n
-    * Default: <code>"initSize"</code>\n
-    * @type String\n
-    */\n
-  this.fullScreenSizeDownMethod = \'initSize\';\n
-  \n
-  /** This array orders all buttons except plugin buttons in the toolbar. Plugin buttons typically look for one \n
-   *  a certain button in the toolbar and place themselves next to it.\n
-   * Default value:\n
-   *<pre>\n
-   *xinha_config.toolbar =\n
-   * [\n
-   *   ["popupeditor"],\n
-   *   ["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"],\n
-   *   ["separator","forecolor","hilitecolor","textindicator"],\n
-   *   ["separator","subscript","superscript"],\n
-   *   ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],\n
-   *   ["separator","insertorderedlist","insertunorderedlist","outdent","indent"],\n
-   *   ["separator","inserthorizontalrule","createlink","insertimage","inserttable"],\n
-   *   ["linebreak","separator","undo","redo","selectall","print"], (Xinha.is_gecko ? [] : ["cut","copy","paste","overwrite","saveas"]),\n
-   *   ["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright", "righttoleft"],\n
-   *   ["separator","htmlmode","showhelp","about"]\n
-   * ];\n
-   *</pre>\n
-   * @type Array\n
-   */  \n
-  this.toolbar =\n
-  [\n
-    ["popupeditor"],\n
-    ["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"],\n
-    ["separator","forecolor","hilitecolor","textindicator"],\n
-    ["separator","subscript","superscript"],\n
-    ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],\n
-    ["separator","insertorderedlist","insertunorderedlist","outdent","indent"],\n
-    ["separator","inserthorizontalrule","createlink","insertimage","inserttable"],\n
-    ["linebreak","separator","undo","redo","selectall","print"], (Xinha.is_gecko ? [] : ["cut","copy","paste","overwrite","saveas"]),\n
-    ["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright", "righttoleft"],\n
-    ["separator","htmlmode","showhelp","about"]\n
-];\n
-\n
-  /** The fontnames listed in the fontname dropdown\n
-   * Default value:\n
-   *<pre>\n
-   *xinha_config.fontname =\n
-   *{\n
-   *  "&#8212; font &#8212;" : \'\',\n
-   *  "Arial"                : \'arial,helvetica,sans-serif\',\n
-   *  "Courier New"          : \'courier new,courier,monospace\',\n
-   *  "Georgia"              : \'georgia,times new roman,times,serif\',\n
-   *  "Tahoma"               : \'tahoma,arial,helvetica,sans-serif\',\n
-   *  "Times New Roman"      : \'times new roman,times,serif\',\n
-   *  "Verdana"              : \'verdana,arial,helvetica,sans-serif\',\n
-   *  "impact"               : \'impact\',\n
-   *  "WingDings"            : \'wingdings\'\n
-   *};\n
-   *</pre>\n
-   * @type Object\n
-   */\n
-  this.fontname =\n
-  {\n
-    "&#8212; font &#8212;": "", // &#8212; is mdash\n
-    "Arial"           :\t\'arial,helvetica,sans-serif\',\n
-    "Courier New"     :\t\'courier new,courier,monospace\',\n
-    "Georgia"         :\t\'georgia,times new roman,times,serif\',\n
-    "Tahoma"          :\t\'tahoma,arial,helvetica,sans-serif\',\n
-    "Times New Roman" : \'times new roman,times,serif\',\n
-    "Verdana"         :\t\'verdana,arial,helvetica,sans-serif\',\n
-    "impact"          :\t\'impact\',\n
-    "WingDings"       : \'wingdings\' \n
-  };\n
-\n
-  /** The fontsizes listed in the fontsize dropdown\n
-   * Default value:\n
-   *<pre>\n
-   *xinha_config.fontsize =\n
-   *{\n
-   *  "&#8212; size &#8212;": "",\n
-   *  "1 (8 pt)" : "1",\n
-   *  "2 (10 pt)": "2",\n
-   *  "3 (12 pt)": "3",\n
-   *  "4 (14 pt)": "4",\n
-   *  "5 (18 pt)": "5",\n
-   *  "6 (24 pt)": "6",\n
-   *  "7 (36 pt)": "7"\n
-   *};\n
-   *</pre>\n
-   * @type Object\n
-   */\n
-  this.fontsize =\n
-  {\n
-    "&#8212; size &#8212;": "", // &#8212; is mdash\n
-    "1 (8 pt)" : "1",\n
-    "2 (10 pt)": "2",\n
-    "3 (12 pt)": "3",\n
-    "4 (14 pt)": "4",\n
-    "5 (18 pt)": "5",\n
-    "6 (24 pt)": "6",\n
-    "7 (36 pt)": "7"\n
-  };\n
-  /** The tags listed in the formatblock dropdown\n
-   * Default value:\n
-   *<pre>\n
-   *xinha_config.formatblock =\n
-   *{\n
-   *  "&#8212; size &#8212;": "",\n
-   *  "1 (8 pt)" : "1",\n
-   *  "2 (10 pt)": "2",\n
-   *  "3 (12 pt)": "3",\n
-   *  "4 (14 pt)": "4",\n
-   *  "5 (18 pt)": "5",\n
-   *  "6 (24 pt)": "6",\n
-   *  "7 (36 pt)": "7"\n
-   *};\n
-   *</pre>\n
-   * @type Object\n
-   */\n
-  this.formatblock =\n
-  {\n
-    "&#8212; format &#8212;": "", // &#8212; is mdash\n
-    "Heading 1": "h1",\n
-    "Heading 2": "h2",\n
-    "Heading 3": "h3",\n
-    "Heading 4": "h4",\n
-    "Heading 5": "h5",\n
-    "Heading 6": "h6",\n
-    "Normal"   : "p",\n
-    "Address"  : "address",\n
-    "Formatted": "pre"\n
-  };\n
-  \n
-  this.dialogOptions =\n
-  { \n
-    \'centered\' : true, //true: dialog is shown in the center the screen, false dialog is shown near the clicked toolbar button\n
-    \'greyout\':true, //true: when showing modal dialogs, the page behind the dialoge is greyed-out\n
-    \'closeOnEscape\':true\n
-  };\n
-  /** You can add functions to this object to be executed on specific events\n
-   * Example:\n
-   * <pre>\n
-   * xinha_config.Events.onKeyPress = function (event)\n
-   * {\n
-   *    //do something \n
-   *    return false;\n
-   * }\n
-   * </pre>\n
-   * Note that <em>this</em> inside the function refers to the respective Xinha object\n
-   * The possible function names are documented at <a href="http://trac.xinha.org/wiki/Documentation/EventHooks">http://trac.xinha.org/wiki/Documentation/EventHooks</a>\n
-   */\n
-  this.Events = {};\n
-  \n
-  /** ??\n
-   * Default: <code>{}</code>\n
-   * @type Object\n
-   */\n
-  this.customSelects = {};\n
-\n
-  /** Switches on some debugging (only in execCommand() as far as I see at the moment)<br />\n
-   *\n
-   * Default: <code>false</code>\n
-   * @type Boolean\n
-   */\n
-  this.debug = false;\n
-\n
-  this.URIs =\n
-  {\n
-   "blank": _editor_url + "popups/blank.html",\n
-   "link":  _editor_url + "modules/CreateLink/link.html",\n
-   "insert_image": _editor_url + "modules/InsertImage/insert_image.html",\n
-   "insert_table":  _editor_url + "modules/InsertTable/insert_table.html",\n
-   "select_color": _editor_url + "popups/select_color.html",\n
-   "help": _editor_url + "popups/editor_help.html"\n
-  };\n
-\n
-   /** The button list conains the definitions of the toolbar button. Normally, there\'s nothing to change here :) \n
-   * <div style="white-space:pre">ADDING CUSTOM BUTTONS: please read below!\n
-   * format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"\n
-   *    - ID: unique ID for the button.  If the button calls document.execCommand\n
-   *\t    it\'s wise to give it the same name as the called command.\n
-   *    - ACTION: function that gets called when the button is clicked.\n
-   *              it has the following prototype:\n
-   *                 function(editor, buttonName)\n
-   *              - editor is the Xinha object that triggered the call\n
-   *              - buttonName is the ID of the clicked button\n
-   *              These 2 parameters makes it possible for you to use the same\n
-   *              handler for more Xinha objects or for more different buttons.\n
-   *    - ToolTip: tooltip, will be translated below\n
-   *    - Icon: path to an icon image file for the button\n
-   *            OR; you can use an 18x18 block of a larger image by supllying an array\n
-   *            that has three elemtents, the first is the larger image, the second is the column\n
-   *            the third is the row.  The ros and columns numbering starts at 0 but there is\n
-   *            a header row and header column which have numbering to make life easier.\n
-   *            See images/buttons_main.gif to see how it\'s done.\n
-   *    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.</div>\n
-   * @type Object\n
-   */\n
-  this.btnList =\n
-  {\n
-    bold: [ "Bold", Xinha._lc({key: \'button_bold\', string: ["ed_buttons_main.png",3,2]}, \'Xinha\'), false, function(e) { e.execCommand("bold"); } ],\n
-    italic: [ "Italic", Xinha._lc({key: \'button_italic\', string: ["ed_buttons_main.png",2,2]}, \'Xinha\'), false, function(e) { e.execCommand("italic"); } ],\n
-    underline: [ "Underline", Xinha._lc({key: \'button_underline\', string: ["ed_buttons_main.png",2,0]}, \'Xinha\'), false, function(e) { e.execCommand("underline"); } ],\n
-    strikethrough: [ "Strikethrough", Xinha._lc({key: \'button_strikethrough\', string: ["ed_buttons_main.png",3,0]}, \'Xinha\'), false, function(e) { e.execCommand("strikethrough"); } ],\n
-    subscript: [ "Subscript", Xinha._lc({key: \'button_subscript\', string: ["ed_buttons_main.png",3,1]}, \'Xinha\'), false, function(e) { e.execCommand("subscript"); } ],\n
-    superscript: [ "Superscript", Xinha._lc({key: \'button_superscript\', string: ["ed_buttons_main.png",2,1]}, \'Xinha\'), false, function(e) { e.execCommand("superscript"); } ],\n
-\n
-    justifyleft: [ "Justify Left", ["ed_buttons_main.png",0,0], false, function(e) { e.execCommand("justifyleft"); } ],\n
-    justifycenter: [ "Justify Center", ["ed_buttons_main.png",1,1], false, function(e){ e.execCommand("justifycenter"); } ],\n
-    justifyright: [ "Justify Right", ["ed_buttons_main.png",1,0], false, function(e) { e.execCommand("justifyright"); } ],\n
-    justifyfull: [ "Justify Full", ["ed_buttons_main.png",0,1], false, function(e) { e.execCommand("justifyfull"); } ],\n
-\n
-    orderedlist: [ "Ordered List", ["ed_buttons_main.png",0,3], false, function(e) { e.execCommand("insertorderedlist"); } ],\n
-    unorderedlist: [ "Bulleted List", ["ed_buttons_main.png",1,3], false, function(e) { e.execCommand("insertunorderedlist"); } ],\n
-    insertorderedlist: [ "Ordered List", ["ed_buttons_main.png",0,3], false, function(e) { e.execCommand("insertorderedlist"); } ],\n
-    insertunorderedlist: [ "Bulleted List", ["ed_buttons_main.png",1,3], false, function(e) { e.execCommand("insertunorderedlist"); } ],\n
-\n
-    outdent: [ "Decrease Indent", ["ed_buttons_main.png",1,2], false, function(e) { e.execCommand("outdent"); } ],\n
-    indent: [ "Increase Indent",["ed_buttons_main.png",0,2], false, function(e) { e.execCommand("indent"); } ],\n
-    forecolor: [ "Font Color", ["ed_buttons_main.png",3,3], false, function(e) { e.execCommand("forecolor"); } ],\n
-    hilitecolor: [ "Background Color", ["ed_buttons_main.png",2,3], false, function(e) { e.execCommand("hilitecolor"); } ],\n
-\n
-    undo: [ "Undoes your last action", ["ed_buttons_main.png",4,2], false, function(e) { e.execCommand("undo"); } ],\n
-    redo: [ "Redoes your last action", ["ed_buttons_main.png",5,2], false, function(e) { e.execCommand("redo"); } ],\n
-    cut: [ "Cut selection", ["ed_buttons_main.png",5,0], false,  function (e, cmd) { e.execCommand(cmd); } ],\n
-    copy: [ "Copy selection", ["ed_buttons_main.png",4,0], false,  function (e, cmd) { e.execCommand(cmd); } ],\n
-    paste: [ "Paste from clipboard", ["ed_buttons_main.png",4,1], false,  function (e, cmd) { e.execCommand(cmd); } ],\n
-    selectall: [ "Select all", ["ed_buttons_main.png",3,5], false, function(e) {e.execCommand("selectall");} ],\n
-\n
-    inserthorizontalrule: [ "Horizontal Rule", ["ed_buttons_main.png",6,0], false, function(e) { e.execCommand("inserthorizontalrule"); } ],\n
-    createlink: [ "Insert Web Link", ["ed_buttons_main.png",6,1], false, function(e) { e._createLink(); } ],\n
-    insertimage: [ "Insert/Modify Image", ["ed_buttons_main.png",6,3], false, function(e) { e.execCommand("insertimage"); } ],\n
-    inserttable: [ "Insert Table", ["ed_buttons_main.png",6,2], false, function(e) { e.execCommand("inserttable"); } ],\n
-\n
-    htmlmode: [ "Toggle HTML Source", ["ed_buttons_main.png",7,0], true, function(e) { e.execCommand("htmlmode"); } ],\n
-    toggleborders: [ "Toggle Borders", ["ed_buttons_main.png",7,2], false, function(e) { e._toggleBorders(); } ],\n
-    print: [ "Print document", ["ed_buttons_main.png",8,1], false, function(e) { if(Xinha.is_gecko) {e._iframe.contentWindow.print(); } else { e.focusEditor(); print(); } } ],\n
-    saveas: [ "Save as", ["ed_buttons_main.png",9,1], false, function(e) { e.execCommand("saveas",false,"noname.htm"); } ],\n
-    about: [ "About this editor", ["ed_buttons_main.png",8,2], true, function(e) { e.getPluginInstance("AboutBox").show(); } ],\n
-    showhelp: [ "Help using editor", ["ed_buttons_main.png",9,2], true, function(e) { e.execCommand("showhelp"); } ],\n
-\n
-    splitblock: [ "Split Block", "ed_splitblock.gif", false, function(e) { e._splitBlock(); } ],\n
-    lefttoright: [ "Direction left to right", ["ed_buttons_main.png",0,2], false, function(e) { e.execCommand("lefttoright"); } ],\n
-    righttoleft: [ "Direction right to left", ["ed_buttons_main.png",1,2], false, function(e) { e.execCommand("righttoleft"); } ],\n
-    overwrite: [ "Insert/Overwrite", "ed_overwrite.gif", false, function(e) { e.execCommand("overwrite"); } ],\n
-\n
-    wordclean: [ "MS Word Cleaner", ["ed_buttons_main.png",5,3], false, function(e) { e._wordClean(); } ],\n
-    clearfonts: [ "Clear Inline Font Specifications", ["ed_buttons_main.png",5,4], true, function(e) { e._clearFonts(); } ],\n
-    removeformat: [ "Remove formatting", ["ed_buttons_main.png",4,4], false, function(e) { e.execCommand("removeformat"); } ],\n
-    killword: [ "Clear MSOffice tags", ["ed_buttons_main.png",4,3], false, function(e) { e.execCommand("killword"); } ]\n
-  };\n
-  \n
-  /** A hash of double click handlers for the given elements, each element may have one or more double click handlers\n
-   *  called in sequence.  The element may contain a class selector ( a.somethingSpecial )\n
-   *  \n
-   */\n
-   \n
-  this.dblclickList = \n
-  {\n
-    "a": [function(e, target) {e._createLink(target);}],\n
-    "img": [function(e, target) {e._insertImage(target);}]\n
-  };\n
-  \n
-  /** A container for additional icons that may be swapped within one button (like fullscreen)\n
-   * @private\n
-   */\n
-  this.iconList = \n
-  {\n
-    dialogCaption : _editor_url + \'images/xinha-small-icon.gif\',\n
-    wysiwygmode : [_editor_url + \'images/ed_buttons_main.png\',7,1]\n
-  };\n
-  // initialize tooltips from the I18N module and generate correct image path\n
-  for ( var i in this.btnList )\n
-  {\n
-    var btn = this.btnList[i];\n
-    // prevent iterating over wrong type\n
-    if ( typeof btn != \'object\' )\n
-    {\n
-      continue;\n
-    } \n
-    if ( typeof btn[1] != \'string\' )\n
-    {\n
-      btn[1][0] = _editor_url + this.imgURL + btn[1][0];\n
-    }\n
-    else\n
-    {\n
-      btn[1] = _editor_url + this.imgURL + btn[1];\n
-    }\n
-    btn[0] = Xinha._lc(btn[0]); //initialize tooltip\n
-  }\n
-};\n
-/** A plugin may require more than one icon for one button, this has to be registered in order to work with the iconsets (see FullScreen)\n
- * \n
- * @param {String} id\n
- * @param {String|Array} icon definition like in registerButton\n
- */\n
-Xinha.Config.prototype.registerIcon = function (id, icon)\n
-{\n
-  this.iconList[id] = icon;\n
-};\n
-/** ADDING CUSTOM BUTTONS\n
-*   ---------------------\n
-*\n
-*\n
-* Example on how to add a custom button when you construct the Xinha:\n
-*\n
-*   var editor = new Xinha("your_text_area_id");\n
-*   var cfg = editor.config; // this is the default configuration\n
-*   cfg.btnList["my-hilite"] =\n
-*\t[ "Highlight selection", // tooltip\n
-*\t  "my_hilite.gif", // image\n
-*\t  false // disabled in text mode\n
-*\t  function(editor) { editor.surroundHTML(\'<span style="background:yellow">\', \'</span>\'); }, // action\n
-*\t];\n
-*   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar\n
-*\n
-* An alternate (also more convenient and recommended) way to\n
-* accomplish this is to use the registerButton function below.\n
-*/\n
-/** Helper function: register a new button with the configuration.  It can be\n
- * called with all 5 arguments, or with only one (first one).  When called with\n
- * only one argument it must be an object with the following properties: id,\n
- * tooltip, image, textMode, action.<br />  \n
- * \n
- * Examples:<br />\n
- *<pre>\n
- * config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});\n
- * config.registerButton({\n
- *      id       : "my-hilite",      // the ID of your button\n
- *      tooltip  : "Hilite text",    // the tooltip\n
- *      image    : "my-hilite.gif",  // image to be displayed in the toolbar\n
- *      textMode : false,            // disabled in text mode\n
- *      action   : function(editor) { // called when the button is clicked\n
- *                   editor.surroundHTML(\'<span class="hilite">\', \'</span>\');\n
- *                 },\n
- *      context  : "p"               // will be disabled if outside a <p> element\n
- *    });</pre>\n
- */\n
-Xinha.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context)\n
-{\n
-  if ( typeof id == "string" )\n
-  {\n
-    this.btnList[id] = [ tooltip, image, textMode, action, context ];\n
-  }\n
-  else if ( typeof id == "object" )\n
-  {\n
-    this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ];\n
-  }\n
-  else\n
-  {\n
-    alert("ERROR [Xinha.Config::registerButton]:\\ninvalid arguments");\n
-    return false;\n
-  }\n
-};\n
-\n
-Xinha.prototype.registerPanel = function(side, object)\n
-{\n
-  if ( !side )\n
-  {\n
-    side = \'right\';\n
-  }\n
-  this.setLoadingMessage(\'Register \' + side + \' panel \');\n
-  var panel = this.addPanel(side);\n
-  if ( object )\n
-  {\n
-    object.drawPanelIn(panel);\n
-  }\n
-};\n
-\n
-/** The following helper function registers a dropdown box with the editor\n
- * configuration.  You still have to add it to the toolbar, same as with the\n
- * buttons.  Call it like this:\n
- *\n
- * FIXME: add example\n
- */\n
-Xinha.Config.prototype.registerDropdown = function(object)\n
-{\n
-  // check for existing id\n
-//  if ( typeof this.customSelects[object.id] != "undefined" )\n
-//  {\n
-    // alert("WARNING [Xinha.Config::registerDropdown]:\\nA dropdown with the same ID already exists.");\n
-//  }\n
-//  if ( typeof this.btnList[object.id] != "undefined" )\n
-//  {\n
-    // alert("WARNING [Xinha.Config::registerDropdown]:\\nA button with the same ID already exists.");\n
-//  }\n
-  this.customSelects[object.id] = object;\n
-};\n
-\n
-/** Call this function to remove some buttons/drop-down boxes from the toolbar.\n
- * Pass as the only parameter a string containing button/drop-down names\n
- * delimited by spaces.  Note that the string should also begin with a space\n
- * and end with a space.  Example:\n
- *\n
- *   config.hideSomeButtons(" fontname fontsize textindicator ");\n
- *\n
- * It\'s useful because it\'s easier to remove stuff from the defaul toolbar than\n
- * create a brand new toolbar ;-)\n
- */\n
-Xinha.Config.prototype.hideSomeButtons = function(remove)\n
-{\n
-  var toolbar = this.toolbar;\n
-  for ( var i = toolbar.length; --i >= 0; )\n
-  {\n
-    var line = toolbar[i];\n
-    for ( var j = line.length; --j >= 0; )\n
-    {\n
-      if ( remove.indexOf(" " + line[j] + " ") >= 0 )\n
-      {\n
-        var len = 1;\n
-        if ( /separator|space/.test(line[j + 1]) )\n
-        {\n
-          len = 2;\n
-        }\n
-        line.splice(j, len);\n
-      }\n
-    }\n
-  }\n
-};\n
-\n
-/** Helper Function: add buttons/drop-downs boxes with title or separator to the toolbar\n
- * if the buttons/drop-downs boxes doesn\'t allready exists.\n
- * id: button or selectbox (as array with separator or title)\n
- * where: button or selectbox (as array if the first is not found take the second and so on)\n
- * position:\n
- * -1 = insert button (id) one position before the button (where)\n
- * 0 = replace button (where) by button (id)\n
- * +1 = insert button (id) one position after button (where)\n
- *\n
- * cfg.addToolbarElement(["T[title]", "button_id", "separator"] , ["first_id","second_id"], -1);\n
-*/\n
-\n
-Xinha.Config.prototype.addToolbarElement = function(id, where, position)\n
-{\n
-  var toolbar = this.toolbar;\n
-  var a, i, j, o, sid;\n
-  var idIsArray = false;\n
-  var whereIsArray = false;\n
-  var whereLength = 0;\n
-  var whereJ = 0;\n
-  var whereI = 0;\n
-  var exists = false;\n
-  var found = false;\n
-  // check if id and where are arrys\n
-  if ( ( id && typeof id == "object" ) && ( id.constructor == Array ) )\n
-  {\n
-    idIsArray = true;\n
-  }\n
-  if ( ( where && typeof where == "object" ) && ( where.constructor == Array ) )\n
-  {\n
-    whereIsArray = true;\n
-    whereLength = where.length;\n
-\t}\n
-\n
-  if ( idIsArray ) //find the button/select box in input array\n
-  {\n
-    for ( i = 0; i < id.length; ++i )\n
-    {\n
-      if ( ( id[i] != "separator" ) && ( id[i].indexOf("T[") !== 0) )\n
-      {\n
-        sid = id[i];\n
-      }\n
-    }\n
-  }\n
-  else\n
-  {\n
-    sid = id;\n
-  }\n
-  \n
-  for ( i = 0; i < toolbar.length; ++i ) {\n
-    a = toolbar[i];\n
-    for ( j = 0; j < a.length; ++j ) {\n
-      // check if button/select box exists\n
-      if ( a[j] == sid ) {\n
-        return; // cancel to add elements if same button already exists\n
-      }\n
-    }\n
-  }\n
-  \n
-\n
-  for ( i = 0; !found && i < toolbar.length; ++i )\n
-  {\n
-    a = toolbar[i];\n
-    for ( j = 0; !found && j < a.length; ++j )\n
-    {\n
-      if ( whereIsArray )\n
-      {\n
-        for ( o = 0; o < whereLength; ++o )\n
-        {\n
-          if ( a[j] == where[o] )\n
-          {\n
-            if ( o === 0 )\n
-            {\n
-              found = true;\n
-              j--;\n
-              break;\n
-            }\n
-            else\n
-            {\n
-              whereI = i;\n
-              whereJ = j;\n
-              whereLength = o;\n
-            }\n
-          }\n
-        }\n
-      }\n
-      else\n
-      {\n
-        // find the position to insert\n
-        if ( a[j] == where )\n
-        { \n
-          found = true;\n
-          break;\n
-        }\n
-      }\n
-    }\n
-  }\n
-\n
-  //if check found any other as the first button\n
-  if ( !found && whereIsArray )\n
-  { \n
-    if ( where.length != whereLength )\n
-    {\n
-      j = whereJ;\n
-      a = toolbar[whereI];\n
-      found = true;\n
-    }\n
-  }\n
-  if ( found )\n
-  {\n
-    // replace the found button\n
-    if ( position === 0 )\n
-    {\n
-      if ( idIsArray)\n
-      {\n
-        a[j] = id[id.length-1];\n
-        for ( i = id.length-1; --i >= 0; )\n
-        {\n
-          a.splice(j, 0, id[i]);\n
-        }\n
-      }\n
-      else\n
-      {\n
-        a[j] = id;\n
-      }\n
-    }\n
-    else\n
-    { \n
-      // insert before/after the found button\n
-      if ( position < 0 )\n
-      {\n
-        j = j + position + 1; //correct position before\n
-      }\n
-      else if ( position > 0 )\n
-      {\n
-        j = j + position; //correct posion after\n
-      }\n
-      if ( idIsArray )\n
-      {\n
-        for ( i = id.length; --i >= 0; )\n
-        {\n
-          a.splice(j, 0, id[i]);\n
-        }\n
-      }\n
-      else\n
-      {\n
-        a.splice(j, 0, id);\n
-      }\n
-    }\n
-  }\n
-  else\n
-  {\n
-    // no button found\n
-    toolbar[0].splice(0, 0, "separator");\n
-    if ( idIsArray)\n
-    {\n
-      for ( i = id.length; --i >= 0; )\n
-      {\n
-        toolbar[0].splice(0, 0, id[i]);\n
-      }\n
-    }\n
-    else\n
-    {\n
-      toolbar[0].splice(0, 0, id);\n
-    }\n
-  }\n
-};\n
-/** Alias of Xinha.Config.prototype.hideSomeButtons()\n
-* @type Function\n
-*/\n
-Xinha.Config.prototype.removeToolbarElement = Xinha.Config.prototype.hideSomeButtons;\n
-\n
-/** Helper function: replace all TEXTAREA-s in the document with Xinha-s. \n
-* @param {Xinha.Config} optional config \n
-*/\n
-Xinha.replaceAll = function(config)\n
-{\n
-  var tas = document.getElementsByTagName("textarea");\n
-  // @todo: weird syntax, doesnt help to read the code, doesnt obfuscate it and doesnt make it quicker, better rewrite this part\n
-  for ( var i = tas.length; i > 0; new Xinha(tas[--i], config).generate() )\n
-  {\n
-    // NOP\n
-  }\n
-};\n
-\n
-/** Helper function: replaces the TEXTAREA with the given ID with Xinha. \n
-* @param {string} id id of the textarea to replace \n
-* @param {Xinha.Config} optional config \n
-*/\n
-Xinha.replace = function(id, config)\n
-{\n
-  var ta = Xinha.getElementById("textarea", id);\n
-  return ta ? new Xinha(ta, config).generate() : null;\n
-};\n
- \n
-/** Creates the toolbar and appends it to the _htmlarea\n
-* @private\n
-* @returns {DomNode} toolbar\n
-*/\n
-Xinha.prototype._createToolbar = function ()\n
-{\n
-  this.setLoadingMessage(Xinha._lc(\'Create Toolbar\'));\n
-  var editor = this;\t// to access this in nested functions\n
-\n
-  var toolbar = document.createElement("div");\n
-  // ._toolbar is for legacy, ._toolBar is better thanks.\n
-  this._toolBar = this._toolbar = toolbar;\n
-  toolbar.className = "toolbar";  \n
-  toolbar.align = this.config.toolbarAlign;\n
-  \n
-  Xinha.freeLater(this, \'_toolBar\');\n
-  Xinha.freeLater(this, \'_toolbar\');\n
-  \n
-  var tb_row = null;\n
-  var tb_objects = {};\n
-  this._toolbarObjects = tb_objects;\n
-\n
-\tthis._createToolbar1(editor, toolbar, tb_objects);\n
-\t\n
-\t// IE8 is totally retarded, if you click on a toolbar element (eg button)\n
-\t// and it doesn\'t have unselectable="on", then it defocuses the editor losing the selection\n
-\t// so nothing works.  Particularly prevalent with TableOperations\n
-\tfunction noselect(e)\n
-\t{\n
-    if(e.tagName) e.unselectable = "on";        \n
-    if(e.childNodes)\n
-    {\n
-      for(var i = 0; i < e.childNodes.length; i++) if(e.tagName) noselect(e.childNodes(i));\n
-    }\n
-\t}\n
-\tif(Xinha.is_ie) noselect(toolbar);\n
-\t\n
-\t\n
-\tthis._htmlArea.appendChild(toolbar);      \n
-  \n
-  return toolbar;\n
-};\n
-\n
-/** FIXME : function never used, can probably be removed from source\n
-* @private\n
-* @deprecated\n
-*/\n
-Xinha.prototype._setConfig = function(config)\n
-{\n
-\tthis.config = config;\n
-};\n
-/** FIXME: How can this be used??\n
-* @private\n
-*/\n
-Xinha.prototype._rebuildToolbar = function()\n
-{\n
-\tthis._createToolbar1(this, this._toolbar, this._toolbarObjects);\n
-\n
-  // We only want ONE editor at a time to be active\n
-  if ( Xinha._currentlyActiveEditor )\n
-  {\n
-    if ( Xinha._currentlyActiveEditor == this )\n
-    {\n
-      this.activateEditor();\n
-    }\n
-  }\n
-  else\n
-  {\n
-    this.disableToolbar();\n
-  }\n
-};\n
-\n
-/**\n
- * Create a break element to add in the toolbar\n
- *\n
- * @return {DomNode} HTML element to add\n
- * @private\n
- */\n
-Xinha._createToolbarBreakingElement = function()\n
-{\n
-  var brk = document.createElement(\'div\');\n
-  brk.style.height = \'1px\';\n
-  brk.style.width = \'1px\';\n
-  brk.style.lineHeight = \'1px\';\n
-  brk.style.fontSize = \'1px\';\n
-  brk.style.clear = \'both\';\n
-  return brk;\n
-};\n
-\n
-\n
-/** separate from previous createToolBar to allow dynamic change of toolbar\n
- * @private\n
- * @return {DomNode} toolbar\n
- */\n
-Xinha.prototype._createToolbar1 = function (editor, toolbar, tb_objects)\n
-{\n
-  // We will clean out any existing toolbar elements.\n
-  while (toolbar.lastChild)\n
-  {\n
-    toolbar.removeChild(toolbar.lastChild);\n
-  }\n
-\n
-  var tb_row;\n
-  // This shouldn\'t be necessary, but IE seems to float outside of the container\n
-  // when we float toolbar sections, so we have to clear:both here as well\n
-  // as at the end (which we do have to do).\n
-  if ( editor.config.flowToolbars )\n
-  {\n
-    toolbar.appendChild(Xinha._createToolbarBreakingElement());\n
-  }\n
-\n
-  // creates a new line in the toolbar\n
-  function newLine()\n
-  {\n
-    if ( typeof tb_row != \'undefined\' && tb_row.childNodes.length === 0)\n
-    {\n
-      return;\n
-    }\n
-\n
-    var table = document.createElement("table");\n
-    table.border = "0px";\n
-    table.cellSpacing = "0px";\n
-    table.cellPadding = "0px";\n
-    if ( editor.config.flowToolbars )\n
-    {\n
-      if ( Xinha.is_ie )\n
-      {\n
-        table.style.styleFloat = "left";\n
-      }\n
-      else\n
-      {\n
-        table.style.cssFloat = "left";\n
-      }\n
-    }\n
-\n
-    toolbar.appendChild(table);\n
-    // TBODY is required for IE, otherwise you don\'t see anything\n
-    // in the TABLE.\n
-    var tb_body = document.createElement("tbody");\n
-    table.appendChild(tb_body);\n
-    tb_row = document.createElement("tr");\n
-    tb_body.appendChild(tb_row);\n
-\n
-    table.className = \'toolbarRow\'; // meh, kinda.\n
-  } // END of function: newLine\n
-\n
-  // init first line\n
-  newLine();\n
-\n
-  // updates the state of a toolbar element.  This function is member of\n
-  // a toolbar element object (unnamed objects created by createButton or\n
-  // createSelect functions below).\n
-  function setButtonStatus(id, newval)\n
-  {\n
-    var oldval = this[id];\n
-    var el = this.element;\n
-    if ( oldval != newval )\n
-    {\n
-      switch (id)\n
-      {\n
-        case "enabled":\n
-          if ( newval )\n
-          {\n
-            Xinha._removeClass(el, "buttonDisabled");\n
-            el.disabled = false;\n
-          }\n
-          else\n
-          {\n
-            Xinha._addClass(el, "buttonDisabled");\n
-            el.disabled = true;\n
-          }\n
-        break;\n
-        case "active":\n
-          if ( newval )\n
-          {\n
-            Xinha._addClass(el, "buttonPressed");\n
-          }\n
-          else\n
-          {\n
-            Xinha._removeClass(el, "buttonPressed");\n
-          }\n
-        break;\n
-      }\n
-      this[id] = newval;\n
-    }\n
-  } // END of function: setButtonStatus\n
-\n
-  // this function will handle creation of combo boxes.  Receives as\n
-  // parameter the name of a button as defined in the toolBar config.\n
-  // This function is called from createButton, above, if the given "txt"\n
-  // doesn\'t match a button.\n
-  function createSelect(txt)\n
-  {\n
-    var options = null;\n
-    var el = null;\n
-    var cmd = null;\n
-    var customSelects = editor.config.customSelects;\n
-    var context = null;\n
-    var tooltip = "";\n
-    switch (txt)\n
-    {\n
-      case "fontsize":\n
-      case "fontname":\n
-      case "formatblock":\n
-        // the following line retrieves the correct\n
-        // configuration option because the variable name\n
-        // inside the Config object is named the same as the\n
-        // button/select in the toolbar.  For instance, if txt\n
-        // == "formatblock" we retrieve config.formatblock (or\n
-        // a different way to write it in JS is\n
-        // config["formatblock"].\n
-        options = editor.config[txt];\n
-        cmd = txt;\n
-      break;\n
-      default:\n
-        // try to fetch it from the list of registered selects\n
-        cmd = txt;\n
-        var dropdown = customSelects[cmd];\n
-        if ( typeof dropdown != "undefined" )\n
-        {\n
-          options = dropdown.options;\n
-          context = dropdown.context;\n
-          if ( typeof dropdown.tooltip != "undefined" )\n
-          {\n
-            tooltip = dropdown.tooltip;\n
-          }\n
-        }\n
-        else\n
-        {\n
-          alert("ERROR [createSelect]:\\nCan\'t find the requested dropdown definition");\n
-        }\n
-      break;\n
-    }\n
-    if ( options )\n
-    {\n
-      el = document.createElement("select");\n
-      el.title = tooltip;\n
-      el.style.width = \'auto\';\n
-      el.name = txt;\n
-      var obj =\n
-      {\n
-        name\t: txt, // field name\n
-        element : el,\t// the UI element (SELECT)\n
-        enabled : true, // is it enabled?\n
-        text\t: false, // enabled in text mode?\n
-        cmd\t: cmd, // command ID\n
-        state\t: setButtonStatus, // for changing state\n
-        context : context\n
-      };\n
-      \n
-      Xinha.freeLater(obj);\n
-      \n
-      tb_objects[txt] = obj;\n
-      \n
-      for ( var i in options )\n
-      {\n
-        // prevent iterating over wrong type\n
-        if ( typeof options[i] != \'string\' )\n
-        {\n
-          continue;\n
-        }\n
-        var op = document.createElement("option");\n
-        op.innerHTML = Xinha._lc(i);\n
-        op.value = options[i];\n
-        if (txt ==\'fontname\' && editor.config.showFontStylesInToolbar)\n
-        {\n
-          op.style.fontFamily = options[i];\n
-        }\n
-        el.appendChild(op);\n
-      }\n
-      Xinha._addEvent(el, "change", function () { editor._comboSelected(el, txt); } );\n
-    }\n
-    return el;\n
-  } // END of function: createSelect\n
-\n
-  // appends a new button to toolbar\n
-  function createButton(txt)\n
-  {\n
-    // the element that will be created\n
-    var el, btn, obj = null;\n
-    switch (txt)\n
-    {\n
-      case "separator":\n
-        if ( editor.config.flowToolbars )\n
-        {\n
-          newLine();\n
-        }\n
-        el = document.createElement("div");\n
-        el.className = "separator";\n
-      break;\n
-      case "space":\n
-        el = document.createElement("div");\n
-        el.className = "space";\n
-      break;\n
-      case "linebreak":\n
-        newLine();\n
-        return false;\n
-      case "textindicator":\n
-        el = document.createElement("div");\n
-        el.appendChild(document.createTextNode("A"));\n
-        el.className = "indicator";\n
-        el.title = Xinha._lc("Current style");\n
-        obj =\n
-        {\n
-          name\t: txt, // the button name (i.e. \'bold\')\n
-          element : el, // the UI element (DIV)\n
-          enabled : true, // is it enabled?\n
-          active\t: false, // is it pressed?\n
-          text\t: false, // enabled in text mode?\n
-          cmd\t: "textindicator", // the command ID\n
-          state\t: setButtonStatus // for changing state\n
-        };\n
-      \n
-        Xinha.freeLater(obj);\n
-      \n
-        tb_objects[txt] = obj;\n
-      break;\n
-      default:\n
-        btn = editor.config.btnList[txt];\n
-    }\n
-    if ( !el && btn )\n
-    {\n
-      el = document.createElement("a");\n
-      el.style.display = \'block\';\n
-      el.href = \'javascript:void(0)\';\n
-      el.style.textDecoration = \'none\';\n
-      el.title = btn[0];\n
-      el.className = "button";\n
-      el.style.direction = "ltr";\n
-      // let\'s just pretend we have a button object, and\n
-      // assign all the needed information to it.\n
-      obj =\n
-      {\n
-        name : txt, // the button name (i.e. \'bold\')\n
-        element : el, // the UI element (DIV)\n
-        enabled : true, // is it enabled?\n
-        active : false, // is it pressed?\n
-        text : btn[2], // enabled in text mode?\n
-        cmd\t: btn[3], // the command ID\n
-        state\t: setButtonStatus, // for changing state\n
-        context : btn[4] || null // enabled in a certain context?\n
-      };\n
-      Xinha.freeLater(el);\n
-      Xinha.freeLater(obj);\n
-\n
-      tb_objects[txt] = obj;\n
-\n
-      // prevent drag&drop of the icon to content area\n
-      el.ondrag = function() { return false; };\n
-\n
-      // handlers to emulate nice flat toolbar buttons\n
-      Xinha._addEvent(\n
-        el,\n
-        "mouseout",\n
-        function(ev)\n
-        {\n
-          if ( obj.enabled )\n
-          {\n
-            //Xinha._removeClass(el, "buttonHover");\n
-            Xinha._removeClass(el, "buttonActive");\n
-            if ( obj.active )\n
-            {\n
-              Xinha._addClass(el, "buttonPressed");\n
-            }\n
-          }\n
-        }\n
-      );\n
-\n
-      Xinha._addEvent(\n
-        el,\n
-        "mousedown",\n
-        function(ev)\n
-        {\n
-          if ( obj.enabled )\n
-          {\n
-            Xinha._addClass(el, "buttonActive");\n
-            Xinha._removeClass(el, "buttonPressed");\n
-            Xinha._stopEvent(Xinha.is_ie ? window.event : ev);\n
-          }\n
-        }\n
-      );\n
-\n
-      // when clicked, do the following:\n
-      Xinha._addEvent(\n
-        el,\n
-        "click",\n
-        function(ev)\n
-        {\n
-          ev = ev || window.event;\n
-          editor.btnClickEvent = {clientX : ev.clientX, clientY : ev.clientY};\n
-          if ( obj.enabled )\n
-          {\n
-            Xinha._removeClass(el, "buttonActive");\n
-            //Xinha._removeClass(el, "buttonHover");\n
-            if ( Xinha.is_gecko )\n
-            {\n
-              editor.activateEditor();\n
-            }\n
-            // We pass the event to the action so they can can use it to\n
-            // enhance the UI (e.g. respond to shift or ctrl-click)\n
-            obj.cmd(editor, obj.name, obj, ev);\n
-            Xinha._stopEvent(ev);\n
-          }\n
-        }\n
-      );\n
-\n
-      var i_contain = Xinha.makeBtnImg(btn[1]);\n
-      var img = i_contain.firstChild;\n
-      Xinha.freeLater(i_contain);\n
-      Xinha.freeLater(img);\n
-      \n
-      el.appendChild(i_contain);\n
-\n
-      obj.imgel = img;      \n
-      obj.swapImage = function(newimg)\n
-      {\n
-        if ( typeof newimg != \'string\' )\n
-        {\n
-          img.src = newimg[0];\n
-          img.style.position = \'relative\';\n
-          img.style.top  = newimg[2] ? (\'-\' + (18 * (newimg[2] + 1)) + \'px\') : \'-18px\';\n
-          img.style.left = newimg[1] ? (\'-\' + (18 * (newimg[1] + 1)) + \'px\') : \'-18px\';\n
-        }\n
-        else\n
-        {\n
-          obj.imgel.src = newimg;\n
-          img.style.top = \'0px\';\n
-          img.style.left = \'0px\';\n
-        }\n
-      };\n
-      \n
-    }\n
-    else if( !el )\n
-    {\n
-      el = createSelect(txt);\n
-    }\n
-\n
-    return el;\n
-  }\n
-\n
-  var first = true;\n
-  for ( var i = 0; i < this.config.toolbar.length; ++i )\n
-  {\n
-    if ( !first )\n
-    {\n
-      // createButton("linebreak");\n
-    }\n
-    else\n
-    {\n
-      first = false;\n
-    }\n
-    if ( this.config.toolbar[i] === null )\n
-    {\n
-      this.config.toolbar[i] = [\'separator\'];\n
-    }\n
-    var group = this.config.toolbar[i];\n
-\n
-    for ( var j = 0; j < group.length; ++j )\n
-    {\n
-      var code = group[j];\n
-      var tb_cell;\n
-      if ( /^([IT])\\[(.*?)\\]/.test(code) )\n
-      {\n
-        // special case, create text label\n
-        var l7ed = RegExp.$1 == "I"; // localized?\n
-        var label = RegExp.$2;\n
-        if ( l7ed )\n
-        {\n
-          label = Xinha._lc(label);\n
-        }\n
-        tb_cell = document.createElement("td");\n
-        tb_row.appendChild(tb_cell);\n
-        tb_cell.className = "label";\n
-        tb_cell.innerHTML = label;\n
-      }\n
-      else if ( typeof code != \'function\' )\n
-      {\n
-        var tb_element = createButton(code);\n
-        if ( tb_element )\n
-        {\n
-          tb_cell = document.createElement("td");\n
-          tb_cell.className = \'toolbarElement\';\n
-          tb_row.appendChild(tb_cell);\n
-          tb_cell.appendChild(tb_element);\n
-        }\n
-        else if ( tb_element === null )\n
-        {\n
-          alert("FIXME: Unknown toolbar item: " + code);\n
-        }\n
-      }\n
-    }\n
-  }\n
-\n
-  if ( editor.config.flowToolbars )\n
-  {\n
-    toolbar.appendChild(Xinha._createToolbarBreakingElement());\n
-  }\n
-\n
-  return toolbar;\n
-};\n
-\n
-/** creates a button (i.e. container element + image)\n
- * @private\n
- * @return {DomNode} conteainer element\n
- */\n
-Xinha.makeBtnImg = function(imgDef, doc)\n
-{\n
-  if ( !doc )\n
-  {\n
-    doc = document;\n
-  }\n
-\n
-  if ( !doc._xinhaImgCache )\n
-  {\n
-    doc._xinhaImgCache = {};\n
-    Xinha.freeLater(doc._xinhaImgCache);\n
-  }\n
-\n
-  var i_contain = null;\n
-  if ( Xinha.is_ie && ( ( !doc.compatMode ) || ( doc.compatMode && doc.compatMode == "BackCompat" ) ) )\n
-  {\n
-    i_contain = doc.createElement(\'span\');\n
-  }\n
-  else\n
-  {\n
-    i_contain = doc.createElement(\'div\');\n
-    i_contain.style.position = \'relative\';\n
-  }\n
-\n
-  i_contain.style.overflow = \'hidden\';\n
-  i_contain.style.width = "18px";\n
-  i_contain.style.height = "18px";\n
-  i_contain.className = \'buttonImageContainer\';\n
-\n
-  var img = null;\n
-  if ( typeof imgDef == \'string\' )\n
-  {\n
-    if ( doc._xinhaImgCache[imgDef] )\n
-    {\n
-      img = doc._xinhaImgCache[imgDef].cloneNode();\n
-    }\n
-    else\n
-    {\n
-      if (Xinha.ie_version < 7 && /\\.png$/.test(imgDef[0]))\n
-      {\n
-        img = doc.createElement("span");\n
-      \n
-        img.style.display = \'block\';\n
-        img.style.width = \'18px\';\n
-        img.style.height = \'18px\';\n
-        img.style.filter = \'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="\'+imgDef+\'")\';\n
-\t\timg.unselectable = \'on\';\n
-      }\n
-      else\n
-      {\n
-        img = doc.createElement("img");\n
-        img.src = imgDef;\n
-      }\n
-    }\n
-  }\n
-  else\n
-  {\n
-    if ( doc._xinhaImgCache[imgDef[0]] )\n
-    {\n
-      img = doc._xinhaImgCache[imgDef[0]].cloneNode();\n
-    }\n
-    else\n
-    {\n
-      if (Xinha.ie_version < 7 && /\\.png$/.test(imgDef[0]))\n
-      {\n
-        img = doc.createElement("span");\n
-        img.style.display = \'block\';\n
-        img.style.width = \'18px\';\n
-        img.style.height = \'18px\';\n
-        img.style.filter = \'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="\'+imgDef[0]+\'")\';\n
-\t\timg.unselectable = \'on\';\n
-      }\n
-      else\n
-      {\n
-        img = doc.createElement("img");\n
-        img.src = imgDef[0];\n
-      }\n
-      img.style.position = \'relative\';\n
-    }\n
-    // @todo: Using 18 dont let us use a theme with its own icon toolbar height\n
-    //        and width. Probably better to calculate this value 18\n
-    //        var sizeIcon = img.width / nb_elements_per_image;\n
-    img.style.top  = imgDef[2] ? (\'-\' + (18 * (imgDef[2] + 1)) + \'px\') : \'-18px\';\n
-    img.style.left = imgDef[1] ? (\'-\' + (18 * (imgDef[1] + 1)) + \'px\') : \'-18px\';\n
-  }\n
-  i_contain.appendChild(img);\n
-  return i_contain;\n
-};\n
-/** creates the status bar \n
- * @private\n
- * @return {DomNode} status bar\n
- */\n
-Xinha.prototype._createStatusBar = function()\n
-{\n
-  // TODO: Move styling into separate stylesheet\n
-  this.setLoadingMessage(Xinha._lc(\'Create Statusbar\'));\n
-  var statusBar = document.createElement("div");\n
-  statusBar.style.position = "relative";\n
-  statusBar.className = "statusBar";\n
-  statusBar.style.width = "100%";\n
-  Xinha.freeLater(this, \'_statusBar\');\n
-\n
-  var widgetContainer = document.createElement("div");\n
-  widgetContainer.className = "statusBarWidgetContainer";\n
-  widgetContainer.style.position = "absolute";\n
-  widgetContainer.style.right = "0";\n
-  widgetContainer.style.top = "0";\n
-  widgetContainer.style.padding = "3px 3px 3px 10px";\n
-  statusBar.appendChild(widgetContainer);\n
-\n
-  // statusbar.appendChild(document.createTextNode(Xinha._lc("Path") + ": "));\n
-  // creates a holder for the path view\n
-  var statusBarTree = document.createElement("span");\n
-  statusBarTree.className = "statusBarTree";\n
-  statusBarTree.innerHTML = Xinha._lc("Path") + ": ";\n
-\n
-  this._statusBarTree = statusBarTree;\n
-  Xinha.freeLater(this, \'_statusBarTree\');\n
-  statusBar.appendChild(statusBarTree);\n
-  var statusBarTextMode = document.createElement("span");\n
-  statusBarTextMode.innerHTML = Xinha.htmlEncode(Xinha._lc("You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG."));\n
-  statusBarTextMode.style.display = "none";\n
-\n
-  this._statusBarTextMode = statusBarTextMode;\n
-  Xinha.freeLater(this, \'_statusBarTextMode\');\n
-  statusBar.appendChild(statusBarTextMode);\n
-\n
-  statusBar.style.whiteSpace = "nowrap";\n
-\n
-  var self = this;\n
-  this.notifyOn("before_resize", function(evt, size) {\n
-    self._statusBar.style.width = null;\n
-  });\n
-  this.notifyOn("resize", function(evt, size) {\n
-    // HACK! IE6 doesn\'t update the width properly when resizing if it\'s \n
-    // given in pixels, but does hide the overflow content correctly when \n
-    // using 100% as the width. (FF, Safari and IE7 all require fixed\n
-    // pixel widths to do the overflow hiding correctly.)\n
-    if (Xinha.is_ie && Xinha.ie_version == 6)\n
-    {\n
-      self._statusBar.style.width = "100%";\n
-    } \n
-    else\n
-    {\n
-      var width = size[\'width\'];\n
-      self._statusBar.style.width = width + "px";\n
-    }\n
-  });\n
-\n
-  this.notifyOn("modechange", function(evt, mode) {\n
-    // Loop through all registered status bar items\n
-    // and show them only if they\'re turned on for\n
-    // the new mode.\n
-    for (var i in self._statusWidgets)\n
-    {\n
-      var widget = self._statusWidgets[i];\n
-      for (var index=0; index<widget.modes.length; index++)\n
-      {\n
-        if (widget.modes[index] == mode.mode)\n
-        {\n
-          var found = true;\n
-        }\n
-      }\n
-      if (typeof found == \'undefined\')\n
-      {\n
-        widget.block.style.display = "none";  \n
-      }\n
-      else\n
-      {\n
-        widget.block.style.display = "";\n
-      }\n
-    }\n
-  });\n
-\n
-  if ( !this.config.statusBar )\n
-  {\n
-    // disable it...\n
-    statusBar.style.display = "none";\n
-  }\n
-  return statusBar;\n
-};\n
-\n
-/** Registers and inserts a new block for a widget in the status bar\n
- @param id unique string identifer for this block\n
- @param modes list of modes this block should be shown in\n
-\n
- @returns reference to HTML element inserted into the status bar\n
- */\n
-Xinha.prototype.registerStatusWidget = function(id, modes)\n
-{\n
-  modes = modes || [\'wysiwyg\'];\n
-  if (!this._statusWidgets)\n
-  {\n
-    this._statusWidgets = {};\n
-  }\n
-\n
-  var block = document.createElement("div");\n
-  block.className = "statusBarWidget";\n
-  block = this._statusBar.firstChild.appendChild(block);\n
-\n
-  var showWidget = false;\n
-  for (var i=0; i<modes.length; i++)\n
-  {\n
-    if (modes[i] == this._editMode)\n
-    {\n
-      showWidget = true;\n
-    }\n
-  }\n
-  block.style.display = showWidget == true ? "" : "none";\n
-\n
-  this._statusWidgets[id] = {block: block, modes: modes};\n
-  return block;\n
-};\n
-\n
-/** Creates the Xinha object and replaces the textarea with it. Loads required files.\n
- *  @returns {Boolean}\n
- */\n
-Xinha.prototype.generate = function ()\n
-{\n
-  if ( !Xinha.isSupportedBrowser )\n
-  {\n
-    return;\n
-  }\n
-  \n
-  var i;\n
-  var editor = this;  // we\'ll need "this" in some nested functions\n
-  var url;\n
-  var found = false;\n
-  var links = document.getElementsByTagName("link");\n
-\n
-  if (!document.getElementById("XinhaCoreDesign"))\n
-  {\n
-    _editor_css = (typeof _editor_css == "string") ? _editor_css : "Xinha.css";\n
-    for(i = 0; i<links.length; i++)\n
-    {\n
-      if ( ( links[i].rel == "stylesheet" ) && ( links[i].href == _editor_url + _editor_css ) )\n
-      {\n
-        found = true;\n
-      }\n
-    }\n
-    if ( !found )\n
-    {\n
-      Xinha.loadStyle(_editor_css,null,"XinhaCoreDesign",true);\n
-    }\n
-  }\n
-  \n
-  if ( _editor_skin !== "" && !document.getElementById("XinhaSkin"))\n
-  {\n
-    found = false;\n
-    for(i = 0; i<links.length; i++)\n
-    {\n
-      if ( ( links[i].rel == "stylesheet" ) && ( links[i].href == _editor_url + \'skins/\' + _editor_skin + \'/skin.css\' ) )\n
-      {\n
-        found = true;\n
-      }\n
-    }\n
-    if ( !found )\n
-    {\n
-      Xinha.loadStyle(\'skins/\' + _editor_skin + \'/skin.css\',null,"XinhaSkin");\n
-    }\n
-  }\n
-  var callback = function() { editor.generate(); };\n
-  // Now load a specific browser plugin which will implement the above for us.\n
-  if (Xinha.is_ie)\n
-  {\n
-    url = _editor_url + \'modules/InternetExplorer/InternetExplorer.js\';\n
-    if ( !Xinha.loadPlugins([{plugin:"InternetExplorer",url:url}], callback ) )\n
-    {            \n
-      return false;\n
-    }\n
-    if (!this.plugins.InternetExplorer)\n
-    {\n
-      editor._browserSpecificPlugin = editor.registerPlugin(\'InternetExplorer\');\n
-    }\n
-  }\n
-  else if (Xinha.is_webkit)\n
-  {\n
-    url = _editor_url + \'modules/WebKit/WebKit.js\';\n
-    if ( !Xinha.loadPlugins([{plugin:"WebKit",url:url}], callback ) )\n
-    {\n
-      return false;\n
-    }\n
-    if (!this.plugins.Webkit)\n
-    {\n
-      editor._browserSpecificPlugin = editor.registerPlugin(\'WebKit\');\n
-    }\n
-  }\n
-  else if (Xinha.is_opera)\n
-  {\n
-    url = _editor_url + \'modules/Opera/Opera.js\';\n
-    if ( !Xinha.loadPlugins([{plugin:"Opera",url:url}], callback ) )\n
-    {            \n
-      return false;\n
-    }\n
-    if (!this.plugins.Opera)\n
-    {\n
-      editor._browserSpecificPlugin = editor.registerPlugin(\'Opera\');\n
-    }\n
-  }\n
-  else if (Xinha.is_gecko)\n
-  {\n
-    url = _editor_url + \'modules/Gecko/Gecko.js\';\n
-    if ( !Xinha.loadPlugins([{plugin:"Gecko",url:url}], callback ) )\n
-    {            \n
-      return false;\n
-    }\n
-    if (!this.plugins.Gecko) \n
-    {\n
-      editor._browserSpecificPlugin = editor.registerPlugin(\'Gecko\');\n
-    }\n
-  }\n
-\n
-  if ( typeof Dialog == \'undefined\' && !Xinha._loadback( _editor_url + \'modules/Dialogs/dialog.js\', callback, this ) )\n
-  {    \n
-    return false;\n
-  }\n
-\n
-  if ( typeof Xinha.Dialog == \'undefined\' &&  !Xinha._loadback( _editor_url + \'modules/Dialogs/XinhaDialog.js\' , callback, this ) )\n
-  {    \n
-    return false;\n
-  }\n
-  \n
-  url = _editor_url + \'modules/FullScreen/full-screen.js\';\n
-  if ( !Xinha.loadPlugins([{plugin:"FullScreen",url:url}], callback ))\n
-  {\n
-    return false;\n
-  }\n
-  \n
-  url = _editor_url + \'modules/ColorPicker/ColorPicker.js\';\n
-  if ( !Xinha.loadPlugins([{plugin:"ColorPicker",url:url}], callback ) )\n
-  {\n
-    return false;\n
-  }\n
-  else if ( typeof Xinha.getPluginConstructor(\'ColorPicker\') != \'undefined\' && !this.plugins.colorPicker)\n
-  {\n
-    editor.registerPlugin(\'ColorPicker\');\n
-  }\n
-\n
-  var toolbar = editor.config.toolbar;\n
-  for ( i = toolbar.length; --i >= 0; )\n
-  {\n
-    for ( var j = toolbar[i].length; --j >= 0; )\n
-    {\n
-      switch (toolbar[i][j])\n
-      {\n
-        case "popupeditor":\n
-          if (!this.plugins.FullScreen) \n
-          {\n
-            editor.registerPlugin(\'FullScreen\');\n
-          }\n
-        break;\n
-        case "insertimage":\n
-          url = _editor_url + \'modules/InsertImage/insert_image.js\';\n
-          if ( typeof Xinha.prototype._insertImage == \'undefined\' && !Xinha.loadPlugins([{plugin:"InsertImage",url:url}], callback ) )\n
-          {\n
-            return false;\n
-          }\n
-          else if ( typeof Xinha.getPluginConstructor(\'InsertImage\') != \'undefined\' && !this.plugins.InsertImage)\n
-          {\n
-            editor.registerPlugin(\'InsertImage\');\n
-          }\n
-        break;\n
-        case "createlink":\n
-          url = _editor_url + \'modules/CreateLink/link.js\';\n
-          if ( typeof Xinha.getPluginConstructor(\'Linker\') == \'undefined\' && !Xinha.loadPlugins([{plugin:"CreateLink",url:url}], callback ))\n
-          {\n
-            return false;\n
-          }\n
-          else if ( typeof Xinha.getPluginConstructor(\'CreateLink\') != \'undefined\' && !this.plugins.CreateLink) \n
-          {\n
-            editor.registerPlugin(\'CreateLink\');\n
-          }\n
-        break;\n
-        case "inserttable":\n
-          url = _editor_url + \'modules/InsertTable/insert_table.js\';\n
-          if ( !Xinha.loadPlugins([{plugin:"InsertTable",url:url}], callback ) )\n
-          {\n
-            return false;\n
-          }\n
-          else if ( typeof Xinha.getPluginConstructor(\'InsertTable\') != \'undefined\' && !this.plugins.InsertTable)\n
-          {\n
-            editor.registerPlugin(\'InsertTable\');\n
-          }\n
-        break;\n
-        case "about":\n
-          url = _editor_url + \'modules/AboutBox/AboutBox.js\';\n
-          if ( !Xinha.loadPlugins([{plugin:"AboutBox",url:url}], callback ) )\n
-          {\n
-            return false;\n
-          }\n
-          else if ( typeof Xinha.getPluginConstructor(\'AboutBox\') != \'undefined\' && !this.plugins.AboutBox)\n
-          {\n
-            editor.registerPlugin(\'AboutBox\');\n
-          }\n
-        break;\n
-      }\n
-    }\n
-  }\n
-\n
-  // If this is gecko, set up the paragraph handling now\n
-  if ( Xinha.is_gecko &&  editor.config.mozParaHandler != \'built-in\' )\n
-  {\n
-    if (  !Xinha.loadPlugins([{plugin:"EnterParagraphs",url: _editor_url + \'modules/Gecko/paraHandlerBest.js\'}], callback ) )\n
-    {\n
-      return false;\n
-    }\n
-    if (!this.plugins.EnterParagraphs) \n
-    {\n
-      editor.registerPlugin(\'EnterParagraphs\');\n
-    }\n
-  }\n
-  var getHtmlMethodPlugin = this.config.getHtmlMethod == \'TransformInnerHTML\' ? _editor_url + \'modules/GetHtml/TransformInnerHTML.js\' :  _editor_url + \'modules/GetHtml/DOMwalk.js\';\n
-\n
-  if ( !Xinha.loadPlugins([{plugin:"GetHtmlImplementation",url:getHtmlMethodPlugin}], callback))\n
-  {\n
-    return false;\n
-  }\n
-  else if (!this.plugins.GetHtmlImplementation)\n
-  {\n
-    editor.registerPlugin(\'GetHtmlImplementation\');\n
-  }\n
-  function getTextContent(node)\n
-  {\n
-    return node.textContent || node.text;\n
-  }\n
-  if (_editor_skin)\n
-  {\n
-    this.skinInfo = {};\n
-    var skinXML = Xinha._geturlcontent(_editor_url + \'skins/\' + _editor_skin + \'/skin.xml\', true);\n
-    if (skinXML)\n
-    {\n
-      var meta = skinXML.getElementsByTagName(\'meta\');\n
-      for (i=0;i<meta.length;i++)\n
-      {\n
-        this.skinInfo[meta[i].getAttribute(\'name\')] = meta[i].getAttribute(\'value\');\n
-      }\n
-      var recommendedIcons = skinXML.getElementsByTagName(\'recommendedIcons\');\n
-      if (!_editor_icons && recommendedIcons.length && getTextContent(recommendedIcons[0]))\n
-      {\n
-        _editor_icons = getTextContent(recommendedIcons[0]);\n
-      }\n
-    }\n
-  }\n
-  if (_editor_icons) \n
-  {\n
-    var iconsXML = Xinha._geturlcontent(_editor_url + \'iconsets/\' + _editor_icons + \'/iconset.xml\', true);\n
-\n
-    if (iconsXML)\n
-    {\n
-      var icons = iconsXML.getElementsByTagName(\'icon\');\n
-      var icon, id, path, type, x, y;\n
-\n
-      for (i=0;i<icons.length;i++)\n
-      {\n
-        icon = icons[i];\n
-        id = icon.getAttribute(\'id\');\n
-        \n
-        if (icon.getElementsByTagName(_editor_lang).length)\n
-        {\n
-          icon = icon.getElementsByTagName(_editor_lang)[0];\n
-        }\n
-        else\n
-        {\n
-          icon = icon.getElementsByTagName(\'default\')[0];\n
-        }\n
-        path = getTextContent(icon.getElementsByTagName(\'path\')[0]);\n
-        path = (!/^\\//.test(path) ? _editor_url : \'\') + path;\n
-        type = icon.getAttribute(\'type\');\n
-        if (type == \'map\')\n
-        {\n
-          x = parseInt(getTextContent(icon.getElementsByTagName(\'x\')[0]), 10);\n
-          y = parseInt(getTextContent(icon.getElementsByTagName(\'y\')[0]), 10);\n
-          if (this.config.btnList[id]) \n
-          {\n
-            this.config.btnList[id][1] = [path, x, y];\n
-          }\n
-          if (this.config.iconList[id]) \n
-          {\n
-            this.config.iconList[id] = [path, x, y];\n
-          }\n
-          \n
-        }\n
-        else\n
-        {\n
-          if (this.config.btnList[id]) \n
-          {\n
-            this.config.btnList[id][1] = path;\n
-          }\n
-          if (this.config.iconList[id]) \n
-          {\n
-            this.config.iconList[id] = path;\n
-          }\n
-        }\n
-      }\n
-    }\n
-  }\n
-  \n
-  // create the editor framework, yah, table layout I know, but much easier\n
-  // to get it working correctly this way, sorry about that, patches welcome.\n
-  \n
-  this.setLoadingMessage(Xinha._lc(\'Generate Xinha framework\'));\n
-  \n
-  this._framework =\n
-  {\n
-    \'table\':   document.createElement(\'table\'),\n
-    \'tbody\':   document.createElement(\'tbody\'), // IE will not show the table if it doesn\'t have a tbody!\n
-    \'tb_row\':  document.createElement(\'tr\'),\n
-    \'tb_cell\': document.createElement(\'td\'), // Toolbar\n
-\n
-    \'tp_row\':  document.createElement(\'tr\'),\n
-    \'tp_cell\': this._panels.top.container,   // top panel\n
-\n
-    \'ler_row\': document.createElement(\'tr\'),\n
-    \'lp_cell\': this._panels.left.container,  // left panel\n
-    \'ed_cell\': document.createElement(\'td\'), // editor\n
-    \'rp_cell\': this._panels.right.container, // right panel\n
-\n
-    \'bp_row\':  document.createElement(\'tr\'),\n
-    \'bp_cell\': this._panels.bottom.container,// bottom panel\n
-\n
-    \'sb_row\':  document.createElement(\'tr\'),\n
-    \'sb_cell\': document.createElement(\'td\')  // status bar\n
-\n
-  };\n
-  Xinha.freeLater(this._framework);\n
-  \n
-  var fw = this._framework;\n
-  fw.table.border = "0";\n
-  fw.table.cellPadding = "0";\n
-  fw.table.cellSpacing = "0";\n
-\n
-  fw.tb_row.style.verticalAlign = \'top\';\n
-  fw.tp_row.style.verticalAlign = \'top\';\n
-  fw.ler_row.style.verticalAlign= \'top\';\n
-  fw.bp_row.style.verticalAlign = \'top\';\n
-  fw.sb_row.style.verticalAlign = \'top\';\n
-  fw.ed_cell.style.position     = \'relative\';\n
-\n
-  // Put the cells in the rows        set col & rowspans\n
-  // note that I\'ve set all these so that all panels are showing\n
-  // but they will be redone in sizeEditor() depending on which\n
-  // panels are shown.  It\'s just here to clarify how the thing\n
-  // is put togethor.\n
-  fw.tb_row.appendChild(fw.tb_cell);\n
-  fw.tb_cell.colSpan = 3;\n
-\n
-  fw.tp_row.appendChild(fw.tp_cell);\n
-  fw.tp_cell.colSpan = 3;\n
-\n
-  fw.ler_row.appendChild(fw.lp_cell);\n
-  fw.ler_row.appendChild(fw.ed_cell);\n
-  fw.ler_row.appendChild(fw.rp_cell);\n
-\n
-  fw.bp_row.appendChild(fw.bp_cell);\n
-  fw.bp_cell.colSpan = 3;\n
-\n
-  fw.sb_row.appendChild(fw.sb_cell);\n
-  fw.sb_cell.colSpan = 3;\n
-\n
-  // Put the rows in the table body\n
-  fw.tbody.appendChild(fw.tb_row);  // Toolbar\n
-  fw.tbody.appendChild(fw.tp_row); // Left, Top, Right panels\n
-  fw.tbody.appendChild(fw.ler_row);  // Editor/Textarea\n
-  fw.tbody.appendChild(fw.bp_row);  // Bottom panel\n
-  fw.tbody.appendChild(fw.sb_row);  // Statusbar\n
-\n
-  // and body in the table\n
-  fw.table.appendChild(fw.tbody);\n
-\n
-  var xinha = fw.table;\n
-  this._htmlArea = xinha;\n
-  Xinha.freeLater(this, \'_htmlArea\');\n
-  xinha.className = "htmlarea";\n
-\n
-    // create the toolbar and put in the area\n
-  fw.tb_cell.appendChild( this._createToolbar() );\n
-\n
-    // create the IFRAME & add to container\n
-  var iframe = document.createElement("iframe");\n
-  iframe.src = this.popupURL(editor.config.URIs.blank);\n
-  iframe.id = "XinhaIFrame_" + this._textArea.id;\n
-  fw.ed_cell.appendChild(iframe);\n
-  this._iframe = iframe;\n
-  this._iframe.className = \'xinha_iframe\';\n
-  Xinha.freeLater(this, \'_iframe\');\n
-  \n
-    // creates & appends the status bar\n
-  var statusbar = this._createStatusBar();\n
-  this._statusBar = fw.sb_cell.appendChild(statusbar);\n
-\n
-\n
-  // insert Xinha before the textarea.\n
-  var textarea = this._textArea;\n
-  textarea.parentNode.insertBefore(xinha, textarea);\n
-  textarea.className = \'xinha_textarea\';\n
-\n
-  // extract the textarea and insert it into the xinha framework\n
-  Xinha.removeFromParent(textarea);\n
-  fw.ed_cell.appendChild(textarea);\n
-\n
-  // if another editor is activated while this one is in text mode, toolbar is disabled   \n
-  Xinha.addDom0Event(\n
-  this._textArea,\n
-  \'click\',\n
-  function()\n
-  {\n
-  \tif ( Xinha._currentlyActiveEditor != this)\n
-  \t{\n
-  \t  editor.updateToolbar();\n
-  \t}\n
-    return true;\n
-  });\n
-  \n
-  // Set up event listeners for saving the iframe content to the textarea\n
-  if ( textarea.form )\n
-  {\n
-    // onsubmit get the Xinha content and update original textarea.\n
-    Xinha.prependDom0Event(\n
-      this._textArea.form,\n
-      \'submit\',\n
-      function()\n
-      {\n
-        editor.firePluginEvent(\'onBeforeSubmit\');\n
-        editor._textArea.value = editor.outwardHtml(editor.getHTML());\n
-        return true;\n
-      }\n
-    );\n
-\n
-    var initialTAContent = textarea.value;\n
-\n
-    // onreset revert the Xinha content to the textarea content\n
-    Xinha.prependDom0Event(\n
-      this._textArea.form,\n
-      \'reset\',\n
-      function()\n
-      {\n
-        editor.setHTML(editor.inwardHtml(initialTAContent));\n
-        editor.updateToolbar();\n
-        return true;\n
-      }\n
-    );\n
-\n
-    // attach onsubmit handler to form.submit()\n
-    // note: catch error in IE if any form element has id="submit"\n
-    if ( !textarea.form.xinha_submit )\n
-    {\n
-      try \n
-      {\n
-        textarea.form.xinha_submit = textarea.form.submit;\n
-        textarea.form.submit = function() \n
-        {\n
-          this.onsubmit();\n
-          this.xinha_submit();\n
-        };\n
-      } catch(ex) {}\n
-    }\n
-  }\n
-\n
-  // add a handler for the "back/forward" case -- on body.unload we save\n
-  // the HTML content into the original textarea and restore it in its place.\n
-  // apparently this does not work in IE?\n
-  Xinha.prependDom0Event(\n
-    window,\n
-    \'unload\',\n
-    function()\n
-    {\n
-      editor.firePluginEvent(\'onBeforeUnload\');\n
-      textarea.value = editor.outwardHtml(editor.getHTML());\n
-      if (!Xinha.is_ie)\n
-      {\n
-        xinha.parentNode.replaceChild(textarea,xinha);\n
-      }\n
-      return true;\n
-    }\n
-  );\n
-\n
-  // Hide textarea\n
-  textarea.style.display = "none";\n
-\n
-  // Initalize size\n
-  editor.initSize();\n
-  this.setLoadingMessage(Xinha._lc(\'Finishing\'));\n
-  // Add an event to initialize the iframe once loaded.\n
-  editor._iframeLoadDone = false;\n
-  if (Xinha.is_opera) \n
-  {\n
-    editor.initIframe();\n
-  }\n
-  else \n
-  {\n
-    Xinha._addEvent(\n
-      this._iframe,\n
-      \'load\',\n
-      function(e)\n
-      {\n
-        if ( !editor._iframeLoadDone )\n
-        {\n
-          editor._iframeLoadDone = true;\n
-          editor.initIframe();\n
-        }\n
-        return true;\n
-      }\n
-    );\n
-  }\n
-};\n
-\n
-/**\n
- * Size the editor according to the INITIAL sizing information.\n
- * config.width\n
- *    The width may be set via three ways\n
- *    auto    = the width is inherited from the original textarea\n
- *    toolbar = the width is set to be the same size as the toolbar\n
- *    <set size> = the width is an explicit size (any CSS measurement, eg 100em should be fine)\n
- *\n
- * config.height\n
- *    auto    = the height is inherited from the original textarea\n
- *    <set size> = an explicit size measurement (again, CSS measurements)\n
- *\n
- * config.sizeIncludesBars\n
- *    true    = the tool & status bars will appear inside the width & height confines\n
- *    false   = the tool & status bars will appear outside the width & height confines\n
- *\n
- * @private\n
- */\n
-\n
-Xinha.prototype.initSize = function()\n
-{\n
-  this.setLoadingMessage(Xinha._lc(\'Init editor size\'));\n
-  var editor = this;\n
-  var width = null;\n
-  var height = null;\n
-\n
-  switch ( this.config.width )\n
-  {\n
-    case \'auto\':\n
-      width = this._initial_ta_size.w;\n
-    break;\n
-\n
-    case \'toolbar\':\n
-      width = this._toolBar.offsetWidth + \'px\';\n
-    break;\n
-\n
-    default :\n
-      // @todo: check if this is better :\n
-      // width = (parseInt(this.config.width, 10) == this.config.width)? this.config.width + \'px\' : this.config.width;\n
-      width = /[^0-9]/.test(this.config.width) ? this.config.width : this.config.width + \'px\';\n
-    break;\n
-  }\n
-      // @todo: check if this is better :\n
-      // height = (parseInt(this.config.height, 10) == this.config.height)? this.config.height + \'px\' : this.config.height;\n
-  height = this.config.height == \'auto\' ? this._initial_ta_size.h : /[^0-9]/.test(this.config.height) ? this.config.height : this.config.height + \'px\';\n
-  \n
-  this.sizeEditor(width, height, this.config.sizeIncludesBars, this.config.sizeIncludesPanels);\n
-\n
-  // why can\'t we use the following line instead ?\n
-//  this.notifyOn(\'panel_change\',this.sizeEditor);\n
-  this.notifyOn(\'panel_change\',function() { editor.sizeEditor(); });\n
-};\n
-\n
-/**\n
- *  Size the editor to a specific size, or just refresh the size (when window resizes for example)\n
- *  @param {string} width optional width (CSS specification)\n
- *  @param {string} height optional height (CSS specification)\n
- *  @param {Boolean} includingBars optional to indicate if the size should include or exclude tool & status bars\n
- *  @param {Boolean} includingPanels optional to indicate if the size should include or exclude panels\n
- */\n
-Xinha.prototype.sizeEditor = function(width, height, includingBars, includingPanels)\n
-{\n
-  if (this._risizing) \n
-  {\n
-    return;\n
-  }\n
-  this._risizing = true;\n
-  \n
-  var framework = this._framework;\n
-  \n
-  this.notifyOf(\'before_resize\', {width:width, height:height});\n
-  this.firePluginEvent(\'onBeforeResize\', width, height);\n
-  // We need to set the iframe & textarea to 100% height so that the htmlarea\n
-  // isn\'t "pushed out" when we get it\'s height, so we can change them later.\n
-  this._iframe.style.height   = \'100%\';\n
-  //here 100% can lead to an effect that the editor is considerably higher in text mode\n
-  this._textArea.style.height = \'1px\';\n
-  \n
-  this._iframe.style.width    = \'0px\';\n
-  this._textArea.style.width  = \'0px\';\n
-\n
-  if ( includingBars !== null )\n
-  {\n
-    this._htmlArea.sizeIncludesToolbars = includingBars;\n
-  }\n
-  if ( includingPanels !== null )\n
-  {\n
-    this._htmlArea.sizeIncludesPanels = includingPanels;\n
-  }\n
-\n
-  if ( width )\n
-  {\n
-    this._htmlArea.style.width = width;\n
-    if ( !this._htmlArea.sizeIncludesPanels )\n
-    {\n
-      // Need to add some for l & r panels\n
-      var rPanel = this._panels.right;\n
-      if ( rPanel.on && rPanel.panels.length && Xinha.hasDisplayedChildren(rPanel.div) )\n
-      {\n
-        this._htmlArea.style.width = (this._htmlArea.offsetWidth + parseInt(this.config.panel_dimensions.right, 10)) + \'px\';\n
-      }\n
-\n
-      var lPanel = this._panels.left;\n
-      if ( lPanel.on && lPanel.panels.length && Xinha.hasDisplayedChildren(lPanel.div) )\n
-      {\n
-        this._htmlArea.style.width = (this._htmlArea.offsetWidth + parseInt(this.config.panel_dimensions.left, 10)) + \'px\';\n
-      }\n
-    }\n
-  }\n
-\n
-  if ( height )\n
-  {\n
-    this._htmlArea.style.height = height;\n
-    if ( !this._htmlArea.sizeIncludesToolbars )\n
-    {\n
-      // Need to add some for toolbars\n
-      this._htmlArea.style.height = (this._htmlArea.offsetHeight + this._toolbar.offsetHeight + this._statusBar.offsetHeight) + \'px\';\n
-    }\n
-\n
-    if ( !this._htmlArea.sizeIncludesPanels )\n
-    {\n
-      // Need to add some for t & b panels\n
-      var tPanel = this._panels.top;\n
-      if ( tPanel.on && tPanel.panels.length && Xinha.hasDisplayedChildren(tPanel.div) )\n
-      {\n
-        this._htmlArea.style.height = (this._htmlArea.offsetHeight + parseInt(this.config.panel_dimensions.top, 10)) + \'px\';\n
-      }\n
-\n
-      var bPanel = this._panels.bottom;\n
-      if ( bPanel.on && bPanel.panels.length && Xinha.hasDisplayedChildren(bPanel.div) )\n
-      {\n
-        this._htmlArea.style.height = (this._htmlArea.offsetHeight + parseInt(this.config.panel_dimensions.bottom, 10)) + \'px\';\n
-      }\n
-    }\n
-  }\n
-\n
-  // At this point we have this._htmlArea.style.width & this._htmlArea.style.height\n
-  // which are the size for the OUTER editor area, including toolbars and panels\n
-  // now we size the INNER area and position stuff in the right places.\n
-  width  = this._htmlArea.offsetWidth;\n
-  height = this._htmlArea.offsetHeight;\n
-\n
-  // Set colspan for toolbar, and statusbar, rowspan for left & right panels, and insert panels to be displayed\n
-  // into thier rows\n
-  var panels = this._panels;\n
-  var editor = this;\n
-  var col_span = 1;\n
-\n
-  function panel_is_alive(pan)\n
-  {\n
-    if ( panels[pan].on && panels[pan].panels.length && Xinha.hasDisplayedChildren(panels[pan].container) )\n
-    {\n
-      panels[pan].container.style.display = \'\';\n
-      return true;\n
-    }\n
-    // Otherwise make sure it\'s been removed from the framework\n
-    else\n
-    {\n
-      panels[pan].container.style.display=\'none\';\n
-      return false;\n
-    }\n
-  }\n
-\n
-  if ( panel_is_alive(\'left\') )\n
-  {\n
-    col_span += 1;      \n
-  }\n
-\n
-//  if ( panel_is_alive(\'top\') )\n
-//  {\n
-    // NOP\n
-//  }\n
-\n
-  if ( panel_is_alive(\'right\') )\n
-  {\n
-    col_span += 1;\n
-  }\n
-\n
-//  if ( panel_is_alive(\'bottom\') )\n
-//  {\n
-    // NOP\n
-//  }\n
-\n
-  framework.tb_cell.colSpan = col_span;\n
-  framework.tp_cell.colSpan = col_span;\n
-  framework.bp_cell.colSpan = col_span;\n
-  framework.sb_cell.colSpan = col_span;\n
-\n
-  // Put in the panel rows, top panel goes above editor row\n
-  if ( !framework.tp_row.childNodes.length )\n
-  {\n
-    Xinha.removeFromParent(framework.tp_row);\n
-  }\n
-  else\n
-  {\n
-    if ( !Xinha.hasParentNode(framework.tp_row) )\n
-    {\n
-      framework.tbody.insertBefore(framework.tp_row, framework.ler_row);\n
-    }\n
-  }\n
-\n
-  // bp goes after the editor\n
-  if ( !framework.bp_row.childNodes.length )\n
-  {\n
-    Xinha.removeFromParent(framework.bp_row);\n
-  }\n
-  else\n
-  {\n
-    if ( !Xinha.hasParentNode(framework.bp_row) )\n
-    {\n
-      framework.tbody.insertBefore(framework.bp_row, framework.ler_row.nextSibling);\n
-    }\n
-  }\n
-\n
-  // finally if the statusbar is on, insert it\n
-  if ( !this.config.statusBar )\n
-  {\n
-    Xinha.removeFromParent(framework.sb_row);\n
-  }\n
-  else\n
-  {\n
-    if ( !Xinha.hasParentNode(framework.sb_row) )\n
-    {\n
-      framework.table.appendChild(framework.sb_row);\n
-    }\n
-  }\n
-\n
-  // Size and set colspans, link up the framework\n
-  framework.lp_cell.style.width  = this.config.panel_dimensions.left;\n
-  framework.rp_cell.style.width  = this.config.panel_dimensions.right;\n
-  framework.tp_cell.style.height = this.config.panel_dimensions.top;\n
-  framework.bp_cell.style.height = this.config.panel_dimensions.bottom;\n
-  framework.tb_cell.style.height = this._toolBar.offsetHeight + \'px\';\n
-  framework.sb_cell.style.height = this._statusBar.offsetHeight + \'px\';\n
-\n
-  var edcellheight = height - this._toolBar.offsetHeight - this._statusBar.offsetHeight;\n
-  if ( panel_is_alive(\'top\') )\n
-  {\n
-    edcellheight -= parseInt(this.config.panel_dimensions.top, 10);\n
-  }\n
-  if ( panel_is_alive(\'bottom\') )\n
-  {\n
-    edcellheight -= parseInt(this.config.panel_dimensions.bottom, 10);\n
-  }\n
-  this._iframe.style.height = edcellheight + \'px\';  \n
-  \n
-  var edcellwidth = width;\n
-  if ( panel_is_alive(\'left\') )\n
-  {\n
-    edcellwidth -= parseInt(this.config.panel_dimensions.left, 10);\n
-  }\n
-  if ( panel_is_alive(\'right\') )\n
-  {\n
-    edcellwidth -= parseInt(this.config.panel_dimensions.right, 10);    \n
-  }\n
-  var iframeWidth = this.config.iframeWidth ? parseInt(this.config.iframeWidth,10) : null; \n
-  this._iframe.style.width = (iframeWidth && iframeWidth < edcellwidth) ? iframeWidth + "px": edcellwidth + "px"; \n
-\n
-  this._textArea.style.height = this._iframe.style.height;\n
-  this._textArea.style.width  = this._iframe.style.width;\n
-     \n
-  this.notifyOf(\'resize\', {width:this._htmlArea.offsetWidth, height:this._htmlArea.offsetHeight});\n
-  this.firePluginEvent(\'onResize\',this._htmlArea.offsetWidth, this._htmlArea.offsetWidth);\n
-  this._risizing = false;\n
-};\n
-/** FIXME: Never used, what is this for? \n
-* @param {string} side \n
-* @param {Object}\n
-*/\n
-Xinha.prototype.registerPanel = function(side, object)\n
-{\n
-  if ( !side )\n
-  {\n
-    side = \'right\';\n
-  }\n
-  this.setLoadingMessage(\'Register \' + side + \' panel \');\n
-  var panel = this.addPanel(side);\n
-  if ( object )\n
-  {\n
-    object.drawPanelIn(panel);\n
-  }\n
-};\n
-/** Creates a panel in the panel container on the specified side\n
-* @param {String} side the panel container to which the new panel will be added<br />\n
-*\t\t\t\t\t\t\t\t\tPossible values are: "right","left","top","bottom"\n
-* @returns {DomNode} Panel div\n
-*/\n
-Xinha.prototype.addPanel = function(side)\n
-{\n
-  var div = document.createElement(\'div\');\n
-  div.side = side;\n
-  if ( side == \'left\' || side == \'right\' )\n
-  {\n
-    div.style.width  = this.config.panel_dimensions[side];\n
-    if (this._iframe) \n
-    {\n
-      div.style.height = this._iframe.style.height;\n
-    }\n
-  }\n
-  Xinha.addClasses(div, \'panel\');\n
-  this._panels[side].panels.push(div);\n
-  this._panels[side].div.appendChild(div);\n
-\n
-  this.notifyOf(\'panel_change\', {\'action\':\'add\',\'panel\':div});\n
-  this.firePluginEvent(\'onPanelChange\',\'add\',div);\n
-  return div;\n
-};\n
-/** Removes a panel\n
-* @param {DomNode} panel object as returned by Xinha.prototype.addPanel()\n
-*/\n
-Xinha.prototype.removePanel = function(panel)\n
-{\n
-  this._panels[panel.side].div.removeChild(panel);\n
-  var clean = [];\n
-  for ( var i = 0; i < this._panels[panel.side].panels.length; i++ )\n
-  {\n
-    if ( this._panels[panel.side].panels[i] != panel )\n
-    {\n
-      clean.push(this._panels[panel.side].panels[i]);\n
-    }\n
-  }\n
-  this._panels[panel.side].panels = clean;\n
-  this.notifyOf(\'panel_change\', {\'action\':\'remove\',\'panel\':panel});\n
-  this.firePluginEvent(\'onPanelChange\',\'remove\',panel);\n
-};\n
-/** Hides a panel\n
-* @param {DomNode} panel object as returned by Xinha.prototype.addPanel()\n
-*/\n
-Xinha.prototype.hidePanel = function(panel)\n
-{\n
-  if ( panel && panel.style.display != \'none\' )\n
-  {\n
-    try { var pos = this.scrollPos(this._iframe.contentWindow); } catch(e) { }\n
-    panel.style.display = \'none\';\n
-    this.notifyOf(\'panel_change\', {\'action\':\'hide\',\'panel\':panel});\n
-    this.firePluginEvent(\'onPanelChange\',\'hide\',panel);\n
-    try { this._iframe.contentWindow.scrollTo(pos.x,pos.y); } catch(e) { }\n
-  }\n
-};\n
-/** Shows a panel\n
-* @param {DomNode} panel object as returned by Xinha.prototype.addPanel()\n
-*/\n
-Xinha.prototype.showPanel = function(panel)\n
-{\n
-  if ( panel && panel.style.display == \'none\' )\n
-  {\n
-    try { var pos = this.scrollPos(this._iframe.contentWindow); } catch(e) {}\n
-    panel.style.display = \'\';\n
-    this.notifyOf(\'panel_change\', {\'action\':\'show\',\'panel\':panel});\n
-    this.firePluginEvent(\'onPanelChange\',\'show\',panel);\n
-    try { this._iframe.contentWindow.scrollTo(pos.x,pos.y); } catch(e) { }\n
-  }\n
-};\n
-/** Hides the panel(s) on one or more sides\n
-* @param {Array} sides the sides on which the panels shall be hidden\n
-*/\n
-Xinha.prototype.hidePanels = function(sides)\n
-{\n
-  if ( typeof sides == \'undefined\' )\n
-  {\n
-    sides = [\'left\',\'right\',\'top\',\'bottom\'];\n
-  }\n
-\n
-  var reShow = [];\n
-  for ( var i = 0; i < sides.length;i++ )\n
-  {\n
-    if ( this._panels[sides[i]].on )\n
-    {\n
-      reShow.push(sides[i]);\n
-      this._panels[sides[i]].on = false;\n
-    }\n
-  }\n
-  this.notifyOf(\'panel_change\', {\'action\':\'multi_hide\',\'sides\':sides});\n
-  this.firePluginEvent(\'onPanelChange\',\'multi_hide\',sides);\n
-};\n
-/** Shows the panel(s) on one or more sides\n
-* @param {Array} sides the sides on which the panels shall be hidden\n
-*/\n
-Xinha.prototype.showPanels = function(sides)\n
-{\n
-  if ( typeof sides == \'undefined\' )\n
-  {\n
-    sides = [\'left\',\'right\',\'top\',\'bottom\'];\n
-  }\n
-\n
-  var reHide = [];\n
-  for ( var i = 0; i < sides.length; i++ )\n
-  {\n
-    if ( !this._panels[sides[i]].on )\n
-    {\n
-      reHide.push(sides[i]);\n
-      this._panels[sides[i]].on = true;\n
-    }\n
-  }\n
-  this.notifyOf(\'panel_change\', {\'action\':\'multi_show\',\'sides\':sides});\n
-  this.firePluginEvent(\'onPanelChange\',\'multi_show\',sides);\n
-};\n
-/** Returns an array containig all properties that are set in an object\n
-* @param {Object} obj\n
-* @returns {Array}\n
-*/\n
-Xinha.objectProperties = function(obj)\n
-{\n
-  var props = [];\n
-  for ( var x in obj )\n
-  {\n
-    props[props.length] = x;\n
-  }\n
-  return props;\n
-};\n
-\n
-/** Checks if editor is active\n
- *<br />\n
- * EDITOR ACTIVATION NOTES:<br />\n
- *  when a page has multiple Xinha editors, ONLY ONE should be activated at any time (this is mostly to\n
- *  work around a bug in Mozilla, but also makes some sense).  No editor should be activated or focused\n
- *  automatically until at least one editor has been activated through user action (by mouse-clicking in\n
- *  the editor).\n
- * @private\n
- * @returns {Boolean}\n
- */\n
-Xinha.prototype.editorIsActivated = function()\n
-{\n
-  try\n
-  {\n
-    return Xinha.is_designMode ? this._doc.designMode == \'on\' : this._doc.body.contentEditable;\n
-  }\n
-  catch (ex)\n
-  {\n
-    return false;\n
-  }\n
-};\n
-/**  We need to know that at least one editor on the page has been activated\n
-*    this is because we will not focus any editor until an editor has been activated\n
-* @private\n
-* @type {Boolean}\n
-*/\n
-Xinha._someEditorHasBeenActivated = false;\n
-/**  Stores a reference to the currently active editor\n
-* @private\n
-* @type {Xinha}\n
-*/\n
-Xinha._currentlyActiveEditor      = null;\n
-/** Enables one editor for editing, e.g. by a click in the editing area or after it has been \n
- *  deactivated programmatically before \n
- * @private\n
- * @returns {Boolean}\n
- */\n
-Xinha.prototype.activateEditor = function()\n
-{\n
-  if (this.currentModal) \n
-  {\n
-    return;\n
-  }\n
-  // We only want ONE editor at a time to be active\n
-  if ( Xinha._currentlyActiveEditor )\n
-  {\n
-    if ( Xinha._currentlyActiveEditor == this )\n
-    {\n
-      return true;\n
-    }\n
-    Xinha._currentlyActiveEditor.deactivateEditor();\n
-  }\n
-\n
-  if ( Xinha.is_designMode && this._doc.designMode != \'on\' )\n
-  {\n
-    try\n
-    {\n
-      // cannot set design mode if no display\n
-      if ( this._iframe.style.display == \'none\' )\n
-      {\n
-        this._iframe.style.display = \'\';\n
-        this._doc.designMode = \'on\';\n
-        this._iframe.style.display = \'none\';\n
-      }\n
-      else\n
-      {\n
-        this._doc.designMode = \'on\';\n
-      }\n
-\n
-      // Opera loses some of it\'s event listeners when the designMode is set to on.\n
-\t  // the true just shortcuts the method to only set some listeners.\n
-      if(Xinha.is_opera) this.setEditorEvents(true);\n
-\n
-    } catch (ex) {}\n
-  }\n
-  else if ( Xinha.is_ie&& this._doc.body.contentEditable !== true )\n
-  {\n
-    this._doc.body.contentEditable = true;\n
-  }\n
-\n
-  Xinha._someEditorHasBeenActivated = true;\n
-  Xinha._currentlyActiveEditor      = this;\n
-\n
-  var editor = this;\n
-  this.enableToolbar();\n
-};\n
-/** Disables the editor \n
- * @private\n
- */\n
-Xinha.prototype.deactivateEditor = function()\n
-{\n
-  // If the editor isn\'t active then the user shouldn\'t use the toolbar\n
-  this.disableToolbar();\n
-\n
-  if ( Xinha.is_designMode && this._doc.designMode != \'off\' )\n
-  {\n
-    try\n
-    {\n
-      this._doc.designMode = \'off\';\n
-    } catch (ex) {}\n
-  }\n
-  else if ( !Xinha.is_designMode && this._doc.body.contentEditable !== false )\n
-  {\n
-    this._doc.body.contentEditable = false;\n
-  }\n
-\n
-  if ( Xinha._currentlyActiveEditor != this )\n
-  {\n
-    // We just deactivated an editor that wasn\'t marked as the currentlyActiveEditor\n
-\n
-    return; // I think this should really be an error, there shouldn\'t be a situation where\n
-            // an editor is deactivated without first being activated.  but it probably won\'t\n
-            // hurt anything.\n
-  }\n
-\n
-  Xinha._currentlyActiveEditor = false;\n
-};\n
-/** Creates the iframe (editable area)\n
- * @private\n
- */\n
-Xinha.prototype.initIframe = function()\n
-{\n
-  this.disableToolbar();\n
-  var doc = null;\n
-  var editor = this;\n
-  try\n
-  {\n
-    if ( editor._iframe.contentDocument )\n
-    {\n
-      this._doc = editor._iframe.contentDocument;        \n
-    }\n
-    else\n
-    {\n
-      this._doc = editor._iframe.contentWindow.document;\n
-    }\n
-    doc = this._doc;\n
-    // try later\n
-    if ( !doc )\n
-    {\n
-      if ( Xinha.is_gecko )\n
-      {\n
-        setTimeout(function() { editor.initIframe(); }, 50);\n
-        return false;\n
-      }\n
-      else\n
-      {\n
-        alert("ERROR: IFRAME can\'t be initialized.");\n
-      }\n
-    }\n
-  }\n
-  catch(ex)\n
-  { // try later\n
-    setTimeout(function() { editor.initIframe(); }, 50);\n
-    return false;\n
-  }\n
-  \n
-  Xinha.freeLater(this, \'_doc\');\n
-\n
-  doc.open("text/html","replace");\n
-  var html = \'\', doctype;\n
-  if ( editor.config.browserQuirksMode === false )\n
-  {\n
-    doctype = \'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\';\n
-  }\n
-  else if ( editor.config.browserQuirksMode === true )\n
-  {\n
-    doctype = \'\';\n
-  }\n
-  else\n
-  {\n
-    doctype = Xinha.getDoctype(document);\n
-  }\n
-  \n
-  if ( !editor.config.fullPage )\n
-  {\n
-    html += doctype + "\\n";\n
-    html += "<html>\\n";\n
-    html += "<head>\\n";\n
-    html += "<meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=" + editor.config.charSet + "\\">\\n";\n
-    if ( typeof editor.config.baseHref != \'undefined\' && editor.config.baseHref !== null )\n
-    {\n
-      html += "<base href=\\"" + editor.config.baseHref + "\\"/>\\n";\n
-    }\n
-    \n
-    html += Xinha.addCoreCSS();\n
-    \n
-    if ( typeof editor.config.pageStyleSheets !== \'undefined\' )\n
-    {\n
-      for ( var i = 0; i < editor.config.pageStyleSheets.length; i++ )\n
-      {\n
-        if ( editor.config.pageStyleSheets[i].length > 0 )\n
-        {\n
-          html += "<link rel=\\"stylesheet\\" type=\\"text/css\\" href=\\"" + editor.config.pageStyleSheets[i] + "\\">";\n
-          //html += "<style> @import url(\'" + editor.config.pageStyleSheets[i] + "\'); </style>\\n";\n
-        }\n
-      }\n
-    }\n
-    \n
-    if ( editor.config.pageStyle )\n
-    {\n
-      html += "<style type=\\"text/css\\">\\n" + editor.config.pageStyle + "\\n</style>";\n
-    }\n
-    \n
-    html += "</head>\\n";\n
-    html += "<body" + (editor.config.bodyID ? (" id=\\"" + editor.config.bodyID + "\\"") : \'\') + (editor.config.bodyClass ? (" class=\\"" + editor.config.bodyClass + "\\"") : \'\') + ">\\n";\n
-    html +=   editor.inwardHtml(editor._textArea.value);\n
-    html += "</body>\\n";\n
-    html += "</html>";\n
-  }\n
-  else\n
-  {\n
-    html = editor.inwardHtml(editor._textArea.value);\n
-    if ( html.match(Xinha.RE_doctype) )\n
-    {\n
-      editor.setDoctype(RegExp.$1);\n
-      //html = html.replace(Xinha.RE_doctype, "");\n
-    }\n
-    \n
-    //Fix Firefox problem with link elements not in right place (just before head)\n
-    var match = html.match(/<link\\s+[\\s\\S]*?["\']\\s*\\/?>/gi);\n
-    html = html.replace(/<link\\s+[\\s\\S]*?["\']\\s*\\/?>\\s*/gi, \'\');\n
-    if (match)\n
-    {\n
-      html = html.replace(/<\\/head>/i, match.join(\'\\n\') + "\\n</head>");\n
-    }\n
-  }\n
-  doc.write(html);\n
-  doc.close();\n
-  if ( this.config.fullScreen )\n
-  {\n
-    this._fullScreen();\n
-  }\n
-  this.setEditorEvents();\n
-\n
-\n
-  // If this IFRAME had been configured for autofocus, we\'ll focus it now,\n
-  // since everything needed to do so is now fully loaded.\n
-  if ((typeof editor.config.autofocus != "undefined") && editor.config.autofocus !== false &&\n
-      ((editor.config.autofocus == editor._textArea.id) || editor.config.autofocus == true))\n
-  {\n
-    editor.activateEditor();\n
-    editor.focusEditor();\n
-  }\n
-};\n
-  \n
-/**\n
- * Delay a function until the document is ready for operations.\n
- * See ticket:547\n
- * @public\n
- * @param {Function} f  The function to call once the document is ready\n
- */\n
-Xinha.prototype.whenDocReady = function(f)\n
-{\n
-  var e = this;\n
-  if ( this._doc && this._doc.body )\n
-  {\n
-    f();\n
-  }\n
-  else\n
-  {\n
-    setTimeout(function() { e.whenDocReady(f); }, 50);\n
-  }\n
-};\n
-\n
-\n
-/** Switches editor mode between wysiwyg and text (HTML)\n
- * @param {String} mode optional "textmode" or "wysiwyg", if omitted, toggles between modes.\n
- */\n
-Xinha.prototype.setMode = function(mode)\n
-{\n
-  var html;\n
-  if ( typeof mode == "undefined" )\n
-  {\n
-    mode = this._editMode == "textmode" ? "wysiwyg" : "textmode";\n
-  }\n
-  switch ( mode )\n
-  {\n
-    case "textmode":\n
-      this.firePluginEvent(\'onBeforeMode\', \'textmode\');\n
-      this._toolbarObjects.htmlmode.swapImage(this.config.iconList.wysiwygmode); \n
-      this.setCC("iframe");\n
-      html = this.outwardHtml(this.getHTML());\n
-      this.setHTML(html);\n
-\n
-      // Hide the iframe\n
-      this.deactivateEditor();\n
-      this._iframe.style.display   = \'none\';\n
-      this._textArea.style.display = \'\';\n
-\n
-      if ( this.config.statusBar )\n
-      {\n
-        this._statusBarTree.style.display = "none";\n
-        this._statusBarTextMode.style.display = "";\n
-      }\n
-      this.findCC("textarea");\n
-      this.notifyOf(\'modechange\', {\'mode\':\'text\'});\n
-      this.firePluginEvent(\'onMode\', \'textmode\');\n
-    break;\n
-\n
-    case "wysiwyg":\n
-      this.firePluginEvent(\'onBeforeMode\', \'wysiwyg\');\n
-      this._toolbarObjects.htmlmode.swapImage([this.imgURL(\'images/ed_buttons_main.png\'),7,0]); \n
-      this.setCC("textarea");\n
-      html = this.inwardHtml(this.getHTML());\n
-      this.deactivateEditor();\n
-      this.setHTML(html);\n
-      this._iframe.style.display   = \'\';\n
-      this._textArea.style.display = "none";\n
-      this.activateEditor();\n
-      if ( this.config.statusBar )\n
-      {\n
-        this._statusBarTree.style.display = "";\n
-        this._statusBarTextMode.style.display = "none";\n
-      }\n
-      this.findCC("iframe");\n
-      this.notifyOf(\'modechange\', {\'mode\':\'wysiwyg\'});\n
-      this.firePluginEvent(\'onMode\', \'wysiwyg\');\n
-\n
-    break;\n
-\n
-    default:\n
-      alert("Mode <" + mode + "> not defined!");\n
-      return false;\n
-  }\n
-  this._editMode = mode;\n
-};\n
-/** Sets the HTML in fullpage mode. Actually the whole iframe document is rewritten.\n
- * @private\n
- * @param {String} html\n
- */\n
-Xinha.prototype.setFullHTML = function(html)\n
-{\n
-  var save_multiline = RegExp.multiline;\n
-  RegExp.multiline = true;\n
-  if ( html.match(Xinha.RE_doctype) )\n
-  {\n
-    this.setDoctype(RegExp.$1);\n
-   // html = html.replace(Xinha.RE_doctype, "");\n
-  }\n
-  RegExp.multiline = save_multiline;\n
-  // disabled to save body attributes see #459\n
-  if ( 0 )\n
-  {\n
-    if ( html.match(Xinha.RE_head) )\n
-    {\n
-      this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;\n
-    }\n
-    if ( html.match(Xinha.RE_body) )\n
-    {\n
-      this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;\n
-    }\n
-  }\n
-  else\n
-  {\n
-    // FIXME - can we do this without rewriting the entire document\n
-    //  does the above not work for IE?\n
-    var reac = this.editorIsActivated();\n
-    if ( reac )\n
-    {\n
-      this.deactivateEditor();\n
-    }\n
-    var html_re = /<html>((.|\\n)*?)<\\/html>/i;\n
-    html = html.replace(html_re, "$1");\n
-    this._doc.open("text/html","replace");\n
-    this._doc.write(html);\n
-    this._doc.close();\n
-    if ( reac )\n
-    {\n
-      this.activateEditor();\n
-    }        \n
-    this.setEditorEvents();\n
-    return true;\n
-  }\n
-};\n
-/** Initialize some event handlers\n
- * @private\n
- */\n
-Xinha.prototype.setEditorEvents = function(resetting_events_for_opera)\n
-{\n
-  var editor=this;\n
-  var doc = this._doc;\n
-\n
-  editor.whenDocReady(\n
-    function()\n
-    {\n
-      if(!resetting_events_for_opera) {\n
-      // if we have multiple editors some bug in Mozilla makes some lose editing ability\n
-      Xinha._addEvents(\n
-        doc,\n
-        ["mousedown"],\n
-        function()\n
-        {\n
-          editor.activateEditor();\n
-          return true;\n
-        }\n
-      );\n
-      if (Xinha.is_ie)\n
-      { // #1019 Cusor not jumping to editable part of window when clicked in IE, see also #1039\n
-        Xinha._addEvent(\n
-        editor._doc.getElementsByTagName("html")[0],\n
-        "click",\n
-          function()\n
-          {\n
-            if (editor._iframe.contentWindow.event.srcElement.tagName.toLowerCase() == \'html\') // if  clicked below the text (=body), the text cursor does not appear, see #1019\n
-            {\n
-               var r = editor._doc.body.createTextRange();\n
-               r.collapse();\n
-               r.select();\n
-               //setTimeout (function () { r.collapse();  r.select();},100); // won\'t do without timeout, dunno why\n
-             }\n
-             return true;\n
-          }\n
-        );\n
-      }\n
-      }\n
-\n
-      // intercept some events; for updating the toolbar & keyboard handlers\n
-      Xinha._addEvents(\n
-        doc,\n
-        ["keydown", "keypress", "mousedown", "mouseup", "drag"],\n
-        function (event)\n
-        {\n
-          return editor._editorEvent(Xinha.is_ie ? editor._iframe.contentWindow.event : event);\n
-        }\n
-      );\n
-      \n
-      Xinha._addEvents(\n
-        doc, \n
-        ["dblclick"],\n
-        function (event)\n
-        {\n
-          return editor._onDoubleClick(Xinha.is_ie ? editor._iframe.contentWindow.event : event);\n
-        }\n
-      );\n
-      \n
-      if(resetting_events_for_opera) return;\n
-\n
-      // FIXME - this needs to be cleaned up and use editor.firePluginEvent\n
-      //  I don\'t like both onGenerate and onGenerateOnce, we should only\n
-      //  have onGenerate and it should only be called when the editor is \n
-      //  generated (once and only once)\n
-      // check if any plugins have registered refresh handlers\n
-      for ( var i in editor.plugins )\n
-      {\n
-        var plugin = editor.plugins[i].instance;\n
-        Xinha.refreshPlugin(plugin);\n
-      }\n
-\n
-      // specific editor initialization\n
-      if ( typeof editor._onGenerate == "function" )\n
-      {\n
-        editor._onGenerate();\n
-      }\n
-      //ticket #1407 IE8 fires two resize events on one actual resize, seemingly causing an infinite loop (but not  when Xinha is in an frame/iframe) \n
-      Xinha.addDom0Event(window, \'resize\', function(e) \n
-      {\n
-        if (Xinha.ie_version > 7 && !window.parent)\n
-        {\n
-          if (editor.execResize)\n
-          {\n
-            editor.sizeEditor(); \n
-            editor.execResize = false;\n
-          }\n
-          else\n
-          {\n
-            editor.execResize = true;\n
-          }\n
-        }\n
-        else\n
-        {\n
-          editor.sizeEditor(); \n
-        }\n
-      });      \n
-      editor.removeLoadingMessage();\n
-    }\n
-  );\n
-};\n
-  \n
-/***************************************************\n
- *  Category: PLUGINS\n
- ***************************************************/\n
-/** Plugins may either reside in the golbal scope (not recommended) or in Xinha.plugins. \n
- *  This function looks in both locations and is used to check the loading status and finally retrieve the plugin\'s constructor\n
- * @private\n
- * @type {Function|undefined}\n
- * @param {String} pluginName\n
- */\n
-Xinha.getPluginConstructor = function(pluginName)\n
-{\n
-  return Xinha.plugins[pluginName] || window[pluginName];\n
-};\n
-\n
-/** Create the specified plugin and register it with this Xinha\n
- *  return the plugin created to allow refresh when necessary.<br />\n
- *  <strong>This is only useful if Xinha is generated without using Xinha.makeEditors()</strong>\n
- */\n
-Xinha.prototype.registerPlugin = function()\n
-{\n
-  if (!Xinha.isSupportedBrowser)\n
-  {\n
-    return;\n
-  }\n
-  var plugin = arguments[0];\n
-\n
-  // We can only register plugins that have been succesfully loaded\n
-  if ( plugin === null || typeof plugin == \'undefined\' || (typeof plugin == \'string\' && Xinha.getPluginConstructor(plugin) == \'undefined\') )\n
-  {\n
-    return false;\n
-  }\n
-  var args = [];\n
-  for ( var i = 1; i < arguments.length; ++i )\n
-  {\n
-    args.push(arguments[i]);\n
-  }\n
-  return this.registerPlugin2(plugin, args);\n
-};\n
-/** This is the variant of the function above where the plugin arguments are\n
- * already packed in an array.  Externally, it should be only used in the\n
- * full-screen editor code, in order to initialize plugins with the same\n
- * parameters as in the opener window.\n
- * @private\n
- */\n
-Xinha.prototype.registerPlugin2 = function(plugin, args)\n
-{\n
-  if ( typeof plugin == "string" && typeof Xinha.getPluginConstructor(plugin) == \'function\' )\n
-  {\n
-    var pluginName = plugin;\n
-    plugin = Xinha.getPluginConstructor(plugin);\n
-  }\n
-  if ( typeof plugin == "undefined" )\n
-  {\n
-    /* FIXME: This should never happen. But why does it do? */\n
-    return false;\n
-  }\n
-  if (!plugin._pluginInfo) \n
-  {\n
-    plugin._pluginInfo = \n
-    {\n
-      name: pluginName\n
-    };\n
-  }\n
-  var obj = new plugin(this, args);\n
-  if ( obj )\n
-  {\n
-    var clone = {};\n
-    var info = plugin._pluginInfo;\n
-    for ( var i in info )\n
-    {\n
-      clone[i] = info[i];\n
-    }\n
-    clone.instance = obj;\n
-    clone.args = args;\n
-    this.plugins[plugin._pluginInfo.name] = clone;\n
-    return obj;\n
-  }\n
-  else\n
-  {\n
-    Xinha.debugMsg("Can\'t register plugin " + plugin.toString() + ".", \'warn\');\n
-  }\n
-};\n
-\n
-\n
-/** Dynamically returns the directory from which the plugins are loaded<br />\n
- *  This could be overridden to change the dir<br />\n
- *  @TODO: Wouldn\'t this be better as a config option?\n
- * @private\n
- * @param {String} pluginName\n
- * @param {Boolean} return the directory for an unsupported plugin\n
- * @returns {String} path to plugin\n
- */\n
-Xinha.getPluginDir = function(plugin, forceUnsupported)\n
-{\n
-  if (Xinha.externalPlugins[plugin])\n
-  {\n
-    return Xinha.externalPlugins[plugin][0];\n
-  }\n
-  if (forceUnsupported ||\n
-      // If the plugin is fully loaded, it\'s supported status is already set.\n
-      (Xinha.getPluginConstructor(plugin) && (typeof Xinha.getPluginConstructor(plugin).supported != \'undefined\') && !Xinha.getPluginConstructor(plugin).supported))\n
-  {\n
-    return _editor_url + "unsupported_plugins/" + plugin ;\n
-  }\n
-  return _editor_url + "plugins/" + plugin ;\n
-};\n
-/** Static function that loads the given plugin\n
- * @param {String} pluginName\n
- * @param {Function} callback function to be called when file is loaded\n
- * @param {String} plugin_file URL of the file to load\n
- * @returns {Boolean} true if plugin loaded, false otherwise\n
- */\n
-Xinha.loadPlugin = function(pluginName, callback, url)\n
-{\n
-  if (!Xinha.isSupportedBrowser) \n
-  {\n
-    return;\n
-  }\n
-  Xinha.setLoadingMessage (Xinha._lc("Loading plugin $plugin="+pluginName+"$"));\n
-\n
-  // Might already be loaded\n
-  if ( typeof Xinha.getPluginConstructor(pluginName) != \'undefined\' )\n
-  {\n
-    if ( callback )\n
-    {\n
-      callback(pluginName);\n
-    }\n
-    return true;\n
-  }\n
-  Xinha._pluginLoadStatus[pluginName] = \'loading\';\n
-  \n
-  // This function will try to load a plugin in multiple passes.  It tries to\n
-  // load the plugin from either the plugin or unsupported directory, using\n
-  // both naming schemes in this order:\n
-  // 1. /plugins -> CurrentNamingScheme\n
-  // 2. /plugins -> old-naming-scheme\n
-  // 3. /unsupported -> CurrentNamingScheme\n
-  // 4. /unsupported -> old-naming-scheme\n
-\n
-  function multiStageLoader(stage,pluginName)\n
-  {\n
-    var nextstage, dir, file, success_message;\n
-    switch (stage)\n
-    {\n
-      case \'start\':\n
-        nextstage = \'old_naming\';\n
-        dir = Xinha.getPluginDir(pluginName);\n
-        file = pluginName + ".js";\n
-        break;\n
-      case \'old_naming\':\n
-        nextstage = \'unsupported\';\n
-        dir = Xinha.getPluginDir(pluginName);\n
-        file = pluginName.replace(/([a-z])([A-Z])([a-z])/g, function (str, l1, l2, l3) { return l1 + "-" + l2.toLowerCase() + l3; }).toLowerCase() + ".js";\n
-        success_message = \'You are using an obsolete naming scheme for the Xinha plugin \'+pluginName+\'. Please rename \'+file+\' to \'+pluginName+\'.js\';\n
-        break;\n
-      case \'unsupported\':\n
-        nextstage = \'unsupported_old_name\';\n
-        dir = Xinha.getPluginDir(pluginName, true);\n
-        file = pluginName + ".js";\n
-        success_message = \'You are using the unsupported Xinha plugin \'+pluginName+\'. If you wish continued support, please see http://trac.xinha.org/ticket/1297\';\n
-        break;\n
-      case \'unsupported_old_name\':\n
-        nextstage = \'\';\n
-        dir = Xinha.getPluginDir(pluginName, true);\n
-        file = pluginName.replace(/([a-z])([A-Z])([a-z])/g, function (str, l1, l2, l3) { return l1 + "-" + l2.toLowerCase() + l3; }).toLowerCase() + ".js";\n
-        success_message = \'You are using the unsupported Xinha plugin \'+pluginName+\'. If you wish continued support, please see http://trac.xinha.org/ticket/1297\';\n
-        break;\n
-      default:\n
-        Xinha._pluginLoadStatus[pluginName] = \'failed\';\n
-        Xinha.debugMsg(\'Xinha was not able to find the plugin \'+pluginName+\'. Please make sure the plugin exists.\', \'warn\');\n
-        return;\n
-    }\n
-    var url = dir + "/" + file;\n
-\n
-    // This is a callback wrapper that allows us to set the plugin\'s status\n
-    // once it loads.\n
-    function statusCallback(pluginName)\n
-    {\n
-      Xinha.getPluginConstructor(pluginName).supported = stage.indexOf(\'unsupported\') !== 0;\n
-      callback(pluginName);\n
-    }\n
-\n
-    // To speed things up, we start loading the script file before pinging it.\n
-    // If the load fails, we\'ll just clean up afterwards.\n
-    Xinha._loadback(url, statusCallback, this, pluginName); \n
-\n
-    Xinha.ping(url,\n
-               // On success, we\'ll display a success message if there is one.\n
-               function()\n
-               {\n
-                 if (success_message) \n
-                 {\n
-                   Xinha.debugMsg(success_message);\n
-                 }\n
-               },\n
-               // On failure, we\'ll clean up the failed load and try the next stage\n
-               function()\n
-               {\n
-                 Xinha.removeFromParent(document.getElementById(url));\n
-                 multiStageLoader(nextstage, pluginName);\n
-               });\n
-  }\n
-  \n
-  if(!url)\n
-  {\n
-    if (Xinha.externalPlugins[pluginName])\n
-    {\n
-      Xinha._loadback(Xinha.externalPlugins[pluginName][0]+Xinha.externalPlugins[pluginName][1], callback, this, pluginName);\n
-    }\n
-    else\n
-    {\n
-      var editor = this;\n
-      multiStageLoader(\'start\',pluginName);\n
-    }\n
-  }\n
-  else\n
-  {\n
-    Xinha._loadback(url, callback, this, pluginName);\n
-  }\n
-  \n
-  return false;\n
-};\n
-/** Stores a status for each loading plugin that may be one of "loading","ready", or "failed"\n
- * @private\n
- * @type {Object} \n
- */\n
-Xinha._pluginLoadStatus = {};\n
-/** Stores the paths to plugins that are not in the default location\n
- * @private\n
- * @type {Object}\n
- */\n
-Xinha.externalPlugins = {};\n
-/** The namespace for plugins\n
- * @private\n
- * @type {Object}\n
- */\n
-Xinha.plugins = {};\n
-\n
-/** Static function that loads the plugins (see xinha_plugins in NewbieGuide)\n
- * @param {Array} plugins\n
- * @param {Function} callbackIfNotReady function that is called repeatedly until all files are\n
- * @param {String} optional url URL of the plugin file; obviously plugins should contain only one item if url is given\n
- * @returns {Boolean} true if all plugins are loaded, false otherwise\n
- */\n
-Xinha.loadPlugins = function(plugins, callbackIfNotReady,url)\n
-{\n
-  if (!Xinha.isSupportedBrowser) \n
-  {\n
-    return;\n
-  }\n
-  //Xinha.setLoadingMessage (Xinha._lc("Loading plugins"));\n
-  var m,i;\n
-  for (i=0;i<plugins.length;i++)\n
-  {\n
-    if (typeof plugins[i] == \'object\')\n
-    {\n
-      m = plugins[i].url.match(/(.*)(\\/[^\\/]*)$/);\n
-      Xinha.externalPlugins[plugins[i].plugin] = [m[1],m[2]];\n
-      plugins[i] = plugins[i].plugin;\n
-    }\n
-  }\n
-  \n
-  // Rip the ones that are loaded and look for ones that have failed\n
-  var retVal = true;\n
-  var nuPlugins = Xinha.cloneObject(plugins);\n
-  for (i=0;i<nuPlugins.length;i++ )\n
-  {\n
-    var p = nuPlugins[i];\n
-    \n
-    if (p == \'FullScreen\' && !Xinha.externalPlugins.FullScreen)\n
-    {\n
-      continue; //prevent trying to load FullScreen plugin from the plugins folder\n
-    } \n
-   \n
-    if ( typeof Xinha._pluginLoadStatus[p] == \'undefined\')\n
-    {\n
-      // Load it\n
-      Xinha.loadPlugin(p,\n
-        function(plugin)\n
-        {\n
-          Xinha.setLoadingMessage (Xinha._lc("Finishing"));\n
-\n
-          if ( typeof Xinha.getPluginConstructor(plugin) != \'undefined\' )\n
-          {\n
-            Xinha._pluginLoadStatus[plugin] = \'ready\';\n
-          }\n
-          else\n
-          {\n
-            Xinha._pluginLoadStatus[plugin] = \'failed\';\n
-          }\n
-        }, url);\n
-      retVal = false;\n
-    }\n
-    else if ( Xinha._pluginLoadStatus[p] == \'loading\')\n
-    {\n
-      retVal = false;\n
-    }\n
-  }\n
-  \n
-  // All done, just return\n
-  if ( retVal )\n
-  {\n
-    return true;\n
-  }\n
-\n
-  // Waiting on plugins to load, return false now and come back a bit later\n
-  // if we have to callback\n
-  if ( callbackIfNotReady )\n
-  {\n
-    setTimeout(function() \n
-    { \n
-      if ( Xinha.loadPlugins(plugins, callbackIfNotReady) ) \n
-      { \n
-        callbackIfNotReady(); \n
-      } \n
-    }, 50);\n
-  }\n
-  return retVal;\n
-};\n
-\n
-// \n
-/** Refresh plugin by calling onGenerate or onGenerateOnce method.\n
- * @private\n
- * @param {PluginInstance} plugin\n
- */\n
-Xinha.refreshPlugin = function(plugin)\n
-{\n
-  if ( plugin && typeof plugin.onGenerate == "function" )\n
-  {\n
-    plugin.onGenerate();\n
-  }\n
-  if ( plugin && typeof plugin.onGenerateOnce == "function" )\n
-  {\n
-    //#1392: in fullpage mode this function is called recusively by setFullHTML() when it is used to set the editor content\n
-\t// this is a temporary fix, that should better be handled by a better implemetation of setFullHTML\n
-\tplugin._ongenerateOnce = plugin.onGenerateOnce;\n
-    delete(plugin.onGenerateOnce);\n
-\tplugin._ongenerateOnce();\n
-\tdelete(plugin._ongenerateOnce);\n
-  }\n
-};\n
-\n
-/** Call a method of all plugins which define the method using the supplied arguments.<br /><br />\n
- *\n
- *  Example: <code>editor.firePluginEvent(\'onExecCommand\', \'paste\')</code><br />\n
- *           The plugin would then define a method<br />\n
- *           <code>PluginName.prototype.onExecCommand = function (cmdID, UI, param) {do something...}</code><br /><br />\n
- *           The following methodNames are currently available:<br />\n
- *  <table border="1">\n
- *    <tr>\n
- *       <th>methodName</th><th>Parameters</th>\n
- *     </tr>\n
- *     <tr>\n
- *       <td>onExecCommand</td><td> cmdID, UI, param</td>\n
- *     </tr>\n
- *     <tr>\n
- *       <td>onKeyPress</td><td>ev</td>\n
- *     </tr> \n
- *     <tr>\n
- *       <td>onMouseDown</td><td>ev</td>\n
- *     </tr>\n
- * </table><br /><br />\n
- *  \n
- *  The browser specific plugin (if any) is called last.  The result of each call is \n
- *  treated as boolean.  A true return means that the event will stop, no further plugins\n
- *  will get the event, a false return means the event will continue to fire.\n
- *\n
- *  @param {String} methodName\n
- *  @param {mixed} arguments to pass to the method, optional [2..n] \n
- *  @returns {Boolean}\n
- */\n
-\n
-Xinha.prototype.firePluginEvent = function(methodName)\n
-{\n
-  // arguments is not a real array so we can\'t just .shift() it unfortunatly.\n
-  var argsArray = [ ];\n
-  for(var i = 1; i < arguments.length; i++)\n
-  {\n
-    argsArray[i-1] = arguments[i];\n
-  }\n
-  \n
-  for ( i in this.plugins )\n
-  {\n
-    var plugin = this.plugins[i].instance;\n
-\n
-    // Skip the browser specific plugin\n
-    if (plugin == this._browserSpecificPlugin) \n
-    {\n
-      continue;\n
-    }\n
-    if ( plugin && typeof plugin[methodName] == "function" )\n
-    {\n
-      var thisArg = (i == \'Events\') ? this : plugin;\n
-      if ( plugin[methodName].apply(thisArg, argsArray) )\n
-      {\n
-        return true;\n
-      }\n
-    }\n
-  }\n
-  \n
-  // Now the browser speific\n
-  plugin = this._browserSpecificPlugin;\n
-  if ( plugin && typeof plugin[methodName] == "function" )\n
-  {\n
-    if ( plugin[methodName].apply(plugin, argsArray) )\n
-    {\n
-      return true;\n
-    }\n
-  }\n
-  return false;\n
-};\n
-/** Adds a stylesheet to the document\n
- * @param {String} style name of the stylesheet file\n
- * @param {String} plugin optional name of a plugin; if passed this function looks for the stylesheet file in the plugin directory \n
- * @param {String} id optional a unique id for identifiing the created link element, e.g. for avoiding double loading \n
- *                 or later removing it again\n
- */\n
-Xinha.loadStyle = function(style, plugin, id,prepend)\n
-{\n
-  var url = _editor_url || \'\';\n
-  if ( plugin )\n
-  {\n
-    url = Xinha.getPluginDir( plugin ) + "/";\n
-  }\n
-  url += style;\n
-  // @todo: would not it be better to check the first character instead of a regex ?\n
-  // if ( typeof style == \'string\' && style.charAt(0) == \'/\' )\n
-  // {\n
-  //   url = style;\n
-  // }\n
-  if ( /^\\//.test(style) )\n
-  {\n
-    url = style;\n
-  }\n
-  var head = document.getElementsByTagName("head")[0];\n
-  var link = document.createElement("link");\n
-  link.rel = "stylesheet";\n
-  link.href = url;\n
-  link.type = "text/css";\n
-  if (id)\n
-  {\n
-    link.id = id;\n
-  }\n
-  if (prepend && head.getElementsByTagName(\'link\')[0])\n
-  {\n
-    head.insertBefore(link,head.getElementsByTagName(\'link\')[0]);\n
-  }\n
-  else\n
-  {\n
-    head.appendChild(link);\n
-  }\n
-  \n
-};\n
-\n
-/** Adds a script to the document\n
- *\n
- * Warning: Browsers may cause the script to load asynchronously.\n
- *\n
- * @param {String} style name of the javascript file\n
- * @param {String} plugin optional name of a plugin; if passed this function looks for the stylesheet file in the plugin directory \n
- *\n
- */\n
-Xinha.loadScript = function(script, plugin, callback)\n
-{\n
-  var url = _editor_url || \'\';\n
-  if ( plugin )\n
-  {\n
-    url = Xinha.getPluginDir( plugin ) + "/";\n
-  }\n
-  url += script;\n
-  // @todo: would not it be better to check the first character instead of a regex ?\n
-  // if ( typeof style == \'string\' && style.charAt(0) == \'/\' )\n
-  // {\n
-  //   url = style;\n
-  // }\n
-  if ( /^\\//.test(script) )\n
-  {\n
-    url = script;\n
-  }\n
-  \n
-  Xinha._loadback(url, callback);\n
-  \n
-};\n
-\n
-/** Load one or more assets, sequentially, where an asset is a CSS file, or a javascript file.\n
- *  \n
- * Example Usage:\n
- *\n
- * Xinha.includeAssets( \'foo.css\', \'bar.js\', [ \'foo.css\', \'MyPlugin\' ], { type: \'text/css\', url: \'foo.php\', plugin: \'MyPlugin } );\n
- *\n
- * Alternative usage, use Xinha.includeAssets() to make a loader, then use loadScript, loadStyle and whenReady methods\n
- * on your loader object as and when you wish, you can chain the calls if you like.\n
- *\n
- * You may add any number of callbacks using .whenReady() multiple times.\n
- *\n
- *   var myAssetLoader = Xinha.includeAssets();\n
- *       myAssetLoader.loadScript(\'foo.js\', \'MyPlugin\')\n
- *                    .loadStyle(\'foo.css\', \'MyPlugin\');                        \n
- * \n
- */\n
-\n
-Xinha.includeAssets = function()\n
-{\n
-  var assetLoader = { pendingAssets: [ ], loaderRunning: false, loadedScripts: [ ] };\n
-  \n
-  assetLoader.callbacks = [ ];\n
-  \n
-  assetLoader.loadNext = function()\n
-  {  \n
-    var self = this;\n
-    this.loaderRunning = true;\n
-    \n
-    if(this.pendingAssets.length)\n
-    {\n
-      var nxt = this.pendingAssets[0];\n
-      this.pendingAssets.splice(0,1); // Remove 1 element\n
-      switch(nxt.type)\n
-      {\n
-        case \'text/css\':\n
-          Xinha.loadStyle(nxt.url, nxt.plugin);\n
-          return this.loadNext();\n
-        \n
-        case \'text/javascript\':\n
-          Xinha.loadScript(nxt.url, nxt.plugin, function() { self.loadNext(); });\n
-      }\n
-    }\n
-    else\n
-    {\n
-      this.loaderRunning = false;\n
-      this.runCallback();      \n
-    }\n
-  };\n
-  \n
-  assetLoader.loadScript = function(url, plugin)\n
-  {\n
-    var self = this;\n
-    \n
-    this.pendingAssets.push({ \'type\': \'text/javascript\', \'url\': url, \'plugin\': plugin });\n
-    if(!this.loaderRunning) this.loadNext();\n
-    \n
-    return this;\n
-  };\n
-  \n
-  assetLoader.loadScriptOnce = function(url, plugin)\n
-  {\n
-    for(var i = 0; i < this.loadedScripts.length; i++)\n
-    {\n
-      if(this.loadedScripts[i].url == url && this.loadedScripts[i].plugin == plugin)\n
-        return this; // Already done (or in process)\n
-    }\n
-    \n
-    return this.loadScript(url, plugin);\n
-  }\n
-  \n
-  assetLoader.loadStyle = function(url, plugin)\n
-  {\n
-    var self = this;\n
-    \n
-    this.pendingAssets.push({ \'type\': \'text/css\', \'url\': url, \'plugin\': plugin });\n
-    if(!this.loaderRunning) this.loadNext();\n
-    \n
-    return this;    \n
-  };\n
-  \n
-  assetLoader.whenReady = function(callback) \n
-  {\n
-    this.callbacks.push(callback);    \n
-    if(!this.loaderRunning) this.loadNext();\n
-    \n
-    return this;    \n
-  };\n
-  \n
-  assetLoader.runCallback = function()\n
-  {\n
-    while(this.callbacks.length)\n
-    { \n
-      var _callback = this.callbacks.splice(0,1);\n
-      _callback[0]();\n
-      _callback = null;\n
-    }\n
-    return this;\n
-  }\n
-  \n
-  for(var i = 0 ; i < arguments.length; i++)\n
-  {\n
-    if(typeof arguments[i] == \'string\')\n
-    {\n
-      if(arguments[i].match(/\\.css$/i))\n
-      {\n
-        assetLoader.loadStyle(arguments[i]);\n
-      }\n
-      else \n
-      {\n
-        assetLoader.loadScript(arguments[i]);\n
-      }\n
-    }\n
-    else if(arguments[i].type)\n
-    {\n
-      if(arguments[i].type.match(/text\\/css/i))\n
-      {\n
-        assetLoader.loadStyle(arguments[i].url, arguments[i].plugin);\n
-      }\n
-      else if(arguments[i].type.match(/text\\/javascript/i))\n
-      {\n
-        assetLoader.loadScript(arguments[i].url, arguments[i].plugin);\n
-      }\n
-    }\n
-    else if(arguments[i].length >= 1)\n
-    {\n
-      if(arguments[i][0].match(/\\.css$/i))\n
-      {\n
-        assetLoader.loadStyle(arguments[i][0], arguments[i][1]);\n
-      }\n
-      else \n
-      {\n
-        assetLoader.loadScript(arguments[i][0], arguments[i][1]);\n
-      }\n
-    }\n
-  }\n
-  \n
-  return assetLoader;\n
-}\n
-\n
-/***************************************************\n
- *  Category: EDITOR UTILITIES\n
- ***************************************************/\n
-/** Utility function: Outputs the structure of the edited document */\n
-Xinha.prototype.debugTree = function()\n
-{\n
-  var ta = document.createElement("textarea");\n
-  ta.style.width = "100%";\n
-  ta.style.height = "20em";\n
-  ta.value = "";\n
-  function debug(indent, str)\n
-  {\n
-    for ( ; --indent >= 0; )\n
-    {\n
-      ta.value += " ";\n
-    }\n
-    ta.value += str + "\\n";\n
-  }\n
-  function _dt(root, level)\n
-  {\n
-    var tag = root.tagName.toLowerCase(), i;\n
-    var ns = Xinha.is_ie ? root.scopeName : root.prefix;\n
-    debug(level, "- " + tag + " [" + ns + "]");\n
-    for ( i = root.firstChild; i; i = i.nextSibling )\n
-    {\n
-      if ( i.nodeType == 1 )\n
-      {\n
-        _dt(i, level + 2);\n
-      }\n
-    }\n
-  }\n
-  _dt(this._doc.body, 0);\n
-  document.body.appendChild(ta);\n
-};\n
-/** Extracts the textual content of a given node\n
- * @param {DomNode} el\n
- */\n
-\n
-Xinha.getInnerText = function(el)\n
-{\n
-  var txt = \'\', i;\n
-  for ( i = el.firstChild; i; i = i.nextSibling )\n
-  {\n
-    if ( i.nodeType == 3 )\n
-    {\n
-      txt += i.data;\n
-    }\n
-    else if ( i.nodeType == 1 )\n
-    {\n
-      txt += Xinha.getInnerText(i);\n
-    }\n
-  }\n
-  return txt;\n
-};\n
-/** Cleans dirty HTML from MS word; always cleans the whole editor content\n
- *  @TODO: move this in a separate file\n
- *  @TODO: turn this into a static function that cleans a given string\n
- */\n
-Xinha.prototype._wordClean = function()\n
-{\n
-  var editor = this;\n
-  var stats =\n
-  {\n
-    empty_tags : 0,\n
-    cond_comm  : 0,\n
-    mso_elmts  : 0,\n
-    mso_class  : 0,\n
-    mso_style  : 0,\n
-    mso_xmlel  : 0,\n
-    orig_len   : this._doc.body.innerHTML.length,\n
-    T          : new Date().getTime()\n
-  };\n
-  var stats_txt =\n
-  {\n
-    empty_tags : "Empty tags removed: ",\n
-    cond_comm  : "Conditional comments removed",\n
-    mso_elmts  : "MSO invalid elements removed",\n
-    mso_class  : "MSO class names removed: ",\n
-    mso_style  : "MSO inline style removed: ",\n
-    mso_xmlel  : "MSO XML elements stripped: "\n
-  };\n
-\n
-  function showStats()\n
-  {\n
-    var txt = "Xinha word cleaner stats: \\n\\n";\n
-    for ( var i in stats )\n
-    {\n
-      if ( stats_txt[i] )\n
-      {\n
-        txt += stats_txt[i] + stats[i] + "\\n";\n
-      }\n
-    }\n
-    txt += "\\nInitial document length: " + stats.orig_len + "\\n";\n
-    txt += "Final document length: " + editor._doc.body.innerHTML.length + "\\n";\n
-    txt += "Clean-up took " + ((new Date().getTime() - stats.T) / 1000) + " seconds";\n
-    alert(txt);\n
-  }\n
-\n
-  function clearClass(node)\n
-  {\n
-    var newc = node.className.replace(/(^|\\s)mso.*?(\\s|$)/ig, \' \');\n
-    if ( newc != node.className )\n
-    {\n
-      node.className = newc;\n
-      if ( !/\\S/.test(node.className))\n
-      {\n
-        node.removeAttribute("className");\n
-        ++stats.mso_class;\n
-      }\n
-    }\n
-  }\n
-\n
-  function clearStyle(node)\n
-  {\n
-    var declarations = node.style.cssText.split(/\\s*;\\s*/);\n
-    for ( var i = declarations.length; --i >= 0; )\n
-    {\n
-      if ( /^mso|^tab-stops/i.test(declarations[i]) || /^margin\\s*:\\s*0..\\s+0..\\s+0../i.test(declarations[i]) )\n
-      {\n
-        ++stats.mso_style;\n
-        declarations.splice(i, 1);\n
-      }\n
-    }\n
-    node.style.cssText = declarations.join("; ");\n
-  }\n
+    -------------------------------------------------------------------------*/\n
 \n
-  function removeElements(el)\n
-  {\n
-    if ((\'link\' == el.tagName.toLowerCase() &&\n
-        (el.attributes && /File-List|Edit-Time-Data|themeData|colorSchemeMapping/.test(el.attributes.rel.nodeValue))) ||\n
-        /^(style|meta)$/i.test(el.tagName))\n
-    {\n
-      Xinha.removeFromParent(el);\n
-      ++stats.mso_elmts;\n
-      return true;\n
-    }\n
-    return false;\n
-  }\n
-\n
-  function checkEmpty(el)\n
-  {\n
-    // @todo : check if this is quicker\n
-    //  if (![\'A\',\'SPAN\',\'B\',\'STRONG\',\'I\',\'EM\',\'FONT\'].contains(el.tagName) && !el.firstChild)\n
-    if ( /^(a|span|b|strong|i|em|font|div|p)$/i.test(el.tagName) && !el.firstChild)\n
-    {\n
-      Xinha.removeFromParent(el);\n
-      ++stats.empty_tags;\n
-      return true;\n
-    }\n
-    return false;\n
-  }\n
-\n
-  function parseTree(root)\n
-  {\n
-    clearClass(root);\n
-    clearStyle(root);\n
-    var next;\n
-    for (var i = root.firstChild; i; i = next )\n
-    {\n
-      next = i.nextSibling;\n
-      if ( i.nodeType == 1 && parseTree(i) )\n
-      {\n
-        if ((Xinha.is_ie && root.scopeName != \'HTML\') || (!Xinha.is_ie && /:/.test(i.tagName)))\n
-        {\n
-          // Nowadays, Word spits out tags like \'<o:something />\'.  Since the\n
-          // document being cleaned might be HTML4 and not XHTML, this tag is\n
-          // interpreted as \'<o:something /="/">\'.  For HTML tags without\n
-          // closing elements (e.g. IMG) these two forms are equivalent.  Since\n
-          // HTML does not recognize these tags, however, they end up as\n
-          // parents of elements that should be their siblings.  We reparent\n
-          // the children and remove them from the document.\n
-          for (var index=i.childNodes && i.childNodes.length-1; i.childNodes && i.childNodes.length && i.childNodes[index]; --index)\n
-          {\n
-            if (i.nextSibling)\n
-            {\n
-              i.parentNode.insertBefore(i.childNodes[index],i.nextSibling);\n
-            }\n
-            else\n
-            {\n
-              i.parentNode.appendChild(i.childNodes[index]);\n
-            }\n
-          }\n
-          Xinha.removeFromParent(i);\n
-          continue;\n
-        }\n
-        if (checkEmpty(i))\n
-        {\n
-          continue;\n
-        }\n
-        if (removeElements(i))\n
-        {\n
-          continue;\n
-        }\n
-      }\n
-      else if (i.nodeType == 8)\n
-      {\n
-        // 8 is a comment node, and can contain conditional comments, which\n
-        // will be interpreted by IE as if they were not comments.\n
-        if (/(\\s*\\[\\s*if\\s*(([gl]te?|!)\\s*)?(IE|mso)\\s*(\\d+(\\.\\d+)?\\s*)?\\]>)/.test(i.nodeValue))\n
-        {\n
-          // We strip all conditional comments directly from the tree.\n
-          Xinha.removeFromParent(i);\n
-          ++stats.cond_comm;\n
-        }\n
-      }\n
-    }\n
-    return true;\n
-  }\n
-  parseTree(this._doc.body);\n
-  // showStats();\n
-  // this.debugTree();\n
-  // this.setHTML(this.getHTML());\n
-  // this.setHTML(this.getInnerHTML());\n
-  // this.forceRedraw();\n
-  this.updateToolbar();\n
-};\n
-\n
-/** Removes &lt;font&gt; tags; always cleans the whole editor content\n
- *  @TODO: move this in a separate file\n
- *  @TODO: turn this into a static function that cleans a given string\n
- */\n
-Xinha.prototype._clearFonts = function()\n
-{\n
-  var D = this.getInnerHTML();\n
-\n
-  if ( confirm(Xinha._lc("Would you like to clear font typefaces?")) )\n
-  {\n
-    D = D.replace(/face="[^"]*"/gi, \'\');\n
-    D = D.replace(/font-family:[^;}"\']+;?/gi, \'\');\n
-  }\n
-\n
-  if ( confirm(Xinha._lc("Would you like to clear font sizes?")) )\n
-  {\n
-    D = D.replace(/size="[^"]*"/gi, \'\');\n
-    D = D.replace(/font-size:[^;}"\']+;?/gi, \'\');\n
-  }\n
-\n
-  if ( confirm(Xinha._lc("Would you like to clear font colours?")) )\n
-  {\n
-    D = D.replace(/color="[^"]*"/gi, \'\');\n
-    D = D.replace(/([^\\-])color:[^;}"\']+;?/gi, \'$1\');\n
-  }\n
-\n
-  D = D.replace(/(style|class)="\\s*"/gi, \'\');\n
-  D = D.replace(/<(font|span)\\s*>/gi, \'\');\n
-  this.setHTML(D);\n
-  this.updateToolbar();\n
-};\n
-\n
-Xinha.prototype._splitBlock = function()\n
-{\n
-  this._doc.execCommand(\'formatblock\', false, \'div\');\n
-};\n
-\n
-/** Sometimes the display has to be refreshed to make DOM changes visible (?) (Gecko bug?)  */\n
-Xinha.prototype.forceRedraw = function()\n
-{\n
-  this._doc.body.style.visibility = "hidden";\n
-  this._doc.body.style.visibility = "";\n
-  // this._doc.body.innerHTML = this.getInnerHTML();\n
-};\n
-\n
-/** Focuses the iframe window. \n
- * @returns {document} a reference to the editor document\n
- */\n
-Xinha.prototype.focusEditor = function()\n
-{\n
-  switch (this._editMode)\n
-  {\n
-    // notice the try { ... } catch block to avoid some rare exceptions in FireFox\n
-    // (perhaps also in other Gecko browsers). Manual focus by user is required in\n
-    // case of an error. Somebody has an idea?\n
-    case "wysiwyg" :\n
-      try\n
-      {\n
-        // We don\'t want to focus the field unless at least one field has been activated.\n
-        if ( Xinha._someEditorHasBeenActivated )\n
-        {\n
-          this.activateEditor(); // Ensure *this* editor is activated\n
-          this._iframe.contentWindow.focus(); // and focus it\n
-        }\n
-      } catch (ex) {}\n
-    break;\n
-    case "textmode":\n
-      try\n
-      {\n
-        this._textArea.focus();\n
-      } catch (e) {}\n
-    break;\n
-    default:\n
-      alert("ERROR: mode " + this._editMode + " is not defined");\n
-  }\n
-  return this._doc;\n
-};\n
-\n
-/** Takes a snapshot of the current text (for undo)\n
- * @private\n
- */\n
-Xinha.prototype._undoTakeSnapshot = function()\n
-{\n
-  ++this._undoPos;\n
-  if ( this._undoPos >= this.config.undoSteps )\n
-  {\n
-    // remove the first element\n
-    this._undoQueue.shift();\n
-    --this._undoPos;\n
-  }\n
-  // use the fasted method (getInnerHTML);\n
-  var take = true;\n
-  var txt = this.getInnerHTML();\n
-  if ( this._undoPos > 0 )\n
-  {\n
-    take = (this._undoQueue[this._undoPos - 1] != txt);\n
-  }\n
-  if ( take )\n
-  {\n
-    this._undoQueue[this._undoPos] = txt;\n
-  }\n
-  else\n
-  {\n
-    this._undoPos--;\n
-  }\n
-};\n
-/** Custom implementation of undo functionality\n
- * @private\n
- */\n
-Xinha.prototype.undo = function()\n
-{\n
-  if ( this._undoPos > 0 )\n
-  {\n
-    var txt = this._undoQueue[--this._undoPos];\n
-    if ( txt )\n
-    {\n
-      this.setHTML(txt);\n
-    }\n
-    else\n
-    {\n
-      ++this._undoPos;\n
-    }\n
-  }\n
-};\n
-/** Custom implementation of redo functionality\n
- * @private\n
- */\n
-Xinha.prototype.redo = function()\n
-{\n
-  if ( this._undoPos < this._undoQueue.length - 1 )\n
-  {\n
-    var txt = this._undoQueue[++this._undoPos];\n
-    if ( txt )\n
-    {\n
-      this.setHTML(txt);\n
-    }\n
-    else\n
-    {\n
-      --this._undoPos;\n
-    }\n
-  }\n
-};\n
-/** Disables (greys out) the buttons of the toolbar\n
- * @param {Array} except this array contains ids of toolbar objects that will not be disabled\n
- */\n
-Xinha.prototype.disableToolbar = function(except)\n
-{\n
-  if ( this._timerToolbar )\n
-  {\n
-    clearTimeout(this._timerToolbar);\n
-  }\n
-  if ( typeof except == \'undefined\' )\n
-  {\n
-    except = [ ];\n
-  }\n
-  else if ( typeof except != \'object\' )\n
-  {\n
-    except = [except];\n
-  }\n
-\n
-  for ( var i in this._toolbarObjects )\n
-  {\n
-    var btn = this._toolbarObjects[i];\n
-    if ( except.contains(i) )\n
-    {\n
-      continue;\n
-    }\n
-    // prevent iterating over wrong type\n
-    if ( typeof btn.state != \'function\' )\n
-    {\n
-      continue;\n
-    }\n
-    btn.state("enabled", false);\n
-  }\n
-};\n
-/** Enables the toolbar again when disabled by disableToolbar() */\n
-Xinha.prototype.enableToolbar = function()\n
-{\n
-  this.updateToolbar();\n
-};\n
-\n
-/** Updates enabled/disable/active state of the toolbar elements, the statusbar and other things\n
- *  This function is called on every key stroke as well as by a timer on a regular basis.<br />\n
- *  Plugins have the opportunity to implement a prototype.onUpdateToolbar() method, which will also\n
- *  be called by this function.\n
- * @param {Boolean} noStatus private use Exempt updating of statusbar\n
- */\n
-// FIXME : this function needs to be splitted in more functions.\n
-// It is actually to heavy to be understable and very scary to manipulate\n
-Xinha.prototype.updateToolbar = function(noStatus)\n
-{\n
-  if (this.suspendUpdateToolbar)\n
-  {\n
-    return;\n
-  }\n
-  var doc = this._doc;\n
-  var text = (this._editMode == "textmode");\n
-  var ancestors = null;\n
-  if ( !text )\n
-  {\n
-    ancestors = this.getAllAncestors();\n
-    if ( this.config.statusBar && !noStatus )\n
-    {\n
-      while ( this._statusBarItems.length )\n
-      { \n
-        var item = this._statusBarItems.pop();\n
-        item.el = null;\n
-        item.editor = null;\n
-        item.onclick = null;\n
-        item.oncontextmenu = null;\n
-        item._xinha_dom0Events.click = null;\n
-        item._xinha_dom0Events.contextmenu = null;\n
-        item = null;\n
-      }\n
-\n
-      this._statusBarTree.innerHTML = \' \';\n
-      this._statusBarTree.appendChild(document.createTextNode(Xinha._lc("Path") + ": ")); \n
-      for ( var i = ancestors.length; --i >= 0; )\n
-      {\n
-        var el = ancestors[i];\n
-        if ( !el )\n
-        {\n
-          // hell knows why we get here; this\n
-          // could be a classic example of why\n
-          // it\'s good to check for conditions\n
-          // that are impossible to happen ;-)\n
-          continue;\n
-        }\n
-        var a = document.createElement("a");\n
-        a.href = "javascript:void(0);";\n
-        a.el = el;\n
-        a.editor = this;\n
-        this._statusBarItems.push(a);\n
-        Xinha.addDom0Event(\n
-          a,\n
-          \'click\',\n
-          function() {\n
-            this.blur();\n
-            this.editor.selectNodeContents(this.el);\n
-            this.editor.updateToolbar(true);\n
-            return false;\n
-          }\n
-        );\n
-        Xinha.addDom0Event(\n
-          a,\n
-          \'contextmenu\',\n
-          function()\n
-          {\n
-            // TODO: add context menu here\n
-            this.blur();\n
-            var info = "Inline style:\\n\\n";\n
-            info += this.el.style.cssText.split(/;\\s*/).join(";\\n");\n
-            alert(info);\n
-            return false;\n
-          }\n
-        );\n
-        var txt = el.tagName.toLowerCase();\n
-        switch (txt)\n
-        {\n
-          case \'b\':\n
-            txt = \'strong\';\n
-          break;\n
-          case \'i\':\n
-            txt = \'em\';\n
-          break;\n
-          case \'strike\':\n
-            txt = \'del\';\n
-          break;\n
-        }\n
-        if (typeof el.style != \'undefined\')\n
-        {\n
-          a.title = el.style.cssText;\n
-        }\n
-        if ( el.id )\n
-        {\n
-          txt += "#" + el.id;\n
-        }\n
-        if ( el.className )\n
-        {\n
-          txt += "." + el.className;\n
-        }\n
-        a.appendChild(document.createTextNode(txt));\n
-        this._statusBarTree.appendChild(a);\n
-        if ( i !== 0 )\n
-        {\n
-          this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));\n
-        }\n
-        Xinha.freeLater(a);\n
-      }\n
-    }\n
-  }\n
-\n
-  for ( var cmd in this._toolbarObjects )\n
-  {\n
-    var btn = this._toolbarObjects[cmd];\n
-    var inContext = true;\n
-    // prevent iterating over wrong type\n
-    if ( typeof btn.state != \'function\' )\n
-    {\n
-      continue;\n
-    }\n
-    if ( btn.context && !text )\n
-    {\n
-      inContext = false;\n
-      var context = btn.context;\n
-      var attrs = [];\n
-      if ( /(.*)\\[(.*?)\\]/.test(context) )\n
-      {\n
-        context = RegExp.$1;\n
-        attrs = RegExp.$2.split(",");\n
-      }\n
-      context = context.toLowerCase();\n
-      var match = (context == "*");\n
-      for ( var k = 0; k < ancestors.length; ++k )\n
-      {\n
-        if ( !ancestors[k] )\n
-        {\n
-          // the impossible really happens.\n
-          continue;\n
-        }\n
-        if ( match || ( ancestors[k].tagName.toLowerCase() == context ) )\n
-        {\n
-          inContext = true;\n
-          var contextSplit = null;\n
-          var att = null;\n
-          var comp = null;\n
-          var attVal = null;\n
-          for ( var ka = 0; ka < attrs.length; ++ka )\n
-          {\n
-            contextSplit = attrs[ka].match(/(.*)(==|!=|===|!==|>|>=|<|<=)(.*)/);\n
-            att = contextSplit[1];\n
-            comp = contextSplit[2];\n
-            attVal = contextSplit[3];\n
-\n
-            if (!eval(ancestors[k][att] + comp + attVal))\n
-            {\n
-              inContext = false;\n
-              break;\n
-            }\n
-          }\n
-          if ( inContext )\n
-          {\n
-            break;\n
-          }\n
-        }\n
-      }\n
-    }\n
-    btn.state("enabled", (!text || btn.text) && inContext);\n
-    if ( typeof cmd == "function" )\n
-    {\n
-      continue;\n
-    }\n
-    // look-it-up in the custom dropdown boxes\n
-    var dropdown = this.config.customSelects[cmd];\n
-    if ( ( !text || btn.text ) && ( typeof dropdown != "undefined" ) )\n
-    {\n
-      dropdown.refresh(this);\n
-      continue;\n
-    }\n
-    switch (cmd)\n
-    {\n
-      case "fontname":\n
-      case "fontsize":\n
-        if ( !text )\n
-        {\n
-          try\n
-          {\n
-            var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();\n
-            if ( !value )\n
-            {\n
-              btn.element.selectedIndex = 0;\n
-              break;\n
-            }\n
-\n
-            // HACK -- retrieve the config option for this\n
-            // combo box.  We rely on the fact that the\n
-            // variable in config has the same name as\n
-            // button name in the toolbar.\n
-            var options = this.config[cmd];\n
-            var sIndex = 0;\n
-            for ( var j in options )\n
-            {\n
-            // FIXME: the following line is scary.\n
-              if ( ( j.toLowerCase() == value ) || ( options[j].substr(0, value.length).toLowerCase() == value ) )\n
-              {\n
-                btn.element.selectedIndex = sIndex;\n
-                throw "ok";\n
-              }\n
-              ++sIndex;\n
-            }\n
-            btn.element.selectedIndex = 0;\n
-          } catch(ex) {}\n
-        }\n
-      break;\n
-\n
-      // It\'s better to search for the format block by tag name from the\n
-      //  current selection upwards, because IE has a tendancy to return\n
-      //  things like \'heading 1\' for \'h1\', which breaks things if you want\n
-      //  to call your heading blocks \'header 1\'.  Stupid MS.\n
-      case "formatblock":\n
-        var blocks = [];\n
-        for ( var indexBlock in this.config.formatblock )\n
-        {\n
-          // prevent iterating over wrong type\n
-          if ( typeof this.config.formatblock[indexBlock] == \'string\' )\n
-          {\n
-            blocks[blocks.length] = this.config.formatblock[indexBlock];\n
-          }\n
-        }\n
-\n
-        var deepestAncestor = this._getFirstAncestor(this.getSelection(), blocks);\n
-        if ( deepestAncestor )\n
-        {\n
-          for ( var x = 0; x < blocks.length; x++ )\n
-          {\n
-            if ( blocks[x].toLowerCase() == deepestAncestor.tagName.toLowerCase() )\n
-            {\n
-              btn.element.selectedIndex = x;\n
-            }\n
-          }\n
-        }\n
-        else\n
-        {\n
-          btn.element.selectedIndex = 0;\n
-        }\n
-      break;\n
-\n
-      case "textindicator":\n
-        if ( !text )\n
-        {\n
-          try\n
-          {\n
-            var style = btn.element.style;\n
-            style.backgroundColor = Xinha._makeColor(doc.queryCommandValue(Xinha.is_ie ? "backcolor" : "hilitecolor"));\n
-            if ( /transparent/i.test(style.backgroundColor) )\n
-            {\n
-              // Mozilla\n
-              style.backgroundColor = Xinha._makeColor(doc.queryCommandValue("backcolor"));\n
-            }\n
-            style.color = Xinha._makeColor(doc.queryCommandValue("forecolor"));\n
-            style.fontFamily = doc.queryCommandValue("fontname");\n
-            style.fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";\n
-            style.fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";\n
-          } catch (ex) {\n
-            // alert(e + "\\n\\n" + cmd);\n
-          }\n
-        }\n
-      break;\n
-\n
-      case "htmlmode":\n
-        btn.state("active", text);\n
-      break;\n
-\n
-      case "lefttoright":\n
-      case "righttoleft":\n
-        var eltBlock = this.getParentElement();\n
-        while ( eltBlock && !Xinha.isBlockElement(eltBlock) )\n
-        {\n
-          eltBlock = eltBlock.parentNode;\n
-        }\n
-        if ( eltBlock )\n
-        {\n
-          btn.state("active", (eltBlock.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));\n
-        }\n
-      break;\n
-\n
-      default:\n
-        cmd = cmd.replace(/(un)?orderedlist/i, "insert$1orderedlist");\n
-        try\n
-        {\n
-          btn.state("active", (!text && doc.queryCommandState(cmd)));\n
-        } catch (ex) {}\n
-      break;\n
-    }\n
-  }\n
-  // take undo snapshots\n
-  if ( this._customUndo && !this._timerUndo )\n
-  {\n
-    this._undoTakeSnapshot();\n
-    var editor = this;\n
-    this._timerUndo = setTimeout(function() { editor._timerUndo = null; }, this.config.undoTimeout);\n
-  }\n
-  this.firePluginEvent(\'onUpdateToolbar\');\n
-};\n
-\n
-/** Returns a editor object referenced by the id or name of the textarea or the textarea node itself\n
- * For example to retrieve the HTML of an editor made out of the textarea with the id "myTextArea" you would do<br />\n
- * <code>\n
- *\t var editor = Xinha.getEditor("myTextArea");\n
- *   var html = editor.getEditorContent(); \n
- * </code>\n
- * @returns {Xinha|null} \n
- * @param {String|DomNode} ref id or name of the textarea or the textarea node itself\n
- */\n
-Xinha.getEditor = function(ref)\n
-{\n
-  for ( var i = __xinhas.length; i--; )\n
-  {\n
-    var editor = __xinhas[i];\n
-    if ( editor && ( editor._textArea.id == ref || editor._textArea.name == ref || editor._textArea == ref ) )\n
-    {\n
-      return editor;\n
-    }\n
-  }\n
-  return null;\n
-};\n
-/** Sometimes one wants to call a plugin method directly, e.g. from outside the editor.\n
- * This function returns the respective editor\'s instance of a plugin.\n
- * For example you might want to have a button to trigger SaveSubmit\'s save() method:<br />\n
- * <code>\n
- *\t &lt;button type="button" onclick="Xinha.getEditor(\'myTextArea\').getPluginInstance(\'SaveSubmit\').save();return false;"&gt;Save&lt;/button&gt;\n
- * </code>\n
- * @returns {PluginObject|null} \n
- * @param {String} plugin name of the plugin\n
- */\n
-Xinha.prototype.getPluginInstance = function (plugin)\n
-{\n
-  if (this.plugins[plugin])\n
-  {\n
-    return this.plugins[plugin].instance;\n
-  }\n
-  else\n
-  {\n
-    return null;\n
-  }\n
-};\n
-/** Returns an array with all the ancestor nodes of the selection or current cursor position.\n
-* @returns {Array}\n
-*/\n
-Xinha.prototype.getAllAncestors = function()\n
-{\n
-  var p = this.getParentElement();\n
-  var a = [];\n
-  while ( p && (p.nodeType == 1) && ( p.tagName.toLowerCase() != \'body\' ) )\n
-  {\n
-    a.push(p);\n
-    p = p.parentNode;\n
-  }\n
-  a.push(this._doc.body);\n
-  return a;\n
-};\n
-\n
-/** Traverses the DOM upwards and returns the first element that is of one of the specified types\n
- *  @param {Selection} sel  Selection object as returned by getSelection\n
- *  @param {Array} types Array of matching criteria.  Each criteria is either a string containing the tag name, or a callback used to select the element.\n
- *  @returns {DomNode|null} \n
- */\n
-Xinha.prototype._getFirstAncestor = function(sel, types)\n
-{\n
-  var prnt = this.activeElement(sel);\n
-  if ( prnt === null )\n
-  {\n
-    // Hmm, I think Xinha.getParentElement() would do the job better?? - James\n
-    try\n
-    {\n
-      prnt = (Xinha.is_ie ? this.createRange(sel).parentElement() : this.createRange(sel).commonAncestorContainer);\n
-    }\n
-    catch(ex)\n
-    {\n
-      return null;\n
-    }\n
-  }\n
-\n
-  if ( typeof types == \'string\' )\n
-  {\n
-    types = [types];\n
-  }\n
-\n
-  while ( prnt )\n
-  {\n
-    if ( prnt.nodeType == 1 )\n
-    {\n
-      if ( types === null )\n
-      {\n
-        return prnt;\n
-      }\n
-      for (var index=0; index<types.length; ++index) {\n
-        if (typeof types[index] == \'string\' && types[index] == prnt.tagName.toLowerCase()){\n
-          // Criteria is a tag name.  It matches\n
-        return prnt;\n
-      }\n
-        else if (typeof types[index] == \'function\' && types[index](this, prnt)) {\n
-          // Criteria is a callback.  It matches\n
-          return prnt;\n
-        }\n
-      }\n
-\n
-      if ( prnt.tagName.toLowerCase() == \'body\' )\n
-      {\n
-        break;\n
-      }\n
-      if ( prnt.tagName.toLowerCase() == \'table\' )\n
-      {\n
-        break;\n
-      }\n
-    }\n
-    prnt = prnt.parentNode;\n
-  }\n
-\n
-  return null;\n
-};\n
-\n
-/** Traverses the DOM upwards and returns the first element that is a block level element\n
- *  @param {Selection} sel  Selection object as returned by getSelection\n
- *  @returns {DomNode|null} \n
- */\n
-Xinha.prototype._getAncestorBlock = function(sel)\n
-{\n
-  // Scan upwards to find a block level element that we can change or apply to\n
-  var prnt = (Xinha.is_ie ? this.createRange(sel).parentElement : this.createRange(sel).commonAncestorContainer);\n
-\n
-  while ( prnt && ( prnt.nodeType == 1 ) )\n
-  {\n
-    switch ( prnt.tagName.toLowerCase() )\n
-    {\n
-      case \'div\':\n
-      case \'p\':\n
-      case \'address\':\n
-      case \'blockquote\':\n
-      case \'center\':\n
-      case \'del\':\n
-      case \'ins\':\n
-      case \'pre\':\n
-      case \'h1\':\n
-      case \'h2\':\n
-      case \'h3\':\n
-      case \'h4\':\n
-      case \'h5\':\n
-      case \'h6\':\n
-      case \'h7\':\n
-        // Block Element\n
-        return prnt;\n
-\n
-      case \'body\':\n
-      case \'noframes\':\n
-      case \'dd\':\n
-      case \'li\':\n
-      case \'th\':\n
-      case \'td\':\n
-      case \'noscript\' :\n
-        // Halting element (stop searching)\n
-        return null;\n
-\n
-      default:\n
-        // Keep lookin\n
-        break;\n
-    }\n
-  }\n
-\n
-  return null;\n
-};\n
-\n
-/** What\'s this? does nothing, has to be removed\n
- * \n
- * @deprecated\n
- */\n
-Xinha.prototype._createImplicitBlock = function(type)\n
-{\n
-  // expand it until we reach a block element in either direction\n
-  // then wrap the selection in a block and return\n
-  var sel = this.getSelection();\n
-  if ( Xinha.is_ie )\n
-  {\n
-    sel.empty();\n
-  }\n
-  else\n
-  {\n
-    sel.collapseToStart();\n
-  }\n
-\n
-  var rng = this.createRange(sel);\n
-\n
-  // Expand UP\n
-\n
-  // Expand DN\n
-};\n
-\n
-\n
-\n
-/**\n
- *  Call this function to surround the existing HTML code in the selection with\n
- *  your tags.  FIXME: buggy! Don\'t use this \n
- * @todo: when will it be deprecated ? Can it be removed already ?\n
- * @private (tagged private to not further promote use of this function)\n
- * @deprecated\n
- */\n
-Xinha.prototype.surroundHTML = function(startTag, endTag)\n
-{\n
-  var html = this.getSelectedHTML();\n
-  // the following also deletes the selection\n
-  this.insertHTML(startTag + html + endTag);\n
-};\n
-\n
-/** Return true if we have some selection\n
- *  @returns {Boolean} \n
- */\n
-Xinha.prototype.hasSelectedText = function()\n
-{\n
-  // FIXME: come _on_ mishoo, you can do better than this ;-)\n
-  return this.getSelectedHTML() !== \'\';\n
-};\n
-\n
-/***************************************************\n
- *  Category: EVENT HANDLERS\n
- ***************************************************/\n
-\n
-/** onChange handler for dropdowns in toolbar \n
- *  @private\n
- *  @param {DomNode} el Reference to the SELECT object\n
- *  @param {String} txt  The name of the select field, as in config.toolbar\n
- *  @returns {DomNode|null} \n
- */\n
-Xinha.prototype._comboSelected = function(el, txt)\n
-{\n
-  this.focusEditor();\n
-  var value = el.options[el.selectedIndex].value;\n
-  switch (txt)\n
-  {\n
-    case "fontname":\n
-    case "fontsize":\n
-      this.execCommand(txt, false, value);\n
-    break;\n
-    case "formatblock":\n
-      // Mozilla inserts an empty tag (<>) if no parameter is passed  \n
-      if ( !value )\n
-      {\n
-      \tthis.updateToolbar();\n
-      \tbreak;\n
-      }\n
-      if( !Xinha.is_gecko || value !== \'blockquote\' )\n
-      {\n
-        value = "<" + value + ">";\n
-      }\n
-      this.execCommand(txt, false, value);\n
-    break;\n
-    default:\n
-      // try to look it up in the registered dropdowns\n
-      var dropdown = this.config.customSelects[txt];\n
-      if ( typeof dropdown != "undefined" )\n
-      {\n
-        dropdown.action(this, value, el, txt);\n
-      }\n
-      else\n
-      {\n
-        alert("FIXME: combo box " + txt + " not implemented");\n
-      }\n
-    break;\n
-  }\n
-};\n
-\n
-/** Open a popup to select the hilitecolor or forecolor\n
- * @private\n
- * @param {String} cmdID The commande ID (hilitecolor or forecolor)\n
- */\n
-Xinha.prototype._colorSelector = function(cmdID)\n
-{\n
-  var editor = this;\t// for nested functions\n
-\n
-  // backcolor only works with useCSS/styleWithCSS (see mozilla bug #279330 & Midas doc)\n
-  // and its also nicer as <font>\n
-  if ( Xinha.is_gecko )\n
-  {\n
-    try\n
-    {\n
-     editor._doc.execCommand(\'useCSS\', false, false); // useCSS deprecated & replaced by styleWithCSS \n
-     editor._doc.execCommand(\'styleWithCSS\', false, true); \n
-\n
-    } catch (ex) {}\n
-  }\n
-  \n
-  var btn = editor._toolbarObjects[cmdID].element;\n
-  var initcolor;\n
-  if ( cmdID == \'hilitecolor\' )\n
-  {\n
-    if ( Xinha.is_ie )\n
-    {\n
-      cmdID = \'backcolor\';\n
-      initcolor = Xinha._colorToRgb(editor._doc.queryCommandValue("backcolor"));\n
-    }\n
-    else\n
-    {\n
-      initcolor = Xinha._colorToRgb(editor._doc.queryCommandValue("hilitecolor"));\n
-    }\n
-  }\n
-  else\n
-  {\n
-  \tinitcolor = Xinha._colorToRgb(editor._doc.queryCommandValue("forecolor"));\n
-  }\n
-  var cback = function(color) { editor._doc.execCommand(cmdID, false, color); };\n
-  if ( Xinha.is_ie )\n
-  {\n
-    var range = editor.createRange(editor.getSelection());\n
-    cback = function(color)\n
-    {\n
-      range.select();\n
-      editor._doc.execCommand(cmdID, false, color);\n
-    };\n
-  }\n
-  var picker = new Xinha.colorPicker(\n
-  {\n
-  \tcellsize:editor.config.colorPickerCellSize,\n
-  \tcallback:cback,\n
-  \tgranularity:editor.config.colorPickerGranularity,\n
-  \twebsafe:editor.config.colorPickerWebSafe,\n
-  \tsavecolors:editor.config.colorPickerSaveColors\n
-  });\n
-  picker.open(editor.config.colorPickerPosition, btn, initcolor);\n
-};\n
-\n
-/** This is a wrapper for the browser\'s execCommand function that handles things like \n
- *  formatting, inserting elements, etc.<br />\n
- *  It intercepts some commands and replaces them with our own implementation.<br />\n
- *  It provides a hook for the "firePluginEvent" system ("onExecCommand").<br /><br />\n
- *  For reference see:<br />\n
- *     <a href="http://www.mozilla.org/editor/midas-spec.html">Mozilla implementation</a><br />\n
- *     <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/execcommand.asp">MS implementation</a>\n
- *\n
- *  @see Xinha#firePluginEvent\n
- *  @param {String} cmdID command to be executed as defined in the browsers implemantations or Xinha custom\n
- *  @param {Boolean} UI for compatibility with the execCommand syntax; false in most (all) cases\n
- *  @param {Mixed} param Some commands require parameters\n
- *  @returns {Boolean} always false \n
- */\n
-Xinha.prototype.execCommand = function(cmdID, UI, param)\n
-{\n
-  var editor = this;\t// for nested functions\n
-  this.focusEditor();\n
-  cmdID = cmdID.toLowerCase();\n
-  \n
-  // See if any plugins want to do something special\n
-  if(this.firePluginEvent(\'onExecCommand\', cmdID, UI, param))\n
-  {\n
-    this.updateToolbar();\n
-    return false;\n
-  }\n
-\n
-  switch (cmdID)\n
-  {\n
-    case "htmlmode":\n
-      this.setMode();\n
-    break;\n
-\n
-    case "hilitecolor":\n
-    case "forecolor":\n
-      this._colorSelector(cmdID);\n
-    break;\n
-\n
-    case "createlink":\n
-      this._createLink();\n
-    break;\n
-\n
-    case "undo":\n
-    case "redo":\n
-      if (this._customUndo)\n
-      {\n
-        this[cmdID]();\n
-      }\n
-      else\n
-      {\n
-        this._doc.execCommand(cmdID, UI, param);\n
-      }\n
-    break;\n
-\n
-    case "inserttable":\n
-      this._insertTable();\n
-    break;\n
-\n
-    case "insertimage":\n
-      this._insertImage();\n
-    break;\n
-\n
-    case "showhelp":\n
-      this._popupDialog(editor.config.URIs.help, null, this);\n
-    break;\n
-\n
-    case "killword":\n
-      this._wordClean();\n
-    break;\n
-\n
-    case "cut":\n
-    case "copy":\n
-    case "paste":\n
-      this._doc.execCommand(cmdID, UI, param);\n
-      if ( this.config.killWordOnPaste )\n
-      {\n
-        this._wordClean();\n
-      }\n
-    break;\n
-    case "lefttoright":\n
-    case "righttoleft":\n
-      if (this.config.changeJustifyWithDirection) \n
-      {\n
-        this._doc.execCommand((cmdID == "righttoleft") ? "justifyright" : "justifyleft", UI, param);\n
-      }\n
-      var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";\n
-      var el = this.getParentElement();\n
-      while ( el && !Xinha.isBlockElement(el) )\n
-      {\n
-        el = el.parentNode;\n
-      }\n
-      if ( el )\n
-      {\n
-        if ( el.style.direction == dir )\n
-        {\n
-          el.style.direction = "";\n
-        }\n
-        else\n
-        {\n
-          el.style.direction = dir;\n
-        }\n
-      }\n
-    break;\n
-    \n
-    case \'justifyleft\'  :\n
-    case \'justifyright\' :\n
-      cmdID.match(/^justify(.*)$/);\n
-      var ae = this.activeElement(this.getSelection());      \n
-      if(ae && ae.tagName.toLowerCase() == \'img\')\n
-      {\n
-        ae.align = ae.align == RegExp.$1 ? \'\' : RegExp.$1;\n
-      }\n
-      else\n
-      {\n
-        this._doc.execCommand(cmdID, UI, param);\n
-      }\n
-    break;\n
-    \n
-    default:\n
-      try\n
-      {\n
-        this._doc.execCommand(cmdID, UI, param);\n
-      }\n
-      catch(ex)\n
-      {\n
-        if ( this.config.debug )\n
-        {\n
-          alert(ex + "\\n\\nby execCommand(" + cmdID + ");");\n
-        }\n
-      }\n
-    break;\n
-  }\n
-\n
-  this.updateToolbar();\n
-  return false;\n
-};\n
-\n
-/** A generic event handler for things that happen in the IFRAME\'s document.<br />\n
- *  It provides two hooks for the "firePluginEvent" system:<br />\n
- *   "onKeyPress"<br />\n
- *   "onMouseDown"\n
- *  @see Xinha#firePluginEvent\n
- *  @param {Event} ev\n
- */\n
-Xinha.prototype._editorEvent = function(ev)\n
-{\n
-  var editor = this;\n
-\n
-  //call events of textarea\n
-  if ( typeof editor._textArea[\'on\'+ev.type] == "function" )\n
-  {\n
-    editor._textArea[\'on\'+ev.type](ev);\n
-  }\n
-  \n
-  if ( this.isKeyEvent(ev) )\n
-  {\n
-    // Run the ordinary plugins first\n
-    if(editor.firePluginEvent(\'onKeyPress\', ev))\n
-    {\n
-      return false;\n
-    }\n
-    \n
-    // Handle the core shortcuts\n
-    if ( this.isShortCut( ev ) )\n
-    {\n
-      this._shortCuts(ev);\n
-    }\n
-  }\n
-\n
-  if ( ev.type == \'mousedown\' )\n
-  {\n
-    if(editor.firePluginEvent(\'onMouseDown\', ev))\n
-    {\n
-      return false;\n
-    }\n
-  }\n
-\n
-  // update the toolbar state after some time\n
-  if ( editor._timerToolbar )\n
-  {\n
-    clearTimeout(editor._timerToolbar);\n
-  }\n
-  if (!this.suspendUpdateToolbar)\n
-  {\n
-  editor._timerToolbar = setTimeout(\n
-    function()\n
-    {\n
-      editor.updateToolbar();\n
-      editor._timerToolbar = null;\n
-    },\n
-    250);\n
-  }\n
-};\n
-\n
-/** Handle double click events.\n
- *  See dblclickList in the config.\n
- */\n
- \n
-Xinha.prototype._onDoubleClick = function(ev)\n
-{\n
-  var editor=this;\n
-  var target = Xinha.is_ie ? ev.srcElement : ev.target;\n
-  var tag = target.tagName;\n
-  var className = target.className;\n
-  if (tag) {\n
-    tag = tag.toLowerCase();\n
-    if (className && (this.config.dblclickList[tag+"."+className] != undefined))\n
-      this.config.dblclickList[tag+"."+className][0](editor, target);\n
-    else if (this.config.dblclickList[tag] != undefined)\n
-      this.config.dblclickList[tag][0](editor, target);\n
-  };\n
-};\n
-\n
-/** Handles ctrl + key shortcuts \n
- *  @TODO: make this mor flexible\n
- *  @private\n
- *  @param {Event} ev\n
- */\n
-Xinha.prototype._shortCuts = function (ev)\n
-{\n
-  var key = this.getKey(ev).toLowerCase();\n
-  var cmd = null;\n
-  var value = null;\n
-  switch (key)\n
-  {\n
-    // simple key commands follow\n
-\n
-    case \'b\': cmd = "bold"; break;\n
-    case \'i\': cmd = "italic"; break;\n
-    case \'u\': cmd = "underline"; break;\n
-    case \'s\': cmd = "strikethrough"; break;\n
-    case \'l\': cmd = "justifyleft"; break;\n
-    case \'e\': cmd = "justifycenter"; break;\n
-    case \'r\': cmd = "justifyright"; break;\n
-    case \'j\': cmd = "justifyfull"; break;\n
-    case \'z\': cmd = "undo"; break;\n
-    case \'y\': cmd = "redo"; break;\n
-    case \'v\': cmd = "paste"; break;\n
-    case \'n\':\n
-    cmd = "formatblock";\n
-    value = "p";\n
-    break;\n
-\n
-    case \'0\': cmd = "killword"; break;\n
-\n
-    // headings\n
-    case \'1\':\n
-    case \'2\':\n
-    case \'3\':\n
-    case \'4\':\n
-    case \'5\':\n
-    case \'6\':\n
-    cmd = "formatblock";\n
-    value = "h" + key;\n
-    break;\n
-  }\n
-  if ( cmd )\n
-  {\n
-    // execute simple command\n
-    this.execCommand(cmd, false, value);\n
-    Xinha._stopEvent(ev);\n
-  }\n
-};\n
-/** Changes the type of a given node\n
- *  @param {DomNode} el The element to convert\n
- *  @param {String} newTagName The type the element will be converted to\n
- *  @returns {DomNode} A reference to the new element\n
- */\n
-Xinha.prototype.convertNode = function(el, newTagName)\n
-{\n
-  var newel = this._doc.createElement(newTagName);\n
-  while ( el.firstChild )\n
-  {\n
-    newel.appendChild(el.firstChild);\n
-  }\n
-  return newel;\n
-};\n
-\n
-/** Scrolls the editor iframe to a given element or to the cursor\n
- *  @param {DomNode} e optional The element to scroll to; if ommitted, element the element the cursor is in\n
- */\n
-Xinha.prototype.scrollToElement = function(e)\n
-{\n
-  if(!e)\n
-  {\n
-    e = this.getParentElement();\n
-    if(!e)\n
-    {\n
-      return;\n
-    }\n
-  }\n
-  \n
-  // This was at one time limited to Gecko only, but I see no reason for it to be. - James\n
-  var position = Xinha.getElementTopLeft(e);  \n
-  this._iframe.contentWindow.scrollTo(position.left, position.top);\n
-};\n
-\n
-/** Get the edited HTML\n
- *  \n
- *  @public\n
- *  @returns {String} HTML content\n
- */\n
-Xinha.prototype.getEditorContent = function()\n
-{\n
-  return this.outwardHtml(this.getHTML());\n
-};\n
-\n
-/** Completely change the HTML inside the editor\n
- *\n
- *  @public\n
- *  @param {String} html new content\n
- */\n
-Xinha.prototype.setEditorContent = function(html)\n
-{\n
-  this.setHTML(this.inwardHtml(html));\n
-};\n
-/** Saves the contents of all Xinhas to their respective textareas\n
- *  @public \n
- */\n
-Xinha.updateTextareas = function()\n
-{\n
-  var e;\n
-  for (var i=0;i<__xinhas.length;i++)\n
-  {\n
-    e = __xinhas[i];\n
-    e._textArea.value = e.getEditorContent();\n
-  }\n
-}\n
-/** Get the raw edited HTML, should not be used without Xinha.prototype.outwardHtml()\n
- *  \n
- *  @private\n
- *  @returns {String} HTML content\n
- */\n
-Xinha.prototype.getHTML = function()\n
-{\n
-  var html = \'\';\n
-  switch ( this._editMode )\n
-  {\n
-    case "wysiwyg":\n
-      if ( !this.config.fullPage )\n
-      {\n
-        html = Xinha.getHTML(this._doc.body, false, this).trim();\n
-      }\n
-      else\n
-      {\n
-        html = this.doctype + "\\n" + Xinha.getHTML(this._doc.documentElement, true, this);\n
-      }\n
-    break;\n
-    case "textmode":\n
-      html = this._textArea.value;\n
-    break;\n
-    default:\n
-      alert("Mode <" + this._editMode + "> not defined!");\n
-      return false;\n
-  }\n
-  return html;\n
-};\n
-\n
-/** Performs various transformations of the HTML used internally, complement to Xinha.prototype.inwardHtml()  \n
- *  Plugins can provide their own, additional transformations by defining a plugin.prototype.outwardHtml() implematation,\n
- *  which is called by this function\n
- *\n
- *  @private\n
- *  @see Xinha#inwardHtml\n
- *  @param {String} html\n
- *  @returns {String} HTML content\n
- */\n
-Xinha.prototype.outwardHtml = function(html)\n
-{\n
-  for ( var i in this.plugins )\n
-  {\n
-    var plugin = this.plugins[i].instance;    \n
-    if ( plugin && typeof plugin.outwardHtml == "function" )\n
-    {\n
-      html = plugin.outwardHtml(html);\n
-    }\n
-  }\n
-  \n
-  html = html.replace(/<(\\/?)b(\\s|>|\\/)/ig, "<$1strong$2");\n
-  html = html.replace(/<(\\/?)i(\\s|>|\\/)/ig, "<$1em$2");\n
-  html = html.replace(/<(\\/?)strike(\\s|>|\\/)/ig, "<$1del$2");\n
-  \n
-  // remove disabling of inline event handle inside Xinha iframe\n
-  html = html.replace(/(<[^>]*on(click|mouse(over|out|up|down))=[\'"])if\\(window\\.parent &amp;&amp; window\\.parent\\.Xinha\\)\\{return false\\}/gi,\'$1\');\n
-\n
-  // Figure out what our server name is, and how it\'s referenced\n
-  var serverBase = location.href.replace(/(https?:\\/\\/[^\\/]*)\\/.*/, \'$1\') + \'/\';\n
-\n
-  // IE puts this in can\'t figure out why\n
-  //  leaving this in the core instead of InternetExplorer \n
-  //  because it might be something we are doing so could present itself\n
-  //  in other browsers - James \n
-  html = html.replace(/https?:\\/\\/null\\//g, serverBase);\n
-\n
-  // Make semi-absolute links to be truely absolute\n
-  //  we do this just to standardize so that special replacements knows what\n
-  //  to expect\n
-  html = html.replace(/((href|src|background)=[\\\'\\"])\\/+/ig, \'$1\' + serverBase);\n
-\n
-  html = this.outwardSpecialReplacements(html);\n
-\n
-  html = this.fixRelativeLinks(html);\n
-\n
-  if ( this.config.sevenBitClean )\n
-  {\n
-    html = html.replace(/[^ -~\\r\\n\\t]/g, function(c) { return (c != Xinha.cc) ? \'&#\'+c.charCodeAt(0)+\';\' : c; });\n
-  }\n
-\n
-  //prevent execution of JavaScript (Ticket #685)\n
-  html = html.replace(/(<script[^>]*((type=[\\"\\\']text\\/)|(language=[\\"\\\'])))(freezescript)/gi,"$1javascript");\n
-\n
-  // If in fullPage mode, strip the coreCSS\n
-  if(this.config.fullPage)\n
-  {\n
-    html = Xinha.stripCoreCSS(html);\n
-  }\n
-\n
-  if (typeof this.config.outwardHtml == \'function\' )\n
-  {\n
-    html = this.config.outwardHtml(html);\n
-  }\n
-\n
-  return html;\n
-};\n
-\n
-/** Performs various transformations of the HTML to be edited \n
- *  Plugins can provide their own, additional transformations by defining a plugin.prototype.inwardHtml() implematation,\n
- *  which is called by this function\n
- *  \n
- *  @private\n
- *  @see Xinha#outwardHtml\n
- *  @param {String} html  \n
- *  @returns {String} transformed HTML\n
- */\n
-Xinha.prototype.inwardHtml = function(html)\n
-{  \n
-  for ( var i in this.plugins )\n
-  {\n
-    var plugin = this.plugins[i].instance;    \n
-    if ( plugin && typeof plugin.inwardHtml == "function" )\n
-    {\n
-      html = plugin.inwardHtml(html);\n
-    }    \n
-  }\n
-    \n
-  // Both IE and Gecko use strike instead of del (#523)\n
-  html = html.replace(/<(\\/?)del(\\s|>|\\/)/ig, "<$1strike$2");\n
-\n
-  // disable inline event handle inside Xinha iframe\n
-  html = html.replace(/(<[^>]*on(click|mouse(over|out|up|down))=["\'])/gi,\'$1if(window.parent &amp;&amp; window.parent.Xinha){return false}\');\n
-  \n
-  html = this.inwardSpecialReplacements(html);\n
-\n
-  html = html.replace(/(<script[^>]*((type=[\\"\\\']text\\/)|(language=[\\"\\\'])))(javascript)/gi,"$1freezescript");\n
-\n
-  // For IE\'s sake, make any URLs that are semi-absolute (="/....") to be\n
-  // truely absolute\n
-  var nullRE = new RegExp(\'((href|src|background)=[\\\'"])/+\', \'gi\');\n
-  html = html.replace(nullRE, \'$1\' + location.href.replace(/(https?:\\/\\/[^\\/]*)\\/.*/, \'$1\') + \'/\');\n
-\n
-  html = this.fixRelativeLinks(html);\n
-  \n
-  // If in fullPage mode, add the coreCSS\n
-  if(this.config.fullPage)\n
-  {\n
-    html = Xinha.addCoreCSS(html);\n
-  }\n
-\n
-  if (typeof this.config.inwardHtml == \'function\' )\n
-  {\n
-    html = this.config.inwardHtml(html);\n
-  }\n
-\n
-  return html;\n
-};\n
-/** Apply the replacements defined in Xinha.Config.specialReplacements\n
- *  \n
- *  @private\n
- *  @see Xinha#inwardSpecialReplacements\n
- *  @param {String} html\n
- *  @returns {String}  transformed HTML\n
- */\n
-Xinha.prototype.outwardSpecialReplacements = function(html)\n
-{\n
-  for ( var i in this.config.specialReplacements )\n
-  {\n
-    var from = this.config.specialReplacements[i];\n
-    var to   = i; // why are declaring a new variable here ? Seems to be better to just do : for (var to in config)\n
-    // prevent iterating over wrong type\n
-    if ( typeof from.replace != \'function\' || typeof to.replace != \'function\' )\n
-    {\n
-      continue;\n
-    } \n
-    // alert(\'out : \' + from + \'=>\' + to);\n
-    var reg = new RegExp(Xinha.escapeStringForRegExp(from), \'g\');\n
-    html = html.replace(reg, to.replace(/\\$/g, \'$$$$\'));\n
-    //html = html.replace(from, to);\n
-  }\n
-  return html;\n
-};\n
-/** Apply the replacements defined in Xinha.Config.specialReplacements\n
- *  \n
- *  @private\n
- *  @see Xinha#outwardSpecialReplacements\n
- *  @param {String} html\n
- *  @returns {String}  transformed HTML\n
- */\n
-Xinha.prototype.inwardSpecialReplacements = function(html)\n
-{\n
-  // alert("inward");\n
-  for ( var i in this.config.specialReplacements )\n
-  {\n
-    var from = i; // why are declaring a new variable here ? Seems to be better to just do : for (var from in config)\n
-    var to   = this.config.specialReplacements[i];\n
-    // prevent iterating over wrong type\n
-    if ( typeof from.replace != \'function\' || typeof to.replace != \'function\' )\n
-    {\n
-      continue;\n
-    }\n
-    // alert(\'in : \' + from + \'=>\' + to);\n
-    //\n
-    // html = html.replace(reg, to);\n
-    // html = html.replace(from, to);\n
-    var reg = new RegExp(Xinha.escapeStringForRegExp(from), \'g\');\n
-    html = html.replace(reg, to.replace(/\\$/g, \'$$$$\')); // IE uses doubled dollar signs to escape backrefs, also beware that IE also implements $& $_ and $\' like perl.\n
-  }\n
-  return html;\n
-};\n
-/** Transforms the paths in src & href attributes\n
- *  \n
- *  @private\n
- *  @see Xinha.Config#expandRelativeUrl\n
- *  @see Xinha.Config#stripSelfNamedAnchors\n
- *  @see Xinha.Config#stripBaseHref\n
- *  @see Xinha.Config#baseHref\n
- *  @param {String} html \n
- *  @returns {String} transformed HTML\n
- */\n
-Xinha.prototype.fixRelativeLinks = function(html)\n
-{\n
-  if ( typeof this.config.expandRelativeUrl != \'undefined\' && this.config.expandRelativeUrl ) \n
-  {\n
-    if (html == null)\n
-    {\n
-      return "";\n
-    }\n
-    var src = html.match(/(src|href)="([^"]*)"/gi);\n
-    var b = document.location.href;\n
-    if ( src )\n
-    {\n
-      var url,url_m,relPath,base_m,absPath;\n
-      for ( var i=0;i<src.length;++i )\n
-      {\n
-        url = src[i].match(/(src|href)="([^"]*)"/i);\n
-        url_m = url[2].match( /\\.\\.\\//g );\n
-        if ( url_m )\n
-        {\n
-          relPath = new RegExp( "(.*?)(([^\\/]*\\/){"+ url_m.length+"})[^\\/]*$" );\n
-          base_m = b.match( relPath );\n
-          absPath = url[2].replace(/(\\.\\.\\/)*/,base_m[1]);\n
-          html = html.replace( new RegExp(Xinha.escapeStringForRegExp(url[2])),absPath );\n
-        }\n
-      }\n
-    }\n
-  }\n
-  \n
-  if ( typeof this.config.stripSelfNamedAnchors != \'undefined\' && this.config.stripSelfNamedAnchors )\n
-  {\n
-    var stripRe = new RegExp("((href|src|background)=\\")("+Xinha.escapeStringForRegExp(window.unescape(document.location.href.replace(/&/g,\'&amp;\'))) + \')([#?][^\\\'" ]*)\', \'g\');\n
-    html = html.replace(stripRe, \'$1$4\');\n
-  }\n
-\n
-  if ( typeof this.config.stripBaseHref != \'undefined\' && this.config.stripBaseHref )\n
-  {\n
-    var baseRe = null;\n
-    if ( typeof this.config.baseHref != \'undefined\' && this.config.baseHref !== null )\n
-    {\n
-      baseRe = new RegExp( "((href|src|background|action)=\\")(" + Xinha.escapeStringForRegExp(this.config.baseHref.replace(/([^\\/]\\/)(?=.+\\.)[^\\/]*$/, "$1")) + ")", \'g\' );\n
-\t  html = html.replace(baseRe, \'$1\');\n
-    }\n
-    baseRe = new RegExp( "((href|src|background|action)=\\")(" +  Xinha.escapeStringForRegExp(document.location.href.replace( /^(https?:\\/\\/[^\\/]*)(.*)/, \'$1\' )) + ")", \'g\' );\n
-    html = html.replace(baseRe, \'$1\');\n
-  }\n
-\n
-  return html;\n
-};\n
-\n
-/** retrieve the HTML (fastest version, but uses innerHTML)\n
- *  \n
- *  @private\n
- *  @returns {String} HTML content\n
- */\n
-Xinha.prototype.getInnerHTML = function()\n
-{\n
-  if ( !this._doc.body )\n
-  {\n
-    return \'\';\n
-  }\n
-  var html = "";\n
-  switch ( this._editMode )\n
-  {\n
-    case "wysiwyg":\n
-      if ( !this.config.fullPage )\n
-      {\n
-        // return this._doc.body.innerHTML;\n
-        html = this._doc.body.innerHTML;\n
-      }\n
-      else\n
-      {\n
-        html = this.doctype + "\\n" + this._doc.documentElement.innerHTML;\n
-      }\n
-    break;\n
-    case "textmode" :\n
-      html = this._textArea.value;\n
-    break;\n
-    default:\n
-      alert("Mode <" + this._editMode + "> not defined!");\n
-      return false;\n
-  }\n
-\n
-  return html;\n
-};\n
-\n
-/** Completely change the HTML inside\n
- *\n
- *  @private\n
- *  @param {String} html new content, should have been run through inwardHtml() first\n
- */\n
-Xinha.prototype.setHTML = function(html)\n
-{\n
-  if ( !this.config.fullPage )\n
-  {\n
-    this._doc.body.innerHTML = html;\n
-  }\n
-  else\n
-  {\n
-    this.setFullHTML(html);\n
-  }\n
-  this._textArea.value = html;\n
-};\n
-\n
-/** sets the given doctype (useful only when config.fullPage is true)\n
- *  \n
- *  @private\n
- *  @param {String} doctype\n
- */\n
-Xinha.prototype.setDoctype = function(doctype)\n
-{\n
-  this.doctype = doctype;\n
-};\n
-\n
-/***************************************************\n
- *  Category: UTILITY FUNCTIONS\n
- ***************************************************/\n
-\n
-/** Variable used to pass the object to the popup editor window.\n
- *  @FIXME: Is this in use?\n
- *  @deprecated \n
- *  @private\n
- *  @type {Object}\n
- */\n
-Xinha._object = null;\n
-\n
-/** Arrays are identified as "object" in typeof calls. Adding this tag to the Array prototype allows to distinguish between the two\n
- */\n
-Array.prototype.isArray = true;\n
-/** RegExps are identified as "object" in typeof calls. Adding this tag to the RegExp prototype allows to distinguish between the two\n
- */\n
-RegExp.prototype.isRegExp = true;\n
-/** function that returns a clone of the given object\n
- *  \n
- *  @private\n
- *  @param {Object} obj\n
- *  @returns {Object} cloned object\n
- */\n
-Xinha.cloneObject = function(obj)\n
-{\n
-  if ( !obj )\n
-  {\n
-    return null;\n
-  }\n
-  var newObj = obj.isArray ? [] : {};\n
-\n
-  // check for function and RegExp objects (as usual, IE is fucked up)\n
-  if ( obj.constructor.toString().match( /\\s*function Function\\(/ ) || typeof obj == \'function\' )\n
-  {\n
-    newObj = obj; // just copy reference to it\n
-  }\n
-  else if (  obj.isRegExp )\n
-  {\n
-    newObj = eval( obj.toString() ); //see no way without eval\n
-  }\n
-  else\n
-  {\n
-    for ( var n in obj )\n
-    {\n
-      var node = obj[n];\n
-      if ( typeof node == \'object\' )\n
-      {\n
-        newObj[n] = Xinha.cloneObject(node);\n
-      }\n
-      else\n
-      {\n
-        newObj[n] = node;\n
-      }\n
-    }\n
-  }\n
-\n
-  return newObj;\n
-};\n
-\n
-\n
-/** Extend one class from another, that is, make a sub class.\n
- *  This manner of doing it was probably first devised by Kevin Lindsey\n
- *\n
- *  http://kevlindev.com/tutorials/javascript/inheritance/index.htm\n
- *\n
- *  It has subsequently been used in one form or another by various toolkits \n
- *  such as the YUI.\n
- *\n
- *  I make no claim as to understanding it really, but it works.\n
- * \n
- *  Example Usage:\n
- *  {{{\n
- *  -------------------------------------------------------------------------\n
- \n
-    // =========  MAKING THE INITIAL SUPER CLASS ===========\n
-    \n
-        document.write("<h1>Superclass Creation And Test</h1>");\n
-    \n
-        function Vehicle(name, sound)\n
-        {    \n
-          this.name  = name;\n
-          this.sound = sound\n
-        }\n
-      \n
-        Vehicle.prototype.pressHorn = function()\n
-        {\n
-          document.write(this.name + \': \' + this.sound + \'<br/>\');\n
-        }\n
-        \n
-        var Bedford  = new Vehicle(\'Bedford Van\', \'Honk Honk\');\n
-        Bedford.pressHorn(); // Vehicle::pressHorn() is defined\n
-    \n
-    \n
-    // ========= MAKING A SUBCLASS OF A SUPER CLASS =========\n
-    \n
-        document.write("<h1>Subclass Creation And Test</h1>");\n
-        \n
-        // Make the sub class constructor first\n
-        Car = function(name)\n
-        {\n
-          // This is how we call the parent\'s constructor, note that\n
-          // we are using Car.parent.... not "this", we can\'t use this.\n
-          Car.parentConstructor.call(this, name, \'Toot Toot\');\n
-        }\n
-        \n
-        // Remember the subclass comes first, then the base class, you are extending\n
-        // Car with the methods and properties of Vehicle.\n
-        Xinha.extend(Car, Vehicle);\n
-        \n
-        var MazdaMx5 = new Car(\'Mazda MX5\');  \n
-        MazdaMx5.pressHorn(); // Car::pressHorn() is inherited from Vehicle::pressHorn()\n
-    \n
-    // =========  ADDING METHODS TO THE SUB CLASS ===========\n
-\n
-        document.write("<h1>Add Method to Sub Class And Test</h1>");\n
-        \n
-        Car.prototype.isACar = function()\n
-        {\n
-          document.write(this.name + ": Car::isACar() is implemented, this is a car! <br/>");\n
-          this.pressHorn();\n
-        }\n
-       \n
-        MazdaMx5.isACar(); // Car::isACar() is defined as above\n
-        try      { Bedford.isACar(); } // Vehicle::isACar() is not defined, will throw this exception\n
-        catch(e) { document.write("Bedford: Vehicle::onGettingCutOff() not implemented, this is not a car!<br/>"); }\n
-    \n
-    // =========  EXTENDING A METHOD (CALLING MASKED PARENT METHODS) ===========\n
-    \n
-        document.write("<h1>Extend/Override Inherited Method in Sub Class And Test</h1>");\n
-        \n
-        Car.prototype.pressHorn = function()\n
-        { \n
-          document.write(this.name + \': I am going to press the horn... <br/>\');\n
-          Car.superClass.pressHorn.call(this);        \n
-        }\n
-        MazdaMx5.pressHorn(); // Car::pressHorn()\n
-        Bedford.pressHorn();  // Vehicle::pressHorn()\n
-        \n
-    // =========  MODIFYING THE SUPERCLASS AFTER SUBCLASSING ===========\n
-    \n
-        document.write("<h1>Add New Method to Superclass And Test In Subclass</h1>");  \n
-        \n
-        Vehicle.prototype.startUp = function() { document.write(this.name + ": Vroooom <br/>"); }  \n
-        MazdaMx5.startUp(); // Cars get the prototype\'d startUp() also.\n
-        \n
- *  -------------------------------------------------------------------------\n
- *  }}}  \n
- *\n
- *  @param subclass_constructor (optional)  Constructor function for the subclass\n
- *  @param superclass Constructor function for the superclass \n
- */\n
-\n
-Xinha.extend = function(subClass, baseClass) {\n
-   function inheritance() {}\n
-   inheritance.prototype = baseClass.prototype;\n
-\n
-   subClass.prototype = new inheritance();\n
-   subClass.prototype.constructor = subClass;\n
-   subClass.parentConstructor = baseClass;\n
-   subClass.superClass = baseClass.prototype;\n
-}\n
-\n
-/** Event Flushing\n
- *  To try and work around memory leaks in the rather broken\n
- *  garbage collector in IE, Xinha.flushEvents can be called\n
- *  onunload, it will remove any event listeners (that were added\n
- *  through _addEvent(s)) and clear any DOM-0 events.\n
- *  @private\n
- *\n
- */\n
-Xinha.flushEvents = function()\n
-{\n
-  var x = 0;\n
-  // @todo : check if Array.prototype.pop exists for every supported browsers\n
-  var e = Xinha._eventFlushers.pop();\n
-  while ( e )\n
-  {\n
-    try\n
-    {\n
-      if ( e.length == 3 )\n
-      {\n
-        Xinha._removeEvent(e[0], e[1], e[2]);\n
-        x++;\n
-      }\n
-      else if ( e.length == 2 )\n
-      {\n
-        e[0][\'on\' + e[1]] = null;\n
-        e[0]._xinha_dom0Events[e[1]] = null;\n
-        x++;\n
-      }\n
-    }\n
-    catch(ex)\n
-    {\n
-      // Do Nothing\n
-    }\n
-    e = Xinha._eventFlushers.pop();\n
-  }\n
-  \n
-  /* \n
-    // This code is very agressive, and incredibly slow in IE, so I\'ve disabled it.\n
-    \n
-    if(document.all)\n
-    {\n
-      for(var i = 0; i < document.all.length; i++)\n
-      {\n
-        for(var j in document.all[i])\n
-        {\n
-          if(/^on/.test(j) && typeof document.all[i][j] == \'function\')\n
-          {\n
-            document.all[i][j] = null;\n
-            x++;\n
-          }\n
-        }\n
-      }\n
-    }\n
-  */\n
-  \n
-  // alert(\'Flushed \' + x + \' events.\');\n
-};\n
- /** Holds the events to be flushed\n
-  * @type Array\n
-  */\n
-Xinha._eventFlushers = [];\n
-\n
-if ( document.addEventListener )\n
-{\n
- /** adds an event listener for the specified element and event type\n
- *  \n
- *  @public\n
- *  @see   Xinha#_addEvents\n
- *  @see   Xinha#addDom0Event\n
- *  @see   Xinha#prependDom0Event\n
- *  @param {DomNode}  el the DOM element the event should be attached to \n
- *  @param {String}   evname the name of the event to listen for (without leading "on")\n
- *  @param {function} func the function to be called when the event is fired\n
- */\n
-  Xinha._addEvent = function(el, evname, func)\n
-  {\n
-    el.addEventListener(evname, func, false);\n
-    Xinha._eventFlushers.push([el, evname, func]);\n
-  };\n
- \n
- /** removes an event listener previously added\n
- *  \n
- *  @public\n
- *  @see   Xinha#_removeEvents\n
- *  @param {DomNode}  el the DOM element the event should be removed from \n
- *  @param {String}   evname the name of the event the listener should be removed from (without leading "on")\n
- *  @param {function} func the function to be removed\n
- */\n
-  Xinha._removeEvent = function(el, evname, func)\n
-  {\n
-    el.removeEventListener(evname, func, false);\n
-  };\n
- \n
- /** stops bubbling of the event, if no further listeners should be triggered\n
- *  \n
- *  @public\n
- *  @param {event} ev the event to be stopped\n
- */\n
-  Xinha._stopEvent = function(ev)\n
-  {\n
-    ev.preventDefault();\n
-    ev.stopPropagation();\n
-  };\n
-}\n
- /** same as above, for IE\n
- *  \n
- */\n
-else if ( document.attachEvent )\n
-{\n
-  Xinha._addEvent = function(el, evname, func)\n
-  {\n
-    el.attachEvent("on" + evname, func);\n
-    Xinha._eventFlushers.push([el, evname, func]);\n
-  };\n
-  Xinha._removeEvent = function(el, evname, func)\n
-  {\n
-    el.detachEvent("on" + evname, func);\n
-  };\n
-  Xinha._stopEvent = function(ev)\n
-  {\n
-    try\n
-    {\n
-      ev.cancelBubble = true;\n
-      ev.returnValue = false;\n
-    }\n
-    catch (ex)\n
-    {\n
-      // Perhaps we could try here to stop the window.event\n
-      // window.event.cancelBubble = true;\n
-      // window.event.returnValue = false;\n
-    }\n
-  };\n
-}\n
-else\n
-{\n
-  Xinha._addEvent = function(el, evname, func)\n
-  {\n
-    alert(\'_addEvent is not supported\');\n
-  };\n
-  Xinha._removeEvent = function(el, evname, func)\n
-  {\n
-    alert(\'_removeEvent is not supported\');\n
-  };\n
-  Xinha._stopEvent = function(ev)\n
-  {\n
-    alert(\'_stopEvent is not supported\');\n
-  };\n
-}\n
- /** add several events at once to one element\n
- *  \n
- *  @public\n
- *  @see Xinha#_addEvent\n
- *  @param {DomNode}  el the DOM element the event should be attached to \n
- *  @param {Array}    evs the names of the event to listen for (without leading "on")\n
- *  @param {function} func the function to be called when the event is fired\n
- */\n
-Xinha._addEvents = function(el, evs, func)\n
-{\n
-  for ( var i = evs.length; --i >= 0; )\n
-  {\n
-    Xinha._addEvent(el, evs[i], func);\n
-  }\n
-};\n
- /** remove several events at once to from element\n
- *  \n
- *  @public\n
- *  @see Xinha#_removeEvent\n
- *  @param {DomNode}  el the DOM element the events should be remove from\n
- *  @param {Array}    evs the names of the events the listener should be removed from (without leading "on")\n
- *  @param {function} func the function to be removed\n
- */\n
-Xinha._removeEvents = function(el, evs, func)\n
-{\n
-  for ( var i = evs.length; --i >= 0; )\n
-  {\n
-    Xinha._removeEvent(el, evs[i], func);\n
-  }\n
-};\n
-\n
-/** Adds a function that is executed in the moment the DOM is ready, but as opposed to window.onload before images etc. have been loaded\n
-*   http://dean.edwards.name/weblog/2006/06/again/\n
-*   IE part from jQuery\n
-*  @public\n
-*  @author Dean Edwards/Matthias Miller/ John Resig / Diego Perini\n
-*  @param {Function}  func the function to be executed\n
-*  @param {Window}    scope the window that is listened to\n
-*/\n
-Xinha.addOnloadHandler = function (func, scope)\n
-{\n
- scope = scope ? scope : window;\n
-\n
- var init = function ()\n
- {\n
-   // quit if this function has already been called\n
-   if (arguments.callee.done) \n
-   {\n
-     return;\n
-   }\n
-   // flag this function so we don\'t do the same thing twice\n
-   arguments.callee.done = true;\n
-   // kill the timer\n
-   if (Xinha.onloadTimer)\n
-   {\n
-     clearInterval(Xinha.onloadTimer);\n
-   }\n
-\n
-   func();\n
- };\n
-  if (Xinha.is_ie)\n
-  {\n
-    // ensure firing before onload,\n
-    // maybe late but safe also for iframes\n
-    document.attachEvent("onreadystatechange", function(){\n
-      if ( document.readyState === "complete" ) {\n
-        document.detachEvent( "onreadystatechange", arguments.callee );\n
-        init();\n
-      }\n
-    });\n
-    if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){\n
-      if (arguments.callee.done) return;\n
-      try {\n
-        // If IE is used, use the trick by Diego Perini\n
-        // http://javascript.nwbox.com/IEContentLoaded/\n
-        document.documentElement.doScroll("left");\n
-      } catch( error ) {\n
-        setTimeout( arguments.callee, 0 );\n
-        return;\n
-      }\n
-      // and execute any waiting functions\n
-      init();\n
-    })();\n
-  }\n
- else if (/applewebkit|KHTML/i.test(navigator.userAgent) ) /* Safari/WebKit/KHTML */\n
- {\n
-   Xinha.onloadTimer = scope.setInterval(function()\n
-   {\n
-     if (/loaded|complete/.test(scope.document.readyState))\n
-     {\n
-       init(); // call the onload handler\n
-     }\n
-   }, 10);\n
- }\n
- else /* for Mozilla/Opera9 */\n
- {\n
-   scope.document.addEventListener("DOMContentLoaded", init, false);\n
-\n
- }\n
- Xinha._addEvent(scope, \'load\', init); // incase anything went wrong\n
-};\n
-\n
-/**\n
- * Adds a standard "DOM-0" event listener to an element.\n
- * The DOM-0 events are those applied directly as attributes to\n
- * an element - eg element.onclick = stuff;\n
- *\n
- * By using this function instead of simply overwriting any existing\n
- * DOM-0 event by the same name on the element it will trigger as well\n
- * as the existing ones.  Handlers are triggered one after the other\n
- * in the order they are added.\n
- *\n
- * Remember to return true/false from your handler, this will determine\n
- * whether subsequent handlers will be triggered (ie that the event will\n
- * continue or be canceled).\n
- *  \n
- *  @public\n
- *  @see Xinha#_addEvent\n
- *  @see Xinha#prependDom0Event\n
- *  @param {DomNode}  el the DOM element the event should be attached to \n
- *  @param {String}   ev the name of the event to listen for (without leading "on")\n
- *  @param {function} fn the function to be called when the event is fired\n
- */\n
-\n
-Xinha.addDom0Event = function(el, ev, fn)\n
-{\n
-  Xinha._prepareForDom0Events(el, ev);\n
-  el._xinha_dom0Events[ev].unshift(fn);\n
-};\n
-\n
-\n
-/** See addDom0Event, the difference is that handlers registered using\n
- *  prependDom0Event will be triggered before existing DOM-0 events of the\n
- *  same name on the same element.\n
- *  \n
- *  @public\n
- *  @see Xinha#_addEvent\n
- *  @see Xinha#addDom0Event\n
- *  @param {DomNode}  the DOM element the event should be attached to \n
- *  @param {String}   the name of the event to listen for (without leading "on")\n
- *  @param {function} the function to be called when the event is fired\n
- */\n
-\n
-Xinha.prependDom0Event = function(el, ev, fn)\n
-{\n
-  Xinha._prepareForDom0Events(el, ev);\n
-  el._xinha_dom0Events[ev].push(fn);\n
-};\n
-\n
-Xinha.getEvent = function(ev)\n
-{\n
-  return ev || window.event;\n
-};\n
-/**\n
- * Prepares an element to receive more than one DOM-0 event handler\n
- * when handlers are added via addDom0Event and prependDom0Event.\n
- *\n
- * @private\n
- */\n
-Xinha._prepareForDom0Events = function(el, ev)\n
-{\n
-  // Create a structure to hold our lists of event handlers\n
-  if ( typeof el._xinha_dom0Events == \'undefined\' )\n
-  {\n
-    el._xinha_dom0Events = {};\n
-    Xinha.freeLater(el, \'_xinha_dom0Events\');\n
-  }\n
-\n
-  // Create a list of handlers for this event type\n
-  if ( typeof el._xinha_dom0Events[ev] == \'undefined\' )\n
-  {\n
-    el._xinha_dom0Events[ev] = [ ];\n
-    if ( typeof el[\'on\'+ev] == \'function\' )\n
-    {\n
-      el._xinha_dom0Events[ev].push(el[\'on\'+ev]);\n
-    }\n
-\n
-    // Make the actual event handler, which runs through\n
-    // each of the handlers in the list and executes them\n
-    // in the correct context.\n
-    el[\'on\'+ev] = function(event)\n
-    {\n
-      var a = el._xinha_dom0Events[ev];\n
-      // call previous submit methods if they were there.\n
-      var allOK = true;\n
-      for ( var i = a.length; --i >= 0; )\n
-      {\n
-        // We want the handler to be a member of the form, not the array, so that "this" will work correctly\n
-        el._xinha_tempEventHandler = a[i];\n
-        if ( el._xinha_tempEventHandler(event) === false )\n
-        {\n
-          el._xinha_tempEventHandler = null;\n
-          allOK = false;\n
-          break;\n
-        }\n
-        el._xinha_tempEventHandler = null;\n
-      }\n
-      return allOK;\n
-    };\n
-\n
-    Xinha._eventFlushers.push([el, ev]);\n
-  }\n
-};\n
-\n
-Xinha.prototype.notifyOn = function(ev, fn)\n
-{\n
-  if ( typeof this._notifyListeners[ev] == \'undefined\' )\n
-  {\n
-    this._notifyListeners[ev] = [];\n
-    Xinha.freeLater(this, \'_notifyListeners\');\n
-  }\n
-  this._notifyListeners[ev].push(fn);\n
-};\n
-\n
-Xinha.prototype.notifyOf = function(ev, args)\n
-{\n
-  if ( this._notifyListeners[ev] )\n
-  {\n
-    for ( var i = 0; i < this._notifyListeners[ev].length; i++ )\n
-    {\n
-      this._notifyListeners[ev][i](ev, args);\n
-    }\n
-  }\n
-};\n
-\n
-/** List of tag names that are defined as block level elements in HTML\n
- *  \n
- *  @private\n
- *  @see Xinha#isBlockElement\n
- *  @type {String}\n
- */\n
-Xinha._blockTags = " body form textarea fieldset ul ol dl li div " +\n
-"p h1 h2 h3 h4 h5 h6 quote pre table thead " +\n
-"tbody tfoot tr td th iframe address blockquote title meta link style head ";\n
-\n
-/** Checks if one element is in the list of elements that are defined as block level elements in HTML\n
- *  \n
- *  @param {DomNode}  el The DOM element to check\n
- *  @returns {Boolean}\n
- */\n
-Xinha.isBlockElement = function(el)\n
-{\n
-  return el && el.nodeType == 1 && (Xinha._blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);\n
-};\n
-/** List of tag names that are allowed to contain a paragraph\n
- *  \n
- *  @private\n
- *  @see Xinha#isParaContainer\n
- *  @type {String}\n
- */\n
-Xinha._paraContainerTags = " body td th caption fieldset div ";\n
-/** Checks if one element is in the list of elements that are allowed to contain a paragraph in HTML\n
- *  \n
- *  @param {DomNode}  el The DOM element to check\n
- *  @returns {Boolean}\n
- */\n
-Xinha.isParaContainer = function(el)\n
-{\n
-  return el && el.nodeType == 1 && (Xinha._paraContainerTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);\n
-};\n
-\n
-\n
-/** These are all the tags for which the end tag is not optional or  forbidden, taken from the list at:\n
- *   http: www.w3.org/TR/REC-html40/index/elements.html\n
- *  \n
- *  @private\n
- *  @see Xinha#needsClosingTag\n
- *  @type String\n
- */\n
-Xinha._closingTags = " a abbr acronym address applet b bdo big blockquote button caption center cite code del dfn dir div dl em fieldset font form frameset h1 h2 h3 h4 h5 h6 i iframe ins kbd label legend map menu noframes noscript object ol optgroup pre q s samp script select small span strike strong style sub sup table textarea title tt u ul var ";\n
-\n
-/** Checks if one element is in the list of elements for which the end tag is not optional or  forbidden in HTML\n
- *  \n
- *  @param {DomNode}  el The DOM element to check\n
- *  @returns {Boolean}\n
- */\n
-Xinha.needsClosingTag = function(el)\n
-{\n
-  return el && el.nodeType == 1 && (Xinha._closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);\n
-};\n
-\n
-/** Performs HTML encoding of some given string (converts HTML special characters to entities)\n
- *  \n
- *  @param {String}  str The unencoded input\n
- *  @returns {String} The encoded output\n
- */\n
-Xinha.htmlEncode = function(str)\n
-{\n
-  if (!str)\n
-  {\n
-    return \'\';\n
-  }  if ( typeof str.replace == \'undefined\' )\n
-  {\n
-    str = str.toString();\n
-  }\n
-  // we don\'t need regexp for that, but.. so be it for now.\n
-  str = str.replace(/&/ig, "&amp;");\n
-  str = str.replace(/</ig, "&lt;");\n
-  str = str.replace(/>/ig, "&gt;");\n
-  str = str.replace(/\\xA0/g, "&nbsp;"); // Decimal 160, non-breaking-space\n
-  str = str.replace(/\\x22/g, "&quot;");\n
-  // \\x22 means \'"\' -- we use hex reprezentation so that we don\'t disturb\n
-  // JS compressors (well, at least mine fails.. ;)\n
-  return str;\n
-};\n
-\n
-/** Strips host-part of URL which is added by browsers to links relative to server root\n
- *  \n
- *  @param {String}  string \n
- *  @returns {String} \n
- */\n
-Xinha.prototype.stripBaseURL = function(string)\n
-{\n
-  if ( this.config.baseHref === null || !this.config.stripBaseHref )\n
-  {\n
-    return string;\n
-  }\n
-  var baseurl = this.config.baseHref.replace(/^(https?:\\/\\/[^\\/]+)(.*)$/, \'$1\');\n
-  var basere = new RegExp(baseurl);\n
-  return string.replace(basere, "");\n
-};\n
-\n
-if (typeof String.prototype.trim != \'function\')\n
-{\n
-  /** Removes whitespace from beginning and end of a string. Custom implementation for JS engines that don\'t support it natively\n
-   *  \n
-   *  @returns {String} \n
-   */\n
-  String.prototype.trim = function()\n
-  {\n
-    return this.replace(/^\\s+/, \'\').replace(/\\s+$/, \'\');\n
-  };\n
-}\n
-\n
-/** Creates a rgb-style rgb(r,g,b) color from a (24bit) number\n
- *  \n
- *  @param {Integer}\n
- *  @returns {String} rgb(r,g,b) color definition\n
- */\n
-Xinha._makeColor = function(v)\n
-{\n
-  if ( typeof v != "number" )\n
-  {\n
-    // already in rgb (hopefully); IE doesn\'t get here.\n
-    return v;\n
-  }\n
-  // IE sends number; convert to rgb.\n
-  var r = v & 0xFF;\n
-  var g = (v >> 8) & 0xFF;\n
-  var b = (v >> 16) & 0xFF;\n
-  return "rgb(" + r + "," + g + "," + b + ")";\n
-};\n
-\n
-/** Returns hexadecimal color representation from a number or a rgb-style color.\n
- *  \n
- *  @param {String|Integer} v rgb(r,g,b) or 24bit color definition\n
- *  @returns {String} #RRGGBB color definition\n
- */\n
-Xinha._colorToRgb = function(v)\n
-{\n
-  if ( !v )\n
-  {\n
-    return \'\';\n
-  }\n
-  var r,g,b;\n
-  // @todo: why declaring this function here ? This needs to be a public methode of the object Xinha._colorToRgb\n
-  // returns the hex representation of one byte (2 digits)\n
-  function hex(d)\n
-  {\n
-    return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);\n
-  }\n
-\n
-  if ( typeof v == "number" )\n
-  {\n
-    // we\'re talking to IE here\n
-    r = v & 0xFF;\n
-    g = (v >> 8) & 0xFF;\n
-    b = (v >> 16) & 0xFF;\n
-    return "#" + hex(r) + hex(g) + hex(b);\n
-  }\n
-\n
-  if ( v.substr(0, 3) == "rgb" )\n
-  {\n
-    // in rgb(...) form -- Mozilla\n
-    var re = /rgb\\s*\\(\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*\\)/;\n
-    if ( v.match(re) )\n
-    {\n
-      r = parseInt(RegExp.$1, 10);\n
-      g = parseInt(RegExp.$2, 10);\n
-      b = parseInt(RegExp.$3, 10);\n
-      return "#" + hex(r) + hex(g) + hex(b);\n
-    }\n
-    // doesn\'t match RE?!  maybe uses percentages or float numbers\n
-    // -- FIXME: not yet implemented.\n
-    return null;\n
-  }\n
-\n
-  if ( v.substr(0, 1) == "#" )\n
-  {\n
-    // already hex rgb (hopefully :D )\n
-    return v;\n
-  }\n
-\n
-  // if everything else fails ;)\n
-  return null;\n
-};\n
-\n
-/** Modal popup dialogs\n
- *  \n
- *  @param {String} url URL to the popup dialog\n
- *  @param {Function} action A function that receives one value; this function will get called \n
- *                    after the dialog is closed, with the return value of the dialog.\n
- *  @param {Mixed} init A variable that is passed to the popup window to pass arbitrary data\n
- */\n
-Xinha.prototype._popupDialog = function(url, action, init)\n
-{\n
-  Dialog(this.popupURL(url), action, init);\n
-};\n
-\n
-/** Creates a path in the form _editor_url + "plugins/" + plugin + "/img/" + file\n
- *  \n
- *  @deprecated\n
- *  @param {String} file Name of the image\n
- *  @param {String} plugin optional If omitted, simply _editor_url + file is returned \n
- *  @returns {String}\n
- */\n
-Xinha.prototype.imgURL = function(file, plugin)\n
-{\n
-  if ( typeof plugin == "undefined" )\n
-  {\n
-    return _editor_url + file;\n
-  }\n
-  else\n
-  {\n
-    return Xinha.getPluginDir(plugin) + "/img/" + file;\n
-  }\n
-};\n
-/** Creates a path\n
- *  \n
- *  @deprecated\n
- *  @param {String} file Name of the popup\n
- *  @returns {String}\n
- */\n
-Xinha.prototype.popupURL = function(file)\n
-{\n
-  var url = "";\n
-  if ( file.match(/^plugin:\\/\\/(.*?)\\/(.*)/) )\n
-  {\n
-    var plugin = RegExp.$1;\n
-    var popup = RegExp.$2;\n
-    if ( !/\\.(html?|php)$/.test(popup) )\n
-    {\n
-      popup += ".html";\n
-    }\n
-    url = Xinha.getPluginDir(plugin) + "/popups/" + popup;\n
-  }\n
-  else if ( file.match(/^\\/.*?/) || file.match(/^https?:\\/\\//))\n
-  {\n
-    url = file;\n
-  }\n
-  else\n
-  {\n
-    url = _editor_url + this.config.popupURL + file;\n
-  }\n
-  return url;\n
-};\n
-\n
-\n
-\n
-/** FIX: Internet Explorer returns an item having the _name_ equal to the given\n
- * id, even if it\'s not having any id.  This way it can return a different form\n
- * field, even if it\'s not a textarea.  This workarounds the problem by\n
- * specifically looking to search only elements having a certain tag name.\n
- * @param {String} tag The tag name to limit the return to\n
- * @param {String} id\n
- * @returns {DomNode}\n
- */\n
-Xinha.getElementById = function(tag, id)\n
-{\n
-  var el, i, objs = document.getElementsByTagName(tag);\n
-  for ( i = objs.length; --i >= 0 && (el = objs[i]); )\n
-  {\n
-    if ( el.id == id )\n
-    {\n
-      return el;\n
-    }\n
-  }\n
-  return null;\n
-};\n
-\n
-\n
-/** Use some CSS trickery to toggle borders on tables \n
- *\t@returns {Boolean} always true\n
- */\n
-\n
-Xinha.prototype._toggleBorders = function()\n
-{\n
-  var tables = this._doc.getElementsByTagName(\'TABLE\');\n
-  if ( tables.length !== 0 )\n
-  {\n
-   if ( !this.borders )\n
-   {    \n
-    this.borders = true;\n
-   }\n
-   else\n
-   {\n
-     this.borders = false;\n
-   }\n
-\n
-   for ( var i=0; i < tables.length; i++ )\n
-   {\n
-     if ( this.borders )\n
-     {\n
-        Xinha._addClass(tables[i], \'htmtableborders\');\n
-     }\n
-     else\n
-     {\n
-       Xinha._removeClass(tables[i], \'htmtableborders\');\n
-     }\n
-   }\n
-  }\n
-  return true;\n
-};\n
-/** Adds the styles for table borders to the iframe during generation\n
- *  \n
- *  @private\n
- *  @see Xinha#stripCoreCSS\n
- *  @param {String} html optional  \n
- *  @returns {String} html HTML with added styles or only styles if html omitted\n
- */\n
-Xinha.addCoreCSS = function(html)\n
-{\n
-    var coreCSS = "<style title=\\"XinhaInternalCSS\\" type=\\"text/css\\">" +\n
-    ".htmtableborders, .htmtableborders td, .htmtableborders th {border : 1px dashed lightgrey ! important;}\\n" +\n
-    "html, body { border: 0px; } \\n" +\n
-    "body { background-color: #ffffff; } \\n" +\n
-    "img, hr { cursor: default } \\n" +\n
-    "</style>\\n";\n
-    \n
-    if( html && /<head>/i.test(html))\n
-    {\n
-      return html.replace(/<head>/i, \'<head>\' + coreCSS);      \n
-    }\n
-    else if ( html)\n
-    {\n
-      return coreCSS + html;\n
-    }\n
-    else\n
-    {\n
-      return coreCSS;\n
-    }\n
-};\n
-/** Allows plugins to add a stylesheet for internal use to the edited document that won\'t appear in the HTML output\n
- *  \n
- *  @see Xinha#stripCoreCSS\n
- *  @param {String} stylesheet URL of the styleshett to be added\n
- */\n
-Xinha.prototype.addEditorStylesheet = function (stylesheet)\n
-{\n
-    var style = this._doc.createElement("link");\n
-    style.rel = \'stylesheet\';\n
-    style.type = \'text/css\';\n
-    style.title = \'XinhaInternalCSS\';\n
-    style.href = stylesheet;\n
-    this._doc.getElementsByTagName("HEAD")[0].appendChild(style);\n
-};\n
-/** Remove internal styles\n
- *  \n
- *  @private\n
- *  @see Xinha#addCoreCSS\n
- *  @param {String} html \n
- *  @returns {String} \n
- */\n
-Xinha.stripCoreCSS = function(html)\n
-{\n
-  return html.replace(/<style[^>]+title="XinhaInternalCSS"(.|\\n)*?<\\/style>/ig, \'\').replace(/<link[^>]+title="XinhaInternalCSS"(.|\\n)*?>/ig, \'\'); \n
-};\n
-/** Removes one CSS class (that is one of possible more parts \n
- *   separated by spaces) from a given element\n
- *  \n
- *  @see Xinha#_removeClasses\n
- *  @param {DomNode}  el The DOM element the class will be removed from\n
- *  @param {String}   className The class to be removed\n
- */\n
-Xinha._removeClass = function(el, className)\n
-{\n
-  if ( ! ( el && el.className ) )\n
-  {\n
-    return;\n
-  }\n
-  var cls = el.className.split(" ");\n
-  var ar = [];\n
-  for ( var i = cls.length; i > 0; )\n
-  {\n
-    if ( cls[--i] != className )\n
-    {\n
-      ar[ar.length] = cls[i];\n
-    }\n
-  }\n
-  el.className = ar.join(" ");\n
-};\n
-/** Adds one CSS class  to a given element (that is, it expands its className property by the given string,\n
- *  separated by a space)\n
- *  \n
- *  @see Xinha#addClasses\n
- *  @param {DomNode}  el The DOM element the class will be added to\n
- *  @param {String}   className The class to be added\n
- */\n
-Xinha._addClass = function(el, className)\n
-{\n
-  // remove the class first, if already there\n
-  Xinha._removeClass(el, className);\n
-  el.className += " " + className;\n
-};\n
-\n
-/** Adds CSS classes  to a given element (that is, it expands its className property by the given string,\n
- *  separated by a space, thereby checking that no class is doubly added)\n
- *  \n
- *  @see Xinha#addClass\n
- *  @param {DomNode}  el The DOM element the classes will be added to\n
- *  @param {String}   classes The classes to be added\n
- */\n
-Xinha.addClasses = function(el, classes)\n
-{\n
-  if ( el !== null )\n
-  {\n
-    var thiers = el.className.trim().split(\' \');\n
-    var ours   = classes.split(\' \');\n
-    for ( var x = 0; x < ours.length; x++ )\n
-    {\n
-      var exists = false;\n
-      for ( var i = 0; exists === false && i < thiers.length; i++ )\n
-      {\n
-        if ( thiers[i] == ours[x] )\n
-        {\n
-          exists = true;\n
-        }\n
-      }\n
-      if ( exists === false )\n
-      {\n
-        thiers[thiers.length] = ours[x];\n
-      }\n
-    }\n
-    el.className = thiers.join(\' \').trim();\n
-  }\n
-};\n
-\n
-/** Removes CSS classes (that is one or more of possibly several parts \n
- *   separated by spaces) from a given element\n
- *  \n
- *  @see Xinha#_removeClasses\n
- *  @param {DomNode}  el The DOM element the class will be removed from\n
- *  @param {String}   className The class to be removed\n
- */\n
-Xinha.removeClasses = function(el, classes)\n
-{\n
-  var existing    = el.className.trim().split();\n
-  var new_classes = [];\n
-  var remove      = classes.trim().split();\n
-\n
-  for ( var i = 0; i < existing.length; i++ )\n
-  {\n
-    var found = false;\n
-    for ( var x = 0; x < remove.length && !found; x++ )\n
-    {\n
-      if ( existing[i] == remove[x] )\n
-      {\n
-        found = true;\n
-      }\n
-    }\n
-    if ( !found )\n
-    {\n
-      new_classes[new_classes.length] = existing[i];\n
-    }\n
-  }\n
-  return new_classes.join(\' \');\n
-};\n
-\n
-/** Alias of Xinha._addClass()\n
- *  @see Xinha#_addClass\n
- */\n
-Xinha.addClass       = Xinha._addClass;\n
-/** Alias of Xinha.Xinha._removeClass()\n
- *  @see Xinha#_removeClass\n
- */\n
-Xinha.removeClass    = Xinha._removeClass;\n
-/** Alias of Xinha.addClasses()\n
- *  @see Xinha#addClasses\n
- */\n
-Xinha._addClasses    = Xinha.addClasses;\n
-/** Alias of Xinha.removeClasses()\n
- *  @see Xinha#removeClasses\n
- */\n
-Xinha._removeClasses = Xinha.removeClasses;\n
-\n
-/** Checks if one element has set the given className\n
- *  \n
- *  @param {DomNode}  el The DOM element to check\n
- *  @param {String}   className The class to be looked for\n
- *  @returns {Boolean}\n
- */\n
-Xinha._hasClass = function(el, className)\n
-{\n
-  if ( ! ( el && el.className ) )\n
-  {\n
-    return false;\n
-  }\n
-  var cls = el.className.split(" ");\n
-  for ( var i = cls.length; i > 0; )\n
-  {\n
-    if ( cls[--i] == className )\n
-    {\n
-      return true;\n
-    }\n
-  }\n
-  return false;\n
-};\n
-\n
-/**\n
- * Use XMLHTTPRequest to post some data back to the server and do something\n
- * with the response (asyncronously!), this is used by such things as the tidy\n
- * functions\n
- * @param {String} url The address for the HTTPRequest\n
- * @param {Object} data The data to be passed to the server like {name:"value"}\n
- * @param {Function} success A function that is called when an answer is\n
- *                           received from the server with the responseText as argument.\n
- * @param {Function} failure A function that is called when we fail to receive\n
- *                           an answer from the server. We pass it the request object.\n
- */\n
- \n
-/** mod_security (an apache module which scans incoming requests for potential hack attempts)\n
- *  has a rule which triggers when it gets an incoming Content-Type with a charset\n
- *  see ticket:1028 to try and work around this, if we get a failure in a postback\n
- *  then Xinha._postback_send_charset will be set to false and the request tried again (once)\n
- *  @type Boolean\n
- *  @private\n
- */ \n
-// \n
-// \n
-// \n
-Xinha._postback_send_charset = true;\n
-/** Use XMLHTTPRequest to send some some data to the server and do something\n
- *  with the getback (asyncronously!)\n
- * @param {String} url The address for the HTTPRequest\n
- * @param {Function} success A function that is called when an answer is\n
- *                           received from the server with the responseText as argument.\n
- * @param {Function} failure A function that is called when we fail to receive\n
- *                           an answer from the server. We pass it the request object.\n
- */\n
-Xinha._postback = function(url, data, success, failure)\n
-{\n
-  var req = null;\n
-  req = Xinha.getXMLHTTPRequestObject();\n
-\n
-  var content = \'\';\n
-  if (typeof data == \'string\')\n
-  {\n
-    content = data;\n
-  }\n
-  else if(typeof data == "object")\n
-  {\n
-    for ( var i in data )\n
-    {\n
-      content += (content.length ? \'&\' : \'\') + i + \'=\' + encodeURIComponent(data[i]);\n
-    }\n
-  }\n
-\n
-  function callBack()\n
-  {\n
-    if ( req.readyState == 4 )\n
-    {\n
-      if ( ((req.status / 100) == 2) || Xinha.isRunLocally && req.status === 0 )\n
-      {\n
-        if ( typeof success == \'function\' )\n
-        {\n
-          success(req.responseText, req);\n
-        }\n
-      }\n
-      else if(Xinha._postback_send_charset)\n
-      {        \n
-        Xinha._postback_send_charset = false;\n
-        Xinha._postback(url,data,success, failure);\n
-      }\n
-      else if (typeof failure == \'function\')\n
-      {\n
-        failure(req);\n
-      }\n
-      else\n
-      {\n
-        alert(\'An error has occurred: \' + req.statusText + \'\\nURL: \' + url);\n
-      }\n
-    }\n
-  }\n
-\n
-  req.onreadystatechange = callBack;\n
-\n
-  req.open(\'POST\', url, true);\n
-  req.setRequestHeader(\'Content-Type\', \'application/x-www-form-urlencoded\'+(Xinha._postback_send_charset ? \'; charset=UTF-8\' : \'\'));\n
-\n
-  req.send(content);\n
-};\n
-\n
-/** Use XMLHTTPRequest to receive some data from the server and do something\n
- * with the it (asyncronously!)\n
- * @param {String} url The address for the HTTPRequest\n
- * @param {Function} success A function that is called when an answer is\n
- *                           received from the server with the responseText as argument.\n
- * @param {Function} failure A function that is called when we fail to receive\n
- *                           an answer from the server. We pass it the request object.\n
- */\n
-Xinha._getback = function(url, success, failure)\n
-{\n
-  var req = null;\n
-  req = Xinha.getXMLHTTPRequestObject();\n
-\n
-  function callBack()\n
-  {\n
-    if ( req.readyState == 4 )\n
-    {\n
-      if ( ((req.status / 100) == 2) || Xinha.isRunLocally && req.status === 0 )\n
-      {\n
-        success(req.responseText, req);\n
-      }\n
-      else if (typeof failure == \'function\')\n
-      {\n
-        failure(req);\n
-      }\n
-      else\n
-      {\n
-        alert(\'An error has occurred: \' + req.statusText + \'\\nURL: \' + url);\n
-      }\n
-    }\n
-  }\n
-\n
-  req.onreadystatechange = callBack;\n
-  req.open(\'GET\', url, true);\n
-  req.send(null);\n
-};\n
-\n
-Xinha.ping = function(url, successHandler, failHandler)\n
-{\n
-  var req = null;\n
-  req = Xinha.getXMLHTTPRequestObject();\n
-\n
-  function callBack()\n
-  {\n
-    if ( req.readyState == 4 )\n
-    {\n
-      if ( ((req.status / 100) == 2) || Xinha.isRunLocally && req.status === 0 )\n
-      {\n
-        if (successHandler) \n
-        {\n
-          successHandler(req);\n
-        }\n
-      }\n
-      else\n
-      {\n
-        if (failHandler) \n
-        {\n
-          failHandler(req);\n
-        }\n
-      }\n
-    }\n
-  }\n
-\n
-  // Opera seems to have some problems mixing HEAD requests with GET requests.\n
-  // The GET is slower, so it\'s a net slowdown for Opera, but it keeps things\n
-  // from breaking.\n
-  var method = \'GET\';\n
-  req.onreadystatechange = callBack;\n
-  req.open(method, url, true);\n
-  req.send(null);\n
-};\n
-\n
-/** Use XMLHTTPRequest to receive some data from the server syncronously\n
- *  @param {String} url The address for the HTTPRequest\n
- */\n
-Xinha._geturlcontent = function(url, returnXML)\n
-{\n
-  var req = null;\n
-  req = Xinha.getXMLHTTPRequestObject();\n
-\n
-  // Synchronous!\n
-  req.open(\'GET\', url, false);\n
-  req.send(null);\n
-  if ( ((req.status / 100) == 2) || Xinha.isRunLocally && req.status === 0 )\n
-  {\n
-    return (returnXML) ? req.responseXML : req.responseText;\n
-  }\n
-  else\n
-  {\n
-    return \'\';\n
-  }\n
-};\n
-\n
-// Unless somebody already has, make a little function to debug things\n
-\n
-if (typeof dumpValues == \'undefined\') \n
-{\n
-  dumpValues = function(o)\n
-  {\n
-    var s = \'\';\n
-    for (var prop in o) \n
-    {\n
-      if (window.console && typeof window.console.log == \'function\') \n
-      {\n
-        if (typeof console.firebug != \'undefined\') \n
-        {\n
-          console.log(o);\n
-        }\n
-        else \n
-        {\n
-          console.log(prop + \' = \' + o[prop] + \'\\n\');\n
-        }\n
-      }\n
-      else\n
-      {\n
-        s += prop + \' = \' + o[prop] + \'\\n\';\n
-      }\n
-    }\n
-    if (s) \n
-    {\n
-      if (document.getElementById(\'errors\'))\n
-      {\n
-        document.getElementById(\'errors\').value += s;\n
-      }\n
-      else\n
-      {\n
-        var x = window.open("", "debugger");\n
-        x.document.write(\'<pre>\' + s + \'</pre>\');\n
-      }\n
-\n
-    }\n
-  };\n
-}\n
-if ( !Array.prototype.contains )\n
-{\n
-  /** Walks through an array and checks if the specified item exists in it\n
-  * @param {String} needle The string to search for\n
-  * @returns {Boolean} True if item found, false otherwise \n
-  */\n
-  Array.prototype.contains = function(needle)\n
-  {\n
-    var haystack = this;\n
-    for ( var i = 0; i < haystack.length; i++ )\n
-    {\n
-      if ( needle == haystack[i] )\n
-      {\n
-        return true;\n
-      }\n
-    }\n
-    return false;\n
-  };\n
-}\n
-\n
-if ( !Array.prototype.indexOf )\n
-{\n
-  /** Walks through an array and, if the specified item exists in it, returns the position\n
-  * @param {String} needle The string to search for\n
-  * @returns {Integer|null} Index position if item found, null otherwise \n
-  */\n
-  Array.prototype.indexOf = function(needle)\n
-  {\n
-    var haystack = this;\n
-    for ( var i = 0; i < haystack.length; i++ )\n
-    {\n
-      if ( needle == haystack[i] )\n
-      {\n
-        return i;\n
-      }\n
-    }\n
-    return null;\n
-  };\n
-}\n
-if ( !Array.prototype.append )\n
-{\n
-  /** Adds an item to an array\n
-   * @param {Mixed} a Item to add\n
-   * @returns {Array} The array including the newly added item\n
-   */\n
-  Array.prototype.append  = function(a)\n
-  {\n
-    for ( var i = 0; i < a.length; i++ )\n
-    {\n
-      this.push(a[i]);\n
-    }\n
-    return this;\n
-  };\n
-}\n
-/** Executes a provided function once per array element.\n
- *  Custom implementation for JS engines that don\'t support it natively\n
- * @source http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/ForEach\n
- * @param {Function} fn Function to execute for each element\n
- * @param {Object} thisObject Object to use as this when executing callback. \n
- */\n
-if (!Array.prototype.forEach)\n
-{\n
-  Array.prototype.forEach = function(fn /*, thisObject*/)\n
-  {\n
-    var len = this.length;\n
-    if (typeof fn != "function")\n
-    {\n
-      throw new TypeError();\n
-    }\n
-\n
-    var thisObject = arguments[1];\n
-    for (var i = 0; i < len; i++)\n
-    {\n
-      if (i in this)\n
-      {\n
-        fn.call(thisObject, this[i], i, this);\n
-      }\n
-    }\n
-  };\n
-}\n
-/** Returns all elements within a given class name inside an element\n
- * @type Array\n
- * @param {DomNode|document} el wherein to search\n
- * @param {Object} className\n
- */\n
-Xinha.getElementsByClassName = function(el,className)\n
-{\n
-  if (el.getElementsByClassName)\n
-  {\n
-    return Array.prototype.slice.call(el.getElementsByClassName(className));\n
-  }\n
-  else\n
-  {\n
-    var els = el.getElementsByTagName(\'*\');\n
-    var result = [];\n
-    var classNames;\n
-    for (var i=0;i<els.length;i++)\n
-    {\n
-      classNames = els[i].className.split(\' \');\n
-      if (classNames.contains(className)) \n
-      {\n
-        result.push(els[i]);\n
-      }\n
-    }\n
-    return result;\n
-  }\n
-};\n
-\n
-/** Returns true if all elements of <em>a2</em> are also contained in <em>a1</em> (at least I think this is what it does)\n
-* @param {Array} a1\n
-* @param {Array} a2\n
-* @returns {Boolean}\n
-*/\n
-Xinha.arrayContainsArray = function(a1, a2)\n
-{\n
-  var all_found = true;\n
-  for ( var x = 0; x < a2.length; x++ )\n
-  {\n
-    var found = false;\n
-    for ( var i = 0; i < a1.length; i++ )\n
-    {\n
-      if ( a1[i] == a2[x] )\n
-      {\n
-        found = true;\n
-        break;\n
-      }\n
-    }\n
-    if ( !found )\n
-    {\n
-      all_found = false;\n
-      break;\n
-    }\n
-  }\n
-  return all_found;\n
-};\n
-/** Walks through an array and applies a filter function to each item\n
-* @param {Array} a1 The array to filter\n
-* @param {Function} filterfn If this function returns true, the item is added to the new array\n
-* @returns {Array} Filtered array\n
-*/\n
-Xinha.arrayFilter = function(a1, filterfn)\n
-{\n
-  var new_a = [ ];\n
-  for ( var x = 0; x < a1.length; x++ )\n
-  {\n
-    if ( filterfn(a1[x]) )\n
-    {\n
-      new_a[new_a.length] = a1[x];\n
-    }\n
-  }\n
-  return new_a;\n
-};\n
-/** Converts a Collection object to an array \n
-* @param {Collection} collection The array to filter\n
-* @returns {Array} Array containing the item of collection\n
-*/\n
-Xinha.collectionToArray = function(collection)\n
-{\n
-  try\n
-  {\n
-    return collection.length ? Array.prototype.slice.call(collection) : []; //Collection to Array\n
-  }\n
-  catch(e)\n
-  {\n
-    // In certain implementations (*cough* IE), you can\'t call slice on a\n
-    // collection.  We\'ll fallback to using the simple, non-native iterative\n
-    // approach.\n
-  }\n
-\n
-  var array = [ ];\n
-  for ( var i = 0; i < collection.length; i++ )\n
-  {\n
-    array.push(collection.item(i));\n
-  }\n
-  return array;\n
-};\n
-\n
-/** Index for Xinha.uniq function \n
-*\t@private\n
-*/\n
-Xinha.uniq_count = 0;\n
-/** Returns a string that is unique on the page\n
-*\t@param {String} prefix This string is prefixed to a running number\n
-*   @returns {String}\n
-*/\n
-Xinha.uniq = function(prefix)\n
-{\n
-  return prefix + Xinha.uniq_count++;\n
-};\n
-\n
-// New language handling functions\n
-\n
-/** Load a language file.\n
- *  This function should not be used directly, Xinha._lc will use it when necessary.\n
- *  @private\n
- *  @param {String} context Case sensitive context name, eg \'Xinha\', \'TableOperations\', ...\n
- *  @returns {Object}\n
- */\n
-Xinha._loadlang = function(context,url)\n
-{\n
-  var lang;\n
-  \n
-  if ( typeof _editor_lcbackend == "string" )\n
-  {\n
-    //use backend\n
-    url = _editor_lcbackend;\n
-    url = url.replace(/%lang%/, _editor_lang);\n
-    url = url.replace(/%context%/, context);\n
-  }\n
-  else if (!url)\n
-  {\n
-    //use internal files\n
-    if ( context != \'Xinha\')\n
-    {\n
-      url = Xinha.getPluginDir(context)+"/lang/"+_editor_lang+".js";\n
-    }\n
-    else\n
-    {\n
-      Xinha.setLoadingMessage("Loading language");\n
-      url = _editor_url+"lang/"+_editor_lang+".js";\n
-    }\n
-  }\n
-\n
-  var langData = Xinha._geturlcontent(url);\n
-  if ( langData !== "" )\n
-  {\n
-    try\n
-    {\n
-      eval(\'lang = \' + langData);\n
-    }\n
-    catch(ex)\n
-    {\n
-      alert(\'Error reading Language-File (\'+url+\'):\\n\'+Error.toString());\n
-      lang = {};\n
-    }\n
-  }\n
-  else\n
-  {\n
-    lang = {};\n
-  }\n
-\n
-  return lang;\n
-};\n
-\n
-/** Return a localised string.\n
- * @param {String} string English language string. It can also contain variables in the form "Some text with $variable=replaced text$". \n
- *                  This replaces $variable in "Some text with $variable" with "replaced text"\n
- * @param {String} context   Case sensitive context name, eg \'Xinha\' (default), \'TableOperations\'...\n
- * @param {Object} replace   Replace $variables in String, eg {foo: \'replaceText\'} ($foo in string will be replaced by replaceText)\n
- */\n
-Xinha._lc = function(string, context, replace)\n
-{\n
-  var url,ret;\n
-  if (typeof context == \'object\' && context.url && context.context)\n
-  {\n
-    url = context.url + _editor_lang + ".js";\n
-    context = context.context;\n
-  }\n
-\n
-  var m = null;\n
-  if (typeof string == \'string\') \n
-  {\n
-    m = string.match(/\\$(.*?)=(.*?)\\$/g);\n
-  }\n
-  if (m) \n
-  {\n
-    if (!replace) \n
-    {\n
-      replace = {};\n
-    }\n
-    for (var i = 0;i<m.length;i++)\n
-    {\n
-      var n = m[i].match(/\\$(.*?)=(.*?)\\$/);\n
-      replace[n[1]] = n[2];\n
-      string = string.replace(n[0],\'$\'+n[1]);\n
-    }\n
-  }\n
-  if ( _editor_lang == "en" )\n
-  {\n
-    if ( typeof string == \'object\' && string.string )\n
-    {\n
-      ret = string.string;\n
-    }\n
-    else\n
-    {\n
-      ret = string;\n
-    }\n
-  }\n
-  else\n
-  {\n
-    if ( typeof Xinha._lc_catalog == \'undefined\' )\n
-    {\n
-      Xinha._lc_catalog = [ ];\n
-    }\n
-\n
-    if ( typeof context == \'undefined\' )\n
-    {\n
-      context = \'Xinha\';\n
-    }\n
-\n
-    if ( typeof Xinha._lc_catalog[context] == \'undefined\' )\n
-    {\n
-      Xinha._lc_catalog[context] = Xinha._loadlang(context,url);\n
-    }\n
-\n
-    var key;\n
-    if ( typeof string == \'object\' && string.key )\n
-    {\n
-      key = string.key;\n
-    }\n
-    else if ( typeof string == \'object\' && string.string )\n
-    {\n
-      key = string.string;\n
-    }\n
-    else\n
-    {\n
-      key = string;\n
-    }\n
-\n
-    if ( typeof Xinha._lc_catalog[context][key] == \'undefined\' )\n
-    {\n
-      if ( context==\'Xinha\' )\n
-      {\n
-        // Indicate it\'s untranslated\n
-        if ( typeof string == \'object\' && string.string )\n
-        {\n
-          ret = string.string;\n
-        }\n
-        else\n
-        {\n
-          ret = string;\n
-        }\n
-      }\n
-      else\n
-      {\n
-        //if string is not found and context is not Xinha try if it is in Xinha\n
-        return Xinha._lc(string, \'Xinha\', replace);\n
-      }\n
-    }\n
-    else\n
-    {\n
-      ret = Xinha._lc_catalog[context][key];\n
-    }\n
-  }\n
-\n
-  if ( typeof string == \'object\' && string.replace )\n
-  {\n
-    replace = string.replace;\n
-  }\n
-  if ( typeof replace != "undefined" )\n
-  {\n
-    for ( i in replace )\n
-    {\n
-      ret = ret.replace(\'$\'+i, replace[i]);\n
-    }\n
-  }\n
-\n
-  return ret;\n
-};\n
-/** Walks through the children of a given element and checks if any of the are visible (= not display:none)\n
- * @param {DomNode} el \n
- * @returns {Boolean} \n
- */\n
-Xinha.hasDisplayedChildren = function(el)\n
-{\n
-  var children = el.childNodes;\n
-  for ( var i = 0; i < children.length; i++ )\n
-  {\n
-    if ( children[i].tagName )\n
-    {\n
-      if ( children[i].style.display != \'none\' )\n
-      {\n
-        return true;\n
-      }\n
-    }\n
-  }\n
-  return false;\n
-};\n
-\n
-/** Load a javascript file by inserting it in the HEAD tag and eventually call a function when loaded\n
- *\n
- *  Note that this method cannot be abstracted into browser specific files\n
- *  because this method LOADS the browser specific files.  Hopefully it should work for most\n
- *  browsers as it is.\n
- *\n
- * @param {String} url               Source url of the file to load\n
- * @param {Object} callback optional Callback function to launch once ready \n
- * @param {Object} scope    optional Application scope for the callback function\n
- * @param {Object} bonus    optional Arbitrary object send as a param to the callback function\n
- */\n
-Xinha._loadback = function(url, callback, scope, bonus)\n
-{  \n
-  if ( document.getElementById(url) )\n
-  {\n
-    return true;\n
-  }\n
-  var t = !Xinha.is_ie ? "onload" : \'onreadystatechange\';\n
-  var s = document.createElement("script");\n
-  s.type = "text/javascript";\n
-  s.src = url;\n
-  s.id = url;\n
-  if ( callback )\n
-  {\n
-    s[t] = function()\n
-    {      \n
-      if (Xinha.is_ie && (!/loaded|complete/.test(window.event.srcElement.readyState)))\n
-      {\n
-        return;\n
-      }\n
-      \n
-      callback.call(scope ? scope : this, bonus);\n
-      s[t] = null;\n
-    };\n
-  }\n
-  document.getElementsByTagName("head")[0].appendChild(s);\n
-  return false;\n
-};\n
-\n
-/** Xinha\'s main loading function (see NewbieGuide)\n
- * @param {Array} editor_names\n
- * @param {Xinha.Config} default_config\n
- * @param {Array} plugin_names\n
- * @returns {Object} An object that contains references to all created editors indexed by the IDs of the textareas \n
- */\n
-Xinha.makeEditors = function(editor_names, default_config, plugin_names)\n
-{\n
-  if (!Xinha.isSupportedBrowser) \n
-  {\n
-    return;\n
-  }\n
-  \n
-  if ( typeof default_config == \'function\' )\n
-  {\n
-    default_config = default_config();\n
-  }\n
-\n
-  var editors = {};\n
-  var textarea;\n
-  for ( var x = 0; x < editor_names.length; x++ )\n
-  {\n
-    if ( typeof editor_names[x] == \'string\' ) // the regular case, an id of a textarea\n
-    {\n
-      textarea = Xinha.getElementById(\'textarea\', editor_names[x] );\n
-      if (!textarea) // the id may be specified for a textarea that is maybe on another page; we simply skip it and go on\n
-      {\n
-        editor_names[x] = null;\n
-        continue;\n
-      }\n
-    }\n
-\t // make it possible to pass a reference instead of an id, for example from  document.getElementsByTagName(\'textarea\')\n
-    else if ( typeof editor_names[x] == \'object\' && editor_names[x].tagName && editor_names[x].tagName.toLowerCase() == \'textarea\' )\n
-    {\n
-      textarea =  editor_names[x];\n
-      if ( !textarea.id ) // we\'d like to have the textarea have an id\n
-      {\n
-        textarea.id = \'xinha_id_\' + x;\n
-      } \n
-    }\n
-    var editor = new Xinha(textarea, Xinha.cloneObject(default_config));\n
-    editor.registerPlugins(plugin_names);\n
-    editors[textarea.id] = editor;\n
-  }\n
-  return editors;\n
-};\n
-/** Another main loading function (see NewbieGuide)\n
- * @param {Object} editors As returned by Xinha.makeEditors()\n
- */\n
-Xinha.startEditors = function(editors)\n
-{\n
-  if (!Xinha.isSupportedBrowser) \n
-  {\n
-    return;\n
-  }\n
-  \n
-  for ( var i in editors )\n
-  {\n
-    if ( editors[i].generate )\n
-    {\n
-      editors[i].generate();\n
-    }\n
-  }\n
-};\n
-/** Registers the loaded plugins with the editor\n
- * @private\n
- * @param {Array} plugin_names\n
- */\n
-Xinha.prototype.registerPlugins = function(plugin_names)\n
-{\n
-  if (!Xinha.isSupportedBrowser) \n
-  {\n
-    return;\n
-  }\n
-  \n
-  if ( plugin_names )\n
-  {\n
-    for ( var i = 0; i < plugin_names.length; i++ )\n
-    {\n
-      this.setLoadingMessage(Xinha._lc(\'Register plugin $plugin\', \'Xinha\', {\'plugin\': plugin_names[i]}));\n
-      this.registerPlugin(plugin_names[i]);\n
-    }\n
-  }\n
-};\n
-\n
-/** Utility function to base64_encode some arbitrary data, uses the builtin btoa() if it exists (Moz) \n
-*  @param {String} input\n
-*  @returns {String}\n
-*/\n
-Xinha.base64_encode = function(input)\n
-{\n
-  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";\n
-  var output = "";\n
-  var chr1, chr2, chr3;\n
-  var enc1, enc2, enc3, enc4;\n
-  var i = 0;\n
-\n
-  do\n
-  {\n
-    chr1 = input.charCodeAt(i++);\n
-    chr2 = input.charCodeAt(i++);\n
-    chr3 = input.charCodeAt(i++);\n
-\n
-    enc1 = chr1 >> 2;\n
-    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n
-    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n
-    enc4 = chr3 & 63;\n
-\n
-    if ( isNaN(chr2) )\n
-    {\n
-      enc3 = enc4 = 64;\n
-    }\n
-    else if ( isNaN(chr3) )\n
-    {\n
-      enc4 = 64;\n
-    }\n
-\n
-    output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);\n
-  } while ( i < input.length );\n
-\n
-  return output;\n
-};\n
-\n
-/** Utility function to base64_decode some arbitrary data, uses the builtin atob() if it exists (Moz)\n
- *  @param {String} input\n
- *  @returns {String}\n
- */\n
-Xinha.base64_decode = function(input)\n
-{\n
-  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";\n
-  var output = "";\n
-  var chr1, chr2, chr3;\n
-  var enc1, enc2, enc3, enc4;\n
-  var i = 0;\n
-\n
-  // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n
-  input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, "");\n
-\n
-  do\n
-  {\n
-    enc1 = keyStr.indexOf(input.charAt(i++));\n
-    enc2 = keyStr.indexOf(input.charAt(i++));\n
-    enc3 = keyStr.indexOf(input.charAt(i++));\n
-    enc4 = keyStr.indexOf(input.charAt(i++));\n
-\n
-    chr1 = (enc1 << 2) | (enc2 >> 4);\n
-    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n
-    chr3 = ((enc3 & 3) << 6) | enc4;\n
-\n
-    output = output + String.fromCharCode(chr1);\n
-\n
-    if ( enc3 != 64 )\n
-    {\n
-      output = output + String.fromCharCode(chr2);\n
-    }\n
-    if ( enc4 != 64 )\n
-    {\n
-      output = output + String.fromCharCode(chr3);\n
-    }\n
-  } while ( i < input.length );\n
-\n
-  return output;\n
-};\n
-/** Removes a node from the DOM\n
- *  @param {DomNode} el The element to be removed\n
- *  @returns {DomNode} The removed element\n
- */\n
-Xinha.removeFromParent = function(el)\n
-{\n
-  if ( !el.parentNode )\n
-  {\n
-    return;\n
-  }\n
-  var pN = el.parentNode;\n
-  return pN.removeChild(el);\n
-};\n
-/** Checks if some element has a parent node\n
- *  @param {DomNode} el \n
- *  @returns {Boolean}\n
- */\n
-Xinha.hasParentNode = function(el)\n
-{\n
-  if ( el.parentNode )\n
-  {\n
-    // When you remove an element from the parent in IE it makes the parent\n
-    // of the element a document fragment.  Moz doesn\'t.\n
-    if ( el.parentNode.nodeType == 11 )\n
-    {\n
-      return false;\n
-    }\n
-    return true;\n
-  }\n
-\n
-  return false;\n
-};\n
-\n
-/** Detect the size of visible area\n
- *  @param {Window} scope optional When calling from a popup window, pass its window object to get the values of the popup\n
- *  @returns {Object} Object with Integer properties x and y\n
- */\n
-Xinha.viewportSize = function(scope)\n
-{\n
-  scope = (scope) ? scope : window;\n
-  var x,y;\n
-  if (scope.innerHeight) // all except Explorer\n
-  {\n
-    x = scope.innerWidth;\n
-    y = scope.innerHeight;\n
-  }\n
-  else if (scope.document.documentElement && scope.document.documentElement.clientHeight)\n
-  // Explorer 6 Strict Mode\n
-  {\n
-    x = scope.document.documentElement.clientWidth;\n
-    y = scope.document.documentElement.clientHeight;\n
-  }\n
-  else if (scope.document.body) // other Explorers\n
-  {\n
-    x = scope.document.body.clientWidth;\n
-    y = scope.document.body.clientHeight;\n
-  }\n
-  return {\'x\':x,\'y\':y};\n
-};\n
-/** Detect the size of the whole document\n
- *  @param {Window} scope optional When calling from a popup window, pass its window object to get the values of the popup\n
- *  @returns {Object} Object with Integer properties x and y\n
- */\n
-Xinha.pageSize = function(scope)\n
-{\n
-  scope = (scope) ? scope : window;\n
-  var x,y;\n
- \n
-  var test1 = scope.document.body.scrollHeight; //IE Quirks\n
-  var test2 = scope.document.documentElement.scrollHeight; // IE Standard + Moz Here quirksmode.org errs! \n
-\n
-  if (test1 > test2) \n
-  {\n
-    x = scope.document.body.scrollWidth;\n
-    y = scope.document.body.scrollHeight;\n
-  }\n
-  else\n
-  {\n
-    x = scope.document.documentElement.scrollWidth;\n
-    y = scope.document.documentElement.scrollHeight;\n
-  }  \n
-  return {\'x\':x,\'y\':y};\n
-};\n
-/** Detect the current scroll position\n
- *  @param {Window} scope optional When calling from a popup window, pass its window object to get the values of the popup\n
- *  @returns {Object} Object with Integer properties x and y\n
- */\n
-Xinha.prototype.scrollPos = function(scope)\n
-{\n
-  scope = (scope) ? scope : window;\n
-  var x,y;\n
-  if (typeof scope.pageYOffset != \'undefined\') // all except Explorer\n
-  {\n
-    x = scope.pageXOffset;\n
-    y = scope.pageYOffset;\n
-  }\n
-  else if (scope.document.documentElement && typeof document.documentElement.scrollTop != \'undefined\')\n
-    // Explorer 6 Strict\n
-  {\n
-    x = scope.document.documentElement.scrollLeft;\n
-    y = scope.document.documentElement.scrollTop;\n
-  }\n
-  else if (scope.document.body) // all other Explorers\n
-  {\n
-    x = scope.document.body.scrollLeft;\n
-    y = scope.document.body.scrollTop;\n
-  }\n
-  return {\'x\':x,\'y\':y};\n
-};\n
-\n
-/** Calculate the top and left pixel position of an element in the DOM.\n
- *  @param  {DomNode} element HTML Element\n
- *  @returns {Object} Object with Integer properties top and left\n
- */\n
- \n
-Xinha.getElementTopLeft = function(element) \n
-{\n
-  var curleft = 0;\n
-  var curtop =  0;\n
-  if (element.offsetParent) \n
-  {\n
-    curleft = element.offsetLeft;\n
-    curtop = element.offsetTop;\n
-    while (element = element.offsetParent) \n
-    {\n
-      curleft += element.offsetLeft;\n
-      curtop += element.offsetTop;\n
-    }\n
-  }\n
-  return { top:curtop, left:curleft };\n
-};\n
-/** Find left pixel position of an element in the DOM.\n
- *  @param  {DomNode} element HTML Element\n
- *  @returns {Integer} \n
- */\n
-Xinha.findPosX = function(obj)\n
-{\n
-  var curleft = 0;\n
-  if ( obj.offsetParent )\n
-  {\n
-    return Xinha.getElementTopLeft(obj).left;\n
-  }\n
-  else if ( obj.x )\n
-  {\n
-    curleft += obj.x;\n
-  }\n
-  return curleft;\n
-};\n
-/** Find top pixel position of an element in the DOM.\n
- *  @param  {DomNode} element HTML Element\n
- *  @returns {Integer} \n
- */\n
-Xinha.findPosY = function(obj)\n
-{\n
-  var curtop = 0;\n
-  if ( obj.offsetParent )\n
-  {\n
-    return Xinha.getElementTopLeft(obj).top;    \n
-  }\n
-  else if ( obj.y )\n
-  {\n
-    curtop += obj.y;\n
-  }\n
-  return curtop;\n
-};\n
-\n
-Xinha.createLoadingMessages = function(xinha_editors)\n
-{\n
-  if ( Xinha.loadingMessages || !Xinha.isSupportedBrowser ) \n
-  {\n
-    return;\n
-  }\n
-  Xinha.loadingMessages = [];\n
-  \n
-  for (var i=0;i<xinha_editors.length;i++)\n
-  {\n
-    if (!document.getElementById(xinha_editors[i])) \n
-    {\n
-      continue;\n
-    }\n
-    Xinha.loadingMessages.push(Xinha.createLoadingMessage(Xinha.getElementById(\'textarea\', xinha_editors[i])));\n
-  }\n
-};\n
-\n
-Xinha.createLoadingMessage = function(textarea,text)\n
-{ \n
-  if ( document.getElementById("loading_" + textarea.id) || !Xinha.isSupportedBrowser)\n
-  {\n
-    return;\n
-  }\n
-  // Create and show the main loading message and the sub loading message for details of loading actions\n
-  // global element\n
-  var loading_message = document.createElement("div");\n
-  loading_message.id = "loading_" + textarea.id;\n
-  loading_message.className = "loading";\n
-  \n
-  loading_message.style.left = (Xinha.findPosX(textarea) + textarea.offsetWidth / 2) - 106 +  \'px\';\n
-  loading_message.style.top = (Xinha.findPosY(textarea) + textarea.offsetHeight / 2) - 50 +  \'px\';\n
-  // main static message\n
-  var loading_main = document.createElement("div");\n
-  loading_main.className = "loading_main";\n
-  loading_main.id = "loading_main_" + textarea.id;\n
-  loading_main.appendChild(document.createTextNode(Xinha._lc("Loading in progress. Please wait!")));\n
-  // sub dynamic message\n
-  var loading_sub = document.createElement("div");\n
-  loading_sub.className = "loading_sub";\n
-  loading_sub.id = "loading_sub_" + textarea.id;\n
-  text = text ? text : Xinha._lc("Loading Core");\n
-  loading_sub.appendChild(document.createTextNode(text));\n
-  loading_message.appendChild(loading_main);\n
-  loading_message.appendChild(loading_sub);\n
-  document.body.appendChild(loading_message);\n
-  \n
-  Xinha.freeLater(loading_message);\n
-  Xinha.freeLater(loading_main);\n
-  Xinha.freeLater(loading_sub);\n
-  \n
-  return loading_sub;\n
-};\n
-\n
-Xinha.prototype.setLoadingMessage = function(subMessage, mainMessage)\n
-{\n
-  if ( !document.getElementById("loading_sub_" + this._textArea.id) )\n
-  {\n
-    return;\n
-  }\n
-  document.getElementById("loading_main_" + this._textArea.id).innerHTML = mainMessage ? mainMessage : Xinha._lc("Loading in progress. Please wait!");\n
-  document.getElementById("loading_sub_" + this._textArea.id).innerHTML = subMessage;\n
-};\n
-\n
-Xinha.setLoadingMessage = function(string)\n
-{\n
-  if (!Xinha.loadingMessages) \n
-  {\n
-    return;\n
-  }\n
-  for ( var i = 0; i < Xinha.loadingMessages.length; i++ )\n
-  {\n
-    Xinha.loadingMessages[i].innerHTML = string;\n
-  }\n
-};\n
-\n
-Xinha.prototype.removeLoadingMessage = function()\n
-{\n
-  if (document.getElementById("loading_" + this._textArea.id) )\n
-  {\n
-   document.body.removeChild(document.getElementById("loading_" + this._textArea.id));\n
-  }\n
-};\n
-\n
-Xinha.removeLoadingMessages = function(xinha_editors)\n
-{\n
-  for (var i=0;i< xinha_editors.length;i++)\n
-  {\n
-     if (!document.getElementById(xinha_editors[i])) \n
-     {\n
-       continue;\n
-     }\n
-     var main = document.getElementById("loading_" + document.getElementById(xinha_editors[i]).id);\n
-     main.parentNode.removeChild(main);\n
-  }\n
-  Xinha.loadingMessages = null;\n
-};\n
-\n
-/** List of objects that have to be trated on page unload in order to work around the broken \n
- * Garbage Collector in IE\n
- * @private\n
- * @see Xinha#freeLater\n
- * @see Xinha#free\n
- * @see Xinha#collectGarbageForIE\n
- */\n
-Xinha.toFree = [];\n
-/** Adds objects to Xinha.toFree \n
- * @param {Object} object The object to free memory\n
- * @param (String} prop optional  The property to release\n
- * @private\n
- * @see Xinha#toFree\n
- * @see Xinha#free\n
- * @see Xinha#collectGarbageForIE\n
- */\n
-Xinha.freeLater = function(obj,prop)\n
-{\n
-  Xinha.toFree.push({o:obj,p:prop});\n
-};\n
-\n
-/** Release memory properties from object\n
- * @param {Object} object The object to free memory\n
- * @param (String} prop optional The property to release\n
- * @private\n
- * @see Xinha#collectGarbageForIE\n
- * @see Xinha#free\n
- */\n
-Xinha.free = function(obj, prop)\n
-{\n
-  if ( obj && !prop )\n
-  {\n
-    for ( var p in obj )\n
-    {\n
-      Xinha.free(obj, p);\n
-    }\n
-  }\n
-  else if ( obj )\n
-  {\n
-    if ( prop.indexOf(\'src\') == -1 ) // if src (also lowsrc, and maybe dynsrc ) is set to null, a file named "null" is requested from the server (see #1001)\n
-    {\n
-      try { obj[prop] = null; } catch(x) {}\n
-    }\n
-  }\n
-};\n
-\n
-/** IE\'s Garbage Collector is broken very badly.  We will do our best to \n
- *   do it\'s job for it, but we can\'t be perfect. Takes all objects from Xinha.free and releases sets the null\n
- * @private\n
- * @see Xinha#toFree\n
- * @see Xinha#free\n
- */\n
-\n
-Xinha.collectGarbageForIE = function() \n
-{  \n
-  Xinha.flushEvents();   \n
-  for ( var x = 0; x < Xinha.toFree.length; x++ )\n
-  {\n
-    Xinha.free(Xinha.toFree[x].o, Xinha.toFree[x].p);\n
-    Xinha.toFree[x].o = null;\n
-  }\n
-};\n
-\n
-\n
-// The following methods may be over-ridden or extended by the browser specific\n
-// javascript files.\n
-\n
-\n
-/** Insert a node at the current selection point. \n
- * @param {DomNode} toBeInserted\n
- */\n
-\n
-Xinha.prototype.insertNodeAtSelection = function(toBeInserted) { Xinha.notImplemented("insertNodeAtSelection"); };\n
-\n
-/** Get the parent element of the supplied or current selection. \n
- *  @param {Selection} sel optional selection as returned by getSelection\n
- *  @returns {DomNode}\n
- */\n
-  \n
-Xinha.prototype.getParentElement      = function(sel) { Xinha.notImplemented("getParentElement"); };\n
-\n
-/**\n
- * Returns the selected element, if any.  That is,\n
- * the element that you have last selected in the "path"\n
- * at the bottom of the editor, or a "control" (eg image)\n
- *\n
- * @returns {DomNode|null}\n
- */\n
- \n
-Xinha.prototype.activeElement         = function(sel) { Xinha.notImplemented("activeElement"); };\n
-\n
-/** \n
- * Determines if the given selection is empty (collapsed).\n
- * @param {Selection} sel Selection object as returned by getSelection\n
- * @returns {Boolean}\n
- */\n
- \n
-Xinha.prototype.selectionEmpty        = function(sel) { Xinha.notImplemented("selectionEmpty"); };\n
-/** \n
- * Returns a range object to be stored \n
- * and later restored with Xinha.prototype.restoreSelection()\n
- * @returns {Range}\n
- */\n
-\n
-Xinha.prototype.saveSelection = function() { Xinha.notImplemented("saveSelection"); };\n
-\n
-/** Restores a selection previously stored\n
- * @param {Range} savedSelection Range object as returned by Xinha.prototype.restoreSelection()\n
- */\n
-Xinha.prototype.restoreSelection = function(savedSelection)  { Xinha.notImplemented("restoreSelection"); };\n
-\n
-/**\n
- * Selects the contents of the given node.  If the node is a "control" type element, (image, form input, table)\n
- * the node itself is selected for manipulation.\n
- *\n
- * @param {DomNode} node \n
- * @param {Integer} pos  Set to a numeric position inside the node to collapse the cursor here if possible. \n
- */\n
-Xinha.prototype.selectNodeContents    = function(node,pos) { Xinha.notImplemented("selectNodeContents"); };\n
-\n
-/** Insert HTML at the current position, deleting the selection if any. \n
- *  \n
- *  @param {String} html\n
- */\n
- \n
-Xinha.prototype.insertHTML            = function(html) { Xinha.notImplemented("insertHTML"); };\n
-\n
-/** Get the HTML of the current selection.  HTML returned has not been passed through outwardHTML.\n
- *\n
- * @returns {String}\n
- */\n
-Xinha.prototype.getSelectedHTML       = function() { Xinha.notImplemented("getSelectedHTML"); };\n
-\n
-/** Get a Selection object of the current selection.  Note that selection objects are browser specific.\n
- *\n
- * @returns {Selection}\n
- */\n
- \n
-Xinha.prototype.getSelection          = function() { Xinha.notImplemented("getSelection"); };\n
-\n
-/** Create a Range object from the given selection.  Note that range objects are browser specific.\n
- *  @see Xinha#getSelection\n
- *  @param {Selection} sel Selection object \n
- *  @returns {Range}\n
- */\n
-Xinha.prototype.createRange           = function(sel) { Xinha.notImplemented("createRange"); };\n
-\n
-/** Determine if the given event object is a keydown/press event.\n
- *\n
- *  @param {Event} event \n
- *  @returns {Boolean}\n
- */\n
- \n
-Xinha.prototype.isKeyEvent            = function(event) { Xinha.notImplemented("isKeyEvent"); };\n
-\n
-/** Determines if the given key event object represents a combination of CTRL-<key>,\n
- *  which for Xinha is a shortcut.  Note that CTRL-ALT-<key> is not a shortcut.\n
- *\n
- *  @param    {Event} keyEvent\n
- *  @returns  {Boolean}\n
- */\n
- \n
-Xinha.prototype.isShortCut = function(keyEvent)\n
-{\n
-  if(keyEvent.ctrlKey && !keyEvent.altKey)\n
-  {\n
-    return true;\n
-  }\n
-  \n
-  return false;\n
-};\n
-\n
-/** Return the character (as a string) of a keyEvent  - ie, press the \'a\' key and\n
- *  this method will return \'a\', press SHIFT-a and it will return \'A\'.\n
- * \n
- *  @param   {Event} keyEvent\n
- *  @returns {String}\n
- */\n
-                                   \n
-Xinha.prototype.getKey = function(keyEvent) { Xinha.notImplemented("getKey"); };\n
-\n
-/** Return the HTML string of the given Element, including the Element.\n
- * \n
- * @param {DomNode} element HTML Element\n
- * @returns {String}\n
- */\n
- \n
-Xinha.getOuterHTML = function(element) { Xinha.notImplemented("getOuterHTML"); };\n
-\n
-/** Get a new XMLHTTPRequest Object ready to be used. \n
- *\n
- * @returns {XMLHTTPRequest}\n
- */\n
-\n
-Xinha.getXMLHTTPRequestObject = function() \n
-{\n
-  try\n
-  {    \n
-    if (typeof XMLHttpRequest != "undefined" && typeof XMLHttpRequest.constructor == \'function\' ) // Safari\'s XMLHttpRequest is typeof object\n
-    {\n
-  \t  return new XMLHttpRequest();\n
-    }\n
-  \telse if (typeof ActiveXObject == "function")\n
-  \t{\n
-  \t  return new ActiveXObject("Microsoft.XMLHTTP");\n
-  \t}\n
-  }\n
-  catch(e)\n
-  {\n
-    Xinha.notImplemented(\'getXMLHTTPRequestObject\');\n
-  }\n
-};\n
- \n
-// Compatability - all these names are deprecated and will be removed in a future version\n
-/** Alias of activeElement()\n
- * @see Xinha#activeElement\n
- * @deprecated\n
- * @returns {DomNode|null}\n
- */\n
-Xinha.prototype._activeElement  = function(sel) { return this.activeElement(sel); };\n
-/** Alias of selectionEmpty()\n
- * @see Xinha#selectionEmpty\n
- * @deprecated\n
- * @param {Selection} sel Selection object as returned by getSelection\n
- * @returns {Boolean}\n
- */\n
-Xinha.prototype._selectionEmpty = function(sel) { return this.selectionEmpty(sel); };\n
-/** Alias of getSelection()\n
- * @see Xinha#getSelection\n
- * @deprecated\n
- * @returns {Selection}\n
- */\n
-Xinha.prototype._getSelection   = function() { return this.getSelection(); };\n
-/** Alias of createRange()\n
- * @see Xinha#createRange\n
- * @deprecated\n
- * @param {Selection} sel Selection object\n
- * @returns {Range}\n
- */\n
-Xinha.prototype._createRange    = function(sel) { return this.createRange(sel); };\n
-HTMLArea = Xinha;\n
-\n
-//what is this for? Do we need it?\n
-Xinha.init();\n
-\n
-if ( Xinha.ie_version < 8 )\n
-{\n
-  Xinha.addDom0Event(window,\'unload\',Xinha.collectGarbageForIE);\n
-}\n
-/** Print some message to Firebug, Webkit, Opera, or IE8 console\n
- * \n
- * @param {String} text\n
- * @param {String} level one of \'warn\', \'info\', or empty \n
- */\n
-Xinha.debugMsg = function(text, level)\n
-{\n
-  if (typeof console != \'undefined\' && typeof console.log == \'function\') \n
-  {\n
-    if (level && level == \'warn\' && typeof console.warn == \'function\') \n
-    {\n
-      console.warn(text);\n
-    }\n
-    else \n
-      if (level && level == \'info\' && typeof console.info == \'function\') \n
-      {\n
-        console.info(text);\n
-      }\n
-      else \n
-      {\n
-        console.log(text);\n
-      }\n
-  }\n
-  else if (typeof opera != \'undefined\' && typeof opera.postError == \'function\') \n
-  {\n
-    opera.postError(text);\n
-  }\n
-};\n
-Xinha.notImplemented = function(methodName) \n
-{\n
-  throw new Error("Method Not Implemented", "Part of Xinha has tried to call the " + methodName + " method which has not been implemented.");\n
-};\n
-
+Xinha.version={Release:"Trunk",Head:"$HeadURL: http://svn.xinha.org/trunk/XinhaCore.js $".replace(/^[^:]*:\\s*(.*)\\s*\\$$/,"$1"),Date:"$LastChangedDate: 2010-05-12 09:40:06 +1200 (Wed, 12 May 2010) $".replace(/^[^:]*:\\s*([0-9\\-]*) ([0-9:]*) ([+0-9]*) \\((.*)\\)\\s*\\$/,"$4 $2 $3"),Revision:"$LastChangedRevision: 1263 $".replace(/^[^:]*:\\s*(.*)\\s*\\$$/,"$1"),RevisionBy:"$LastChangedBy: gogo $".replace(/^[^:]*:\\s*(.*)\\s*\\$$/,"$1")};Xinha._resolveRelativeUrl=function(d,c){if(c.match(/^([^:]+\\:)?\\/\\//)){return c}else{var a=d.split("/");if(a[a.length-1]===""){a.pop()}var e=c.split("/");if(e[0]=="."){e.shift()}while(e[0]==".."){a.pop();e.shift()}return a.join("/")+"/"+e.join("/")}};if(typeof _editor_url=="string"){_editor_url=_editor_url.replace(/\\x2f*$/,"/");if(!_editor_url.match(/^([^:]+\\:)?\\//)){(function(){var a=window.location.toString().replace(/\\?.*$/,"").split("/");a.pop();_editor_url=Xinha._resolveRelativeUrl(a.join("/"),_editor_url)})()}}else{alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in \'/xinha/\', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we\'ll probably fail.");_editor_url=""}if(typeof _editor_lang=="string"){_editor_lang=_editor_lang.toLowerCase()}else{_editor_lang="en"}if(typeof _editor_skin!=="string"){_editor_skin=""}if(typeof _editor_icons!=="string"){_editor_icons=""}var __xinhas=[];Xinha.agt=navigator.userAgent.toLowerCase();Xinha.is_ie=((Xinha.agt.indexOf("msie")!=-1)&&(Xinha.agt.indexOf("opera")==-1));Xinha.ie_version=parseFloat(Xinha.agt.substring(Xinha.agt.indexOf("msie")+5));Xinha.is_opera=(Xinha.agt.indexOf("opera")!=-1);if(Xinha.is_opera&&Xinha.agt.match(/opera[\\/ ]([0-9.]+)/)){Xinha.opera_version=parseFloat(RegExp.$1)}else{Xinha.opera_version=0}Xinha.is_khtml=(Xinha.agt.indexOf("khtml")!=-1);Xinha.is_webkit=(Xinha.agt.indexOf("applewebkit")!=-1);Xinha.webkit_version=parseInt(navigator.appVersion.replace(/.*?AppleWebKit\\/([\\d]).*?/,"$1"),10);Xinha.is_safari=(Xinha.agt.indexOf("safari")!=-1);Xinha.is_chrome=(Xinha.agt.indexOf("chrome")!=-1);Xinha.is_mac=(Xinha.agt.indexOf("mac")!=-1);Xinha.is_mac_ie=(Xinha.is_ie&&Xinha.is_mac);Xinha.is_win_ie=(Xinha.is_ie&&!Xinha.is_mac);Xinha.is_gecko=(navigator.product=="Gecko")||Xinha.is_opera;Xinha.is_real_gecko=(navigator.product=="Gecko"&&!Xinha.is_webkit);Xinha.is_ff2=Xinha.is_real_gecko&&parseInt(navigator.productSub.substr(0,10),10)<20071210;Xinha.isRunLocally=document.URL.toLowerCase().search(/^file:/)!=-1;Xinha.is_designMode=(typeof document.designMode!="undefined"&&!Xinha.is_ie);Xinha.checkSupportedBrowser=function(){return Xinha.is_real_gecko||(Xinha.is_opera&&Xinha.opera_version>=9.2)||Xinha.ie_version>=5.5||Xinha.webkit_version>=522};Xinha.isSupportedBrowser=Xinha.checkSupportedBrowser();if(Xinha.isRunLocally&&Xinha.isSupportedBrowser){alert(\'Xinha *must* be installed on a web server. Locally opened files (those that use the "file://" protocol) cannot properly function. Xinha will try to initialize but may not be correctly loaded.\')}function Xinha(d,c){if(!Xinha.isSupportedBrowser){return}if(!d){throw new Error("Tried to create Xinha without textarea specified.")}if(typeof c=="undefined"){this.config=new Xinha.Config()}else{this.config=c}if(typeof d!="object"){d=Xinha.getElementById("textarea",d)}this._textArea=d;this._textArea.spellcheck=false;Xinha.freeLater(this,"_textArea");this._initial_ta_size={w:d.style.width?d.style.width:(d.offsetWidth?(d.offsetWidth+"px"):(d.cols+"em")),h:d.style.height?d.style.height:(d.offsetHeight?(d.offsetHeight+"px"):(d.rows+"em"))};if(document.getElementById("loading_"+d.id)||this.config.showLoading){if(!document.getElementById("loading_"+d.id)){Xinha.createLoadingMessage(d)}this.setLoadingMessage(Xinha._lc("Constructing object"))}this._editMode="wysiwyg";this.plugins={};this._timerToolbar=null;this._timerUndo=null;this._undoQueue=[this.config.undoSteps];this._undoPos=-1;this._customUndo=true;this._mdoc=document;this.doctype="";this.__htmlarea_id_num=__xinhas.length;__xinhas[this.__htmlarea_id_num]=this;this._notifyListeners={};var b={right:{on:true,container:document.createElement("td"),panels:[]},left:{on:true,container:document.createElement("td"),panels:[]},top:{on:true,container:document.createElement("td"),panels:[]},bottom:{on:true,container:document.createElement("td"),panels:[]}};for(var a in b){if(!b[a].container){continue}b[a].div=b[a].container;b[a].container.className="panels panels_"+a;Xinha.freeLater(b[a],"container");Xinha.freeLater(b[a],"div")}this._panels=b;this._statusBar=null;this._statusBarTree=null;this._statusBarTextMode=null;this._statusBarItems=[];this._framework={};this._htmlArea=null;this._iframe=null;this._doc=null;this._toolBar=this._toolbar=null;this._toolbarObjects={};this.plugins.Events={name:"Events",developer:"The Xinha Core Developer Team",instance:c.Events}}Xinha.onload=function(){};Xinha.init=function(){Xinha.onload()};Xinha.RE_tagName=/(<\\/|<)\\s*([^ \\t\\n>]+)/ig;Xinha.RE_doctype=/(<!doctype((.|\\n)*?)>)\\n?/i;Xinha.RE_head=/<head>((.|\\n)*?)<\\/head>/i;Xinha.RE_body=/<body[^>]*>((.|\\n|\\r|\\t)*?)<\\/body>/i;Xinha.RE_Specials=/([\\/\\^$*+?.()|{}\\[\\]])/g;Xinha.escapeStringForRegExp=function(a){return a.replace(Xinha.RE_Specials,"\\\\$1")};Xinha.RE_email=/^[_a-z\\d\\-\\.]{3,}@[_a-z\\d\\-]{2,}(\\.[_a-z\\d\\-]{2,})+$/i;Xinha.RE_url=/(https?:\\/\\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_\\-]{2,}(\\.[a-z0-9_\\-]{2,}){2,}(:[0-9]+)?(\\/\\S+)*)/i;Xinha.Config=function(){this.version=Xinha.version.Revision;this.width="auto";this.height="auto";this.sizeIncludesBars=true;this.sizeIncludesPanels=true;this.panel_dimensions={left:"200px",right:"200px",top:"100px",bottom:"100px"};this.iframeWidth=null;this.statusBar=true;this.htmlareaPaste=false;this.mozParaHandler="best";this.getHtmlMethod="DOMwalk";this.undoSteps=20;this.undoTimeout=500;this.changeJustifyWithDirection=false;this.fullPage=false;this.pageStyle="";this.pageStyleSheets=[];this.baseHref=null;this.expandRelativeUrl=true;this.stripBaseHref=true;this.stripSelfNamedAnchors=true;this.only7BitPrintablesInURLs=true;this.sevenBitClean=false;this.specialReplacements={};this.inwardHtml=function(c){return c};this.outwardHtml=function(c){return c};this.autofocus=false;this.killWordOnPaste=true;this.makeLinkShowsTarget=true;this.charSet=(typeof document.characterSet!="undefined")?document.characterSet:document.charset;this.browserQuirksMode=null;this.imgURL="images/";this.popupURL="popups/";this.htmlRemoveTags=null;this.flowToolbars=true;this.toolbarAlign="left";this.showFontStylesInToolbar=false;this.showLoading=false;this.stripScripts=true;this.convertUrlsToLinks=true;this.colorPickerCellSize="6px";this.colorPickerGranularity=18;this.colorPickerPosition="bottom,right";this.colorPickerWebSafe=false;this.colorPickerSaveColors=20;this.fullScreen=false;this.fullScreenMargins=[0,0,0,0];this.fullScreenSizeDownMethod="initSize";this.toolbar=[["popupeditor"],["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"],["separator","forecolor","hilitecolor","textindicator"],["separator","subscript","superscript"],["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],["separator","insertorderedlist","insertunorderedlist","outdent","indent"],["separator","inserthorizontalrule","createlink","insertimage","inserttable"],["linebreak","separator","undo","redo","selectall","print"],(Xinha.is_gecko?[]:["cut","copy","paste","overwrite","saveas"]),["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright","righttoleft"],["separator","htmlmode","showhelp","about"]];this.fontname={"&#8212; font &#8212;":"",Arial:"arial,helvetica,sans-serif","Courier New":"courier new,courier,monospace",Georgia:"georgia,times new roman,times,serif",Tahoma:"tahoma,arial,helvetica,sans-serif","Times New Roman":"times new roman,times,serif",Verdana:"verdana,arial,helvetica,sans-serif",impact:"impact",WingDings:"wingdings"};this.fontsize={"&#8212; size &#8212;":"","1 (8 pt)":"1","2 (10 pt)":"2","3 (12 pt)":"3","4 (14 pt)":"4","5 (18 pt)":"5","6 (24 pt)":"6","7 (36 pt)":"7"};this.formatblock={"&#8212; format &#8212;":"","Heading 1":"h1","Heading 2":"h2","Heading 3":"h3","Heading 4":"h4","Heading 5":"h5","Heading 6":"h6",Normal:"p",Address:"address",Formatted:"pre"};this.dialogOptions={centered:true,greyout:true,closeOnEscape:true};this.Events={};this.customSelects={};this.debug=false;this.URIs={blank:_editor_url+"popups/blank.html",link:_editor_url+"modules/CreateLink/link.html",insert_image:_editor_url+"modules/InsertImage/insert_image.html",insert_table:_editor_url+"modules/InsertTable/insert_table.html",select_color:_editor_url+"popups/select_color.html",help:_editor_url+"popups/editor_help.html"};this.btnList={bold:["Bold",Xinha._lc({key:"button_bold",string:["ed_buttons_main.png",3,2]},"Xinha"),false,function(c){c.execCommand("bold")}],italic:["Italic",Xinha._lc({key:"button_italic",string:["ed_buttons_main.png",2,2]},"Xinha"),false,function(c){c.execCommand("italic")}],underline:["Underline",Xinha._lc({key:"button_underline",string:["ed_buttons_main.png",2,0]},"Xinha"),false,function(c){c.execCommand("underline")}],strikethrough:["Strikethrough",Xinha._lc({key:"button_strikethrough",string:["ed_buttons_main.png",3,0]},"Xinha"),false,function(c){c.execCommand("strikethrough")}],subscript:["Subscript",Xinha._lc({key:"button_subscript",string:["ed_buttons_main.png",3,1]},"Xinha"),false,function(c){c.execCommand("subscript")}],superscript:["Superscript",Xinha._lc({key:"button_superscript",string:["ed_buttons_main.png",2,1]},"Xinha"),false,function(c){c.execCommand("superscript")}],justifyleft:["Justify Left",["ed_buttons_main.png",0,0],false,function(c){c.execCommand("justifyleft")}],justifycenter:["Justify Center",["ed_buttons_main.png",1,1],false,function(c){c.execCommand("justifycenter")}],justifyright:["Justify Right",["ed_buttons_main.png",1,0],false,function(c){c.execCommand("justifyright")}],justifyfull:["Justify Full",["ed_buttons_main.png",0,1],false,function(c){c.execCommand("justifyfull")}],orderedlist:["Ordered List",["ed_buttons_main.png",0,3],false,function(c){c.execCommand("insertorderedlist")}],unorderedlist:["Bulleted List",["ed_buttons_main.png",1,3],false,function(c){c.execCommand("insertunorderedlist")}],insertorderedlist:["Ordered List",["ed_buttons_main.png",0,3],false,function(c){c.execCommand("insertorderedlist")}],insertunorderedlist:["Bulleted List",["ed_buttons_main.png",1,3],false,function(c){c.execCommand("insertunorderedlist")}],outdent:["Decrease Indent",["ed_buttons_main.png",1,2],false,function(c){c.execCommand("outdent")}],indent:["Increase Indent",["ed_buttons_main.png",0,2],false,function(c){c.execCommand("indent")}],forecolor:["Font Color",["ed_buttons_main.png",3,3],false,function(c){c.execCommand("forecolor")}],hilitecolor:["Background Color",["ed_buttons_main.png",2,3],false,function(c){c.execCommand("hilitecolor")}],undo:["Undoes your last action",["ed_buttons_main.png",4,2],false,function(c){c.execCommand("undo")}],redo:["Redoes your last action",["ed_buttons_main.png",5,2],false,function(c){c.execCommand("redo")}],cut:["Cut selection",["ed_buttons_main.png",5,0],false,function(d,c){d.execCommand(c)}],copy:["Copy selection",["ed_buttons_main.png",4,0],false,function(d,c){d.execCommand(c)}],paste:["Paste from clipboard",["ed_buttons_main.png",4,1],false,function(d,c){d.execCommand(c)}],selectall:["Select all",["ed_buttons_main.png",3,5],false,function(c){c.execCommand("selectall")}],inserthorizontalrule:["Horizontal Rule",["ed_buttons_main.png",6,0],false,function(c){c.execCommand("inserthorizontalrule")}],createlink:["Insert Web Link",["ed_buttons_main.png",6,1],false,function(c){c._createLink()}],insertimage:["Insert/Modify Image",["ed_buttons_main.png",6,3],false,function(c){c.execCommand("insertimage")}],inserttable:["Insert Table",["ed_buttons_main.png",6,2],false,function(c){c.execCommand("inserttable")}],htmlmode:["Toggle HTML Source",["ed_buttons_main.png",7,0],true,function(c){c.execCommand("htmlmode")}],toggleborders:["Toggle Borders",["ed_buttons_main.png",7,2],false,function(c){c._toggleBorders()}],print:["Print document",["ed_buttons_main.png",8,1],false,function(c){if(Xinha.is_gecko){c._iframe.contentWindow.print()}else{c.focusEditor();print()}}],saveas:["Save as",["ed_buttons_main.png",9,1],false,function(c){c.execCommand("saveas",false,"noname.htm")}],about:["About this editor",["ed_buttons_main.png",8,2],true,function(c){c.getPluginInstance("AboutBox").show()}],showhelp:["Help using editor",["ed_buttons_main.png",9,2],true,function(c){c.execCommand("showhelp")}],splitblock:["Split Block","ed_splitblock.gif",false,function(c){c._splitBlock()}],lefttoright:["Direction left to right",["ed_buttons_main.png",0,2],false,function(c){c.execCommand("lefttoright")}],righttoleft:["Direction right to left",["ed_buttons_main.png",1,2],false,function(c){c.execCommand("righttoleft")}],overwrite:["Insert/Overwrite","ed_overwrite.gif",false,function(c){c.execCommand("overwrite")}],wordclean:["MS Word Cleaner",["ed_buttons_main.png",5,3],false,function(c){c._wordClean()}],clearfonts:["Clear Inline Font Specifications",["ed_buttons_main.png",5,4],true,function(c){c._clearFonts()}],removeformat:["Remove formatting",["ed_buttons_main.png",4,4],false,function(c){c.execCommand("removeformat")}],killword:["Clear MSOffice tags",["ed_buttons_main.png",4,3],false,function(c){c.execCommand("killword")}]};this.dblclickList={a:[function(c,d){c._createLink(d)}],img:[function(c,d){c._insertImage(d)}]};this.iconList={dialogCaption:_editor_url+"images/xinha-small-icon.gif",wysiwygmode:[_editor_url+"images/ed_buttons_main.png",7,1]};for(var b in this.btnList){var a=this.btnList[b];if(typeof a!="object"){continue}if(typeof a[1]!="string"){a[1][0]=_editor_url+this.imgURL+a[1][0]}else{a[1]=_editor_url+this.imgURL+a[1]}a[0]=Xinha._lc(a[0])}};Xinha.Config.prototype.registerIcon=function(b,a){this.iconList[b]=a};Xinha.Config.prototype.registerButton=function(f,b,e,d,a,c){if(typeof f=="string"){this.btnList[f]=[b,e,d,a,c]}else{if(typeof f=="object"){this.btnList[f.id]=[f.tooltip,f.image,f.textMode,f.action,f.context]}else{alert("ERROR [Xinha.Config::registerButton]:\\ninvalid arguments");return false}}};Xinha.prototype.registerPanel=function(c,b){if(!c){c="right"}this.setLoadingMessage("Register "+c+" panel ");var a=this.addPanel(c);if(b){b.drawPanelIn(a)}};Xinha.Config.prototype.registerDropdown=function(a){this.customSelects[a.id]=a};Xinha.Config.prototype.hideSomeButtons=function(f){var c=this.toolbar;for(var e=c.length;--e>=0;){var b=c[e];for(var d=b.length;--d>=0;){if(f.indexOf(" "+b[d]+" ")>=0){var a=1;if(/separator|space/.test(b[d+1])){a=2}b.splice(d,a)}}}};Xinha.Config.prototype.addToolbarElement=function(d,k,m){var s=this.toolbar;var q,l,h,f,c;var p=false;var b=false;var n=0;var g=0;var e=0;var r=false;var t=false;if((d&&typeof d=="object")&&(d.constructor==Array)){p=true}if((k&&typeof k=="object")&&(k.constructor==Array)){b=true;n=k.length}if(p){for(l=0;l<d.length;++l){if((d[l]!="separator")&&(d[l].indexOf("T[")!==0)){c=d[l]}}}else{c=d}for(l=0;l<s.length;++l){q=s[l];for(h=0;h<q.length;++h){if(q[h]==c){return}}}for(l=0;!t&&l<s.length;++l){q=s[l];for(h=0;!t&&h<q.length;++h){if(b){for(f=0;f<n;++f){if(q[h]==k[f]){if(f===0){t=true;h--;break}else{e=l;g=h;n=f}}}}else{if(q[h]==k){t=true;break}}}}if(!t&&b){if(k.length!=n){h=g;q=s[e];t=true}}if(t){if(m===0){if(p){q[h]=d[d.length-1];for(l=d.length-1;--l>=0;){q.splice(h,0,d[l])}}else{q[h]=d}}else{if(m<0){h=h+m+1}else{if(m>0){h=h+m}}if(p){for(l=d.length;--l>=0;){q.splice(h,0,d[l])}}else{q.splice(h,0,d)}}}else{s[0].splice(0,0,"separator");if(p){for(l=d.length;--l>=0;){s[0].splice(0,0,d[l])}}else{s[0].splice(0,0,d)}}};Xinha.Config.prototype.removeToolbarElement=Xinha.Config.prototype.hideSomeButtons;Xinha.replaceAll=function(b){var c=document.getElementsByTagName("textarea");for(var a=c.length;a>0;new Xinha(c[--a],b).generate()){}};Xinha.replace=function(c,b){var a=Xinha.getElementById("textarea",c);return a?new Xinha(a,b).generate():null};Xinha.prototype._createToolbar=function(){this.setLoadingMessage(Xinha._lc("Create Toolbar"));var b=this;var a=document.createElement("div");this._toolBar=this._toolbar=a;a.className="toolbar";a.align=this.config.toolbarAlign;Xinha.freeLater(this,"_toolBar");Xinha.freeLater(this,"_toolbar");var c=null;var e={};this._toolbarObjects=e;this._createToolbar1(b,a,e);function d(g){if(g.tagName){g.unselectable="on"}if(g.childNodes){for(var f=0;f<g.childNodes.length;f++){if(g.tagName){d(g.childNodes(f))}}}}if(Xinha.is_ie){d(a)}this._htmlArea.appendChild(a);return a};Xinha.prototype._setConfig=function(a){this.config=a};Xinha.prototype._rebuildToolbar=function(){this._createToolbar1(this,this._toolbar,this._toolbarObjects);if(Xinha._currentlyActiveEditor){if(Xinha._currentlyActiveEditor==this){this.activateEditor()}}else{this.disableToolbar()}};Xinha._createToolbarBreakingElement=function(){var a=document.createElement("div");a.style.height="1px";a.style.width="1px";a.style.lineHeight="1px";a.style.fontSize="1px";a.style.clear="both";return a};Xinha.prototype._createToolbar1=function(d,s,p){while(s.lastChild){s.removeChild(s.lastChild)}var l;if(d.config.flowToolbars){s.appendChild(Xinha._createToolbarBreakingElement())}function n(){if(typeof l!="undefined"&&l.childNodes.length===0){return}var i=document.createElement("table");i.border="0px";i.cellSpacing="0px";i.cellPadding="0px";if(d.config.flowToolbars){if(Xinha.is_ie){i.style.styleFloat="left"}else{i.style.cssFloat="left"}}s.appendChild(i);var j=document.createElement("tbody");i.appendChild(j);l=document.createElement("tr");j.appendChild(l);i.className="toolbarRow"}n();function m(u,i){var j=this[u];var t=this.element;if(j!=i){switch(u){case"enabled":if(i){Xinha._removeClass(t,"buttonDisabled");t.disabled=false}else{Xinha._addClass(t,"buttonDisabled");t.disabled=true}break;case"active":if(i){Xinha._addClass(t,"buttonPressed")}else{Xinha._removeClass(t,"buttonPressed")}break}this[u]=i}}function c(x){var A=null;var t=null;var u=null;var C=d.config.customSelects;var j=null;var z="";switch(x){case"fontsize":case"fontname":case"formatblock":A=d.config[x];u=x;break;default:u=x;var B=C[u];if(typeof B!="undefined"){A=B.options;j=B.context;if(typeof B.tooltip!="undefined"){z=B.tooltip}}else{alert("ERROR [createSelect]:\\nCan\'t find the requested dropdown definition")}break}if(A){t=document.createElement("select");t.title=z;t.style.width="auto";t.name=x;var w={name:x,element:t,enabled:true,text:false,cmd:u,state:m,context:j};Xinha.freeLater(w);p[x]=w;for(var v in A){if(typeof A[v]!="string"){continue}var y=document.createElement("option");y.innerHTML=Xinha._lc(v);y.value=A[v];if(x=="fontname"&&d.config.showFontStylesInToolbar){y.style.fontFamily=A[v]}t.appendChild(y)}Xinha._addEvent(t,"change",function(){d._comboSelected(t,x)})}return t}function q(i){var u,t,w=null;switch(i){case"separator":if(d.config.flowToolbars){n()}u=document.createElement("div");u.className="separator";break;case"space":u=document.createElement("div");u.className="space";break;case"linebreak":n();return false;case"textindicator":u=document.createElement("div");u.appendChild(document.createTextNode("A"));u.className="indicator";u.title=Xinha._lc("Current style");w={name:i,element:u,enabled:true,active:false,text:false,cmd:"textindicator",state:m};Xinha.freeLater(w);p[i]=w;break;default:t=d.config.btnList[i]}if(!u&&t){u=document.createElement("a");u.style.display="block";u.href="javascript:void(0)";u.style.textDecoration="none";u.title=t[0];u.className="button";u.style.direction="ltr";w={name:i,element:u,enabled:true,active:false,text:t[2],cmd:t[3],state:m,context:t[4]||null};Xinha.freeLater(u);Xinha.freeLater(w);p[i]=w;u.ondrag=function(){return false};Xinha._addEvent(u,"mouseout",function(x){if(w.enabled){Xinha._removeClass(u,"buttonActive");if(w.active){Xinha._addClass(u,"buttonPressed")}}});Xinha._addEvent(u,"mousedown",function(x){if(w.enabled){Xinha._addClass(u,"buttonActive");Xinha._removeClass(u,"buttonPressed");Xinha._stopEvent(Xinha.is_ie?window.event:x)}});Xinha._addEvent(u,"click",function(x){x=x||window.event;d.btnClickEvent={clientX:x.clientX,clientY:x.clientY};if(w.enabled){Xinha._removeClass(u,"buttonActive");if(Xinha.is_gecko){d.activateEditor()}w.cmd(d,w.name,w,x);Xinha._stopEvent(x)}});var v=Xinha.makeBtnImg(t[1]);var j=v.firstChild;Xinha.freeLater(v);Xinha.freeLater(j);u.appendChild(v);w.imgel=j;w.swapImage=function(x){if(typeof x!="string"){j.src=x[0];j.style.position="relative";j.style.top=x[2]?("-"+(18*(x[2]+1))+"px"):"-18px";j.style.left=x[1]?("-"+(18*(x[1]+1))+"px"):"-18px"}else{w.imgel.src=x;j.style.top="0px";j.style.left="0px"}}}else{if(!u){u=c(i)}}return u}var k=true;for(var h=0;h<this.config.toolbar.length;++h){if(!k){}else{k=false}if(this.config.toolbar[h]===null){this.config.toolbar[h]=["separator"]}var r=this.config.toolbar[h];for(var g=0;g<r.length;++g){var b=r[g];var a;if(/^([IT])\\[(.*?)\\]/.test(b)){var f=RegExp.$1=="I";var o=RegExp.$2;if(f){o=Xinha._lc(o)}a=document.createElement("td");l.appendChild(a);a.className="label";a.innerHTML=o}else{if(typeof b!="function"){var e=q(b);if(e){a=document.createElement("td");a.className="toolbarElement";l.appendChild(a);a.appendChild(e)}else{if(e===null){alert("FIXME: Unknown toolbar item: "+b)}}}}}}if(d.config.flowToolbars){s.appendChild(Xinha._createToolbarBreakingElement())}return s};Xinha.makeBtnImg=function(b,d){if(!d){d=document}if(!d._xinhaImgCache){d._xinhaImgCache={};Xinha.freeLater(d._xinhaImgCache)}var c=null;if(Xinha.is_ie&&((!d.compatMode)||(d.compatMode&&d.compatMode=="BackCompat"))){c=d.createElement("span")}else{c=d.createElement("div");c.style.position="relative"}c.style.overflow="hidden";c.style.width="18px";c.style.height="18px";c.className="buttonImageContainer";var a=null;if(typeof b=="string"){if(d._xinhaImgCache[b]){a=d._xinhaImgCache[b].cloneNode()}else{if(Xinha.ie_version<7&&/\\.png$/.test(b[0])){a=d.createElement("span");a.style.display="block";a.style.width="18px";a.style.height="18px";a.style.filter=\'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="\'+b+\'")\';a.unselectable="on"}else{a=d.createElement("img");a.src=b}}}else{if(d._xinhaImgCache[b[0]]){a=d._xinhaImgCache[b[0]].cloneNode()}else{if(Xinha.ie_version<7&&/\\.png$/.test(b[0])){a=d.createElement("span");a.style.display="block";a.style.width="18px";a.style.height="18px";a.style.filter=\'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="\'+b[0]+\'")\';a.unselectable="on"}else{a=d.createElement("img");a.src=b[0]}a.style.position="relative"}a.style.top=b[2]?("-"+(18*(b[2]+1))+"px"):"-18px";a.style.left=b[1]?("-"+(18*(b[1]+1))+"px"):"-18px"}c.appendChild(a);return c};Xinha.prototype._createStatusBar=function(){this.setLoadingMessage(Xinha._lc("Create Statusbar"));var b=document.createElement("div");b.style.position="relative";b.className="statusBar";b.style.width="100%";Xinha.freeLater(this,"_statusBar");var d=document.createElement("div");d.className="statusBarWidgetContainer";d.style.position="absolute";d.style.right="0";d.style.top="0";d.style.padding="3px 3px 3px 10px";b.appendChild(d);var e=document.createElement("span");e.className="statusBarTree";e.innerHTML=Xinha._lc("Path")+": ";this._statusBarTree=e;Xinha.freeLater(this,"_statusBarTree");b.appendChild(e);var c=document.createElement("span");c.innerHTML=Xinha.htmlEncode(Xinha._lc("You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG."));c.style.display="none";this._statusBarTextMode=c;Xinha.freeLater(this,"_statusBarTextMode");b.appendChild(c);b.style.whiteSpace="nowrap";var a=this;this.notifyOn("before_resize",function(f,g){a._statusBar.style.width=null});this.notifyOn("resize",function(f,g){if(Xinha.is_ie&&Xinha.ie_version==6){a._statusBar.style.width="100%"}else{var h=g.width;a._statusBar.style.width=h+"px"}});this.notifyOn("modechange",function(g,l){for(var j in a._statusWidgets){var f=a._statusWidgets[j];for(var h=0;h<f.modes.length;h++){if(f.modes[h]==l.mode){var k=true}}if(typeof k=="undefined"){f.block.style.display="none"}else{f.block.style.display=""}}});if(!this.config.statusBar){b.style.display="none"}return b};Xinha.prototype.registerStatusWidget=function(e,c){c=c||["wysiwyg"];if(!this._statusWidgets){this._statusWidgets={}}var d=document.createElement("div");d.className="statusBarWidget";d=this._statusBar.firstChild.appendChild(d);var b=false;for(var a=0;a<c.length;a++){if(c[a]==this._editMode){b=true}}d.style.display=b==true?"":"none";this._statusWidgets[e]={block:d,modes:c};return d};Xinha.prototype.generate=function(){if(!Xinha.isSupportedBrowser){return}var w;var k=this;var g;var o=false;var c=document.getElementsByTagName("link");if(!document.getElementById("XinhaCoreDesign")){_editor_css=(typeof _editor_css=="string")?_editor_css:"Xinha.css";for(w=0;w<c.length;w++){if((c[w].rel=="stylesheet")&&(c[w].href==_editor_url+_editor_css)){o=true}}if(!o){Xinha.loadStyle(_editor_css,null,"XinhaCoreDesign",true)}}if(_editor_skin!==""&&!document.getElementById("XinhaSkin")){o=false;for(w=0;w<c.length;w++){if((c[w].rel=="stylesheet")&&(c[w].href==_editor_url+"skins/"+_editor_skin+"/skin.css")){o=true}}if(!o){Xinha.loadStyle("skins/"+_editor_skin+"/skin.css",null,"XinhaSkin")}}var h=function(){k.generate()};if(Xinha.is_ie){g=_editor_url+"modules/InternetExplorer/InternetExplorer.js";if(!Xinha.loadPlugins([{plugin:"InternetExplorer",url:g}],h)){return false}if(!this.plugins.InternetExplorer){k._browserSpecificPlugin=k.registerPlugin("InternetExplorer")}}else{if(Xinha.is_webkit){g=_editor_url+"modules/WebKit/WebKit.js";if(!Xinha.loadPlugins([{plugin:"WebKit",url:g}],h)){return false}if(!this.plugins.Webkit){k._browserSpecificPlugin=k.registerPlugin("WebKit")}}else{if(Xinha.is_opera){g=_editor_url+"modules/Opera/Opera.js";if(!Xinha.loadPlugins([{plugin:"Opera",url:g}],h)){return false}if(!this.plugins.Opera){k._browserSpecificPlugin=k.registerPlugin("Opera")}}else{if(Xinha.is_gecko){g=_editor_url+"modules/Gecko/Gecko.js";if(!Xinha.loadPlugins([{plugin:"Gecko",url:g}],h)){return false}if(!this.plugins.Gecko){k._browserSpecificPlugin=k.registerPlugin("Gecko")}}}}}if(typeof Dialog=="undefined"&&!Xinha._loadback(_editor_url+"modules/Dialogs/dialog.js",h,this)){return false}if(typeof Xinha.Dialog=="undefined"&&!Xinha._loadback(_editor_url+"modules/Dialogs/XinhaDialog.js",h,this)){return false}g=_editor_url+"modules/FullScreen/full-screen.js";if(!Xinha.loadPlugins([{plugin:"FullScreen",url:g}],h)){return false}g=_editor_url+"modules/ColorPicker/ColorPicker.js";if(!Xinha.loadPlugins([{plugin:"ColorPicker",url:g}],h)){return false}else{if(typeof Xinha.getPluginConstructor("ColorPicker")!="undefined"&&!this.plugins.colorPicker){k.registerPlugin("ColorPicker")}}var a=k.config.toolbar;for(w=a.length;--w>=0;){for(var v=a[w].length;--v>=0;){switch(a[w][v]){case"popupeditor":if(!this.plugins.FullScreen){k.registerPlugin("FullScreen")}break;case"insertimage":g=_editor_url+"modules/InsertImage/insert_image.js";if(typeof Xinha.prototype._insertImage=="undefined"&&!Xinha.loadPlugins([{plugin:"InsertImage",url:g}],h)){return false}else{if(typeof Xinha.getPluginConstructor("InsertImage")!="undefined"&&!this.plugins.InsertImage){k.registerPlugin("InsertImage")}}break;case"createlink":g=_editor_url+"modules/CreateLink/link.js";if(typeof Xinha.getPluginConstructor("Linker")=="undefined"&&!Xinha.loadPlugins([{plugin:"CreateLink",url:g}],h)){return false}else{if(typeof Xinha.getPluginConstructor("CreateLink")!="undefined"&&!this.plugins.CreateLink){k.registerPlugin("CreateLink")}}break;case"inserttable":g=_editor_url+"modules/InsertTable/insert_table.js";if(!Xinha.loadPlugins([{plugin:"InsertTable",url:g}],h)){return false}else{if(typeof Xinha.getPluginConstructor("InsertTable")!="undefined"&&!this.plugins.InsertTable){k.registerPlugin("InsertTable")}}break;case"about":g=_editor_url+"modules/AboutBox/AboutBox.js";if(!Xinha.loadPlugins([{plugin:"AboutBox",url:g}],h)){return false}else{if(typeof Xinha.getPluginConstructor("AboutBox")!="undefined"&&!this.plugins.AboutBox){k.registerPlugin("AboutBox")}}break}}}if(Xinha.is_gecko&&k.config.mozParaHandler!="built-in"){if(!Xinha.loadPlugins([{plugin:"EnterParagraphs",url:_editor_url+"modules/Gecko/paraHandlerBest.js"}],h)){return false}if(!this.plugins.EnterParagraphs){k.registerPlugin("EnterParagraphs")}}var C=this.config.getHtmlMethod=="TransformInnerHTML"?_editor_url+"modules/GetHtml/TransformInnerHTML.js":_editor_url+"modules/GetHtml/DOMwalk.js";if(!Xinha.loadPlugins([{plugin:"GetHtmlImplementation",url:C}],h)){return false}else{if(!this.plugins.GetHtmlImplementation){k.registerPlugin("GetHtmlImplementation")}}function D(i){return i.textContent||i.text}if(_editor_skin){this.skinInfo={};var s=Xinha._geturlcontent(_editor_url+"skins/"+_editor_skin+"/skin.xml",true);if(s){var p=s.getElementsByTagName("meta");for(w=0;w<p.length;w++){this.skinInfo[p[w].getAttribute("name")]=p[w].getAttribute("value")}var t=s.getElementsByTagName("recommendedIcons");if(!_editor_icons&&t.length&&D(t[0])){_editor_icons=D(t[0])}}}if(_editor_icons){var b=Xinha._geturlcontent(_editor_url+"iconsets/"+_editor_icons+"/iconset.xml",true);if(b){var E=b.getElementsByTagName("icon");var A,r,q,f,n,m;for(w=0;w<E.length;w++){A=E[w];r=A.getAttribute("id");if(A.getElementsByTagName(_editor_lang).length){A=A.getElementsByTagName(_editor_lang)[0]}else{A=A.getElementsByTagName("default")[0]}q=D(A.getElementsByTagName("path")[0]);q=(!/^\\//.test(q)?_editor_url:"")+q;f=A.getAttribute("type");if(f=="map"){n=parseInt(D(A.getElementsByTagName("x")[0]),10);m=parseInt(D(A.getElementsByTagName("y")[0]),10);if(this.config.btnList[r]){this.config.btnList[r][1]=[q,n,m]}if(this.config.iconList[r]){this.config.iconList[r]=[q,n,m]}}else{if(this.config.btnList[r]){this.config.btnList[r][1]=q}if(this.config.iconList[r]){this.config.iconList[r]=q}}}}}this.setLoadingMessage(Xinha._lc("Generate Xinha framework"));this._framework={table:document.createElement("table"),tbody:document.createElement("tbody"),tb_row:document.createElement("tr"),tb_cell:document.createElement("td"),tp_row:document.createElement("tr"),tp_cell:this._panels.top.container,ler_row:document.createElement("tr"),lp_cell:this._panels.left.container,ed_cell:document.createElement("td"),rp_cell:this._panels.right.container,bp_row:document.createElement("tr"),bp_cell:this._panels.bottom.container,sb_row:document.createElement("tr"),sb_cell:document.createElement("td")};Xinha.freeLater(this._framework);var e=this._framework;e.table.border="0";e.table.cellPadding="0";e.table.cellSpacing="0";e.tb_row.style.verticalAlign="top";e.tp_row.style.verticalAlign="top";e.ler_row.style.verticalAlign="top";e.bp_row.style.verticalAlign="top";e.sb_row.style.verticalAlign="top";e.ed_cell.style.position="relative";e.tb_row.appendChild(e.tb_cell);e.tb_cell.colSpan=3;e.tp_row.appendChild(e.tp_cell);e.tp_cell.colSpan=3;e.ler_row.appendChild(e.lp_cell);e.ler_row.appendChild(e.ed_cell);e.ler_row.appendChild(e.rp_cell);e.bp_row.appendChild(e.bp_cell);e.bp_cell.colSpan=3;e.sb_row.appendChild(e.sb_cell);e.sb_cell.colSpan=3;e.tbody.appendChild(e.tb_row);e.tbody.appendChild(e.tp_row);e.tbody.appendChild(e.ler_row);e.tbody.appendChild(e.bp_row);e.tbody.appendChild(e.sb_row);e.table.appendChild(e.tbody);var B=e.table;this._htmlArea=B;Xinha.freeLater(this,"_htmlArea");B.className="htmlarea";e.tb_cell.appendChild(this._createToolbar());var d=document.createElement("iframe");d.src=this.popupURL(k.config.URIs.blank);d.id="XinhaIFrame_"+this._textArea.id;e.ed_cell.appendChild(d);this._iframe=d;this._iframe.className="xinha_iframe";Xinha.freeLater(this,"_iframe");var u=this._createStatusBar();this._statusBar=e.sb_cell.appendChild(u);var F=this._textArea;F.parentNode.insertBefore(B,F);F.className="xinha_textarea";Xinha.removeFromParent(F);e.ed_cell.appendChild(F);Xinha.addDom0Event(this._textArea,"click",function(){if(Xinha._currentlyActiveEditor!=this){k.updateToolbar()}return true});if(F.form){Xinha.prependDom0Event(this._textArea.form,"submit",function(){k.firePluginEvent("onBeforeSubmit");k._textArea.value=k.outwardHtml(k.getHTML());return true});var l=F.value;Xinha.prependDom0Event(this._textArea.form,"reset",function(){k.setHTML(k.inwardHtml(l));k.updateToolbar();return true});if(!F.form.xinha_submit){try{F.form.xinha_submit=F.form.submit;F.form.submit=function(){this.onsubmit();this.xinha_submit()}}catch(z){}}}Xinha.prependDom0Event(window,"unload",function(){k.firePluginEvent("onBeforeUnload");F.value=k.outwardHtml(k.getHTML());if(!Xinha.is_ie){B.parentNode.replaceChild(F,B)}return true});F.style.display="none";k.initSize();this.setLoadingMessage(Xinha._lc("Finishing"));k._iframeLoadDone=false;if(Xinha.is_opera){k.initIframe()}else{Xinha._addEvent(this._iframe,"load",function(i){if(!k._iframeLoadDone){k._iframeLoadDone=true;k.initIframe()}return true})}};Xinha.prototype.initSize=function(){this.setLoadingMessage(Xinha._lc("Init editor size"));var a=this;var b=null;var c=null;switch(this.config.width){case"auto":b=this._initial_ta_size.w;break;case"toolbar":b=this._toolBar.offsetWidth+"px";break;default:b=/[^0-9]/.test(this.config.width)?this.config.width:this.config.width+"px";break}c=this.config.height=="auto"?this._initial_ta_size.h:/[^0-9]/.test(this.config.height)?this.config.height:this.config.height+"px";this.sizeEditor(b,c,this.config.sizeIncludesBars,this.config.sizeIncludesPanels);this.notifyOn("panel_change",function(){a.sizeEditor()})};Xinha.prototype.sizeEditor=function(c,o,j,a){if(this._risizing){return}this._risizing=true;var k=this._framework;this.notifyOf("before_resize",{width:c,height:o});this.firePluginEvent("onBeforeResize",c,o);this._iframe.style.height="100%";this._textArea.style.height="1px";this._iframe.style.width="0px";this._textArea.style.width="0px";if(j!==null){this._htmlArea.sizeIncludesToolbars=j}if(a!==null){this._htmlArea.sizeIncludesPanels=a}if(c){this._htmlArea.style.width=c;if(!this._htmlArea.sizeIncludesPanels){var p=this._panels.right;if(p.on&&p.panels.length&&Xinha.hasDisplayedChildren(p.div)){this._htmlArea.style.width=(this._htmlArea.offsetWidth+parseInt(this.config.panel_dimensions.right,10))+"px"}var l=this._panels.left;if(l.on&&l.panels.length&&Xinha.hasDisplayedChildren(l.div)){this._htmlArea.style.width=(this._htmlArea.offsetWidth+parseInt(this.config.panel_dimensions.left,10))+"px"}}}if(o){this._htmlArea.style.height=o;if(!this._htmlArea.sizeIncludesToolbars){this._htmlArea.style.height=(this._htmlArea.offsetHeight+this._toolbar.offsetHeight+this._statusBar.offsetHeight)+"px"}if(!this._htmlArea.sizeIncludesPanels){var e=this._panels.top;if(e.on&&e.panels.length&&Xinha.hasDisplayedChildren(e.div)){this._htmlArea.style.height=(this._htmlArea.offsetHeight+parseInt(this.config.panel_dimensions.top,10))+"px"}var n=this._panels.bottom;if(n.on&&n.panels.length&&Xinha.hasDisplayedChildren(n.div)){this._htmlArea.style.height=(this._htmlArea.offsetHeight+parseInt(this.config.panel_dimensions.bottom,10))+"px"}}}c=this._htmlArea.offsetWidth;o=this._htmlArea.offsetHeight;var b=this._panels;var d=this;var i=1;function h(q){if(b[q].on&&b[q].panels.length&&Xinha.hasDisplayedChildren(b[q].container)){b[q].container.style.display="";return true}else{b[q].container.style.display="none";return false}}if(h("left")){i+=1}if(h("right")){i+=1}k.tb_cell.colSpan=i;k.tp_cell.colSpan=i;k.bp_cell.colSpan=i;k.sb_cell.colSpan=i;if(!k.tp_row.childNodes.length){Xinha.removeFromParent(k.tp_row)}else{if(!Xinha.hasParentNode(k.tp_row)){k.tbody.insertBefore(k.tp_row,k.ler_row)}}if(!k.bp_row.childNodes.length){Xinha.removeFromParent(k.bp_row)}else{if(!Xinha.hasParentNode(k.bp_row)){k.tbody.insertBefore(k.bp_row,k.ler_row.nextSibling)}}if(!this.config.statusBar){Xinha.removeFromParent(k.sb_row)}else{if(!Xinha.hasParentNode(k.sb_row)){k.table.appendChild(k.sb_row)}}k.lp_cell.style.width=this.config.panel_dimensions.left;k.rp_cell.style.width=this.config.panel_dimensions.right;k.tp_cell.style.height=this.config.panel_dimensions.top;k.bp_cell.style.height=this.config.panel_dimensions.bottom;k.tb_cell.style.height=this._toolBar.offsetHeight+"px";k.sb_cell.style.height=this._statusBar.offsetHeight+"px";var m=o-this._toolBar.offsetHeight-this._statusBar.offsetHeight;if(h("top")){m-=parseInt(this.config.panel_dimensions.top,10)}if(h("bottom")){m-=parseInt(this.config.panel_dimensions.bottom,10)}this._iframe.style.height=m+"px";var f=c;if(h("left")){f-=parseInt(this.config.panel_dimensions.left,10)}if(h("right")){f-=parseInt(this.config.panel_dimensions.right,10)}var g=this.config.iframeWidth?parseInt(this.config.iframeWidth,10):null;this._iframe.style.width=(g&&g<f)?g+"px":f+"px";this._textArea.style.height=this._iframe.style.height;this._textArea.style.width=this._iframe.style.width;this.notifyOf("resize",{width:this._htmlArea.offsetWidth,height:this._htmlArea.offsetHeight});this.firePluginEvent("onResize",this._htmlArea.offsetWidth,this._htmlArea.offsetWidth);this._risizing=false};Xinha.prototype.registerPanel=function(c,b){if(!c){c="right"}this.setLoadingMessage("Register "+c+" panel ");var a=this.addPanel(c);if(b){b.drawPanelIn(a)}};Xinha.prototype.addPanel=function(a){var b=document.createElement("div");b.side=a;if(a=="left"||a=="right"){b.style.width=this.config.panel_dimensions[a];if(this._iframe){b.style.height=this._iframe.style.height}}Xinha.addClasses(b,"panel");this._panels[a].panels.push(b);this._panels[a].div.appendChild(b);this.notifyOf("panel_change",{action:"add",panel:b});this.firePluginEvent("onPanelChange","add",b);return b};Xinha.prototype.removePanel=function(a){this._panels[a.side].div.removeChild(a);var c=[];for(var b=0;b<this._panels[a.side].panels.length;b++){if(this._panels[a.side].panels[b]!=a){c.push(this._panels[a.side].panels[b])}}this._panels[a.side].panels=c;this.notifyOf("panel_change",{action:"remove",panel:a});this.firePluginEvent("onPanelChange","remove",a)};Xinha.prototype.hidePanel=function(a){if(a&&a.style.display!="none"){try{var c=this.scrollPos(this._iframe.contentWindow)}catch(b){}a.style.display="none";this.notifyOf("panel_change",{action:"hide",panel:a});this.firePluginEvent("onPanelChange","hide",a);try{this._iframe.contentWindow.scrollTo(c.x,c.y)}catch(b){}}};Xinha.prototype.showPanel=function(a){if(a&&a.style.display=="none"){try{var c=this.scrollPos(this._iframe.contentWindow)}catch(b){}a.style.display="";this.notifyOf("panel_change",{action:"show",panel:a});this.firePluginEvent("onPanelChange","show",a);try{this._iframe.contentWindow.scrollTo(c.x,c.y)}catch(b){}}};Xinha.prototype.hidePanels=function(b){if(typeof b=="undefined"){b=["left","right","top","bottom"]}var c=[];for(var a=0;a<b.length;a++){if(this._panels[b[a]].on){c.push(b[a]);this._panels[b[a]].on=false}}this.notifyOf("panel_change",{action:"multi_hide",sides:b});this.firePluginEvent("onPanelChange","multi_hide",b)};Xinha.prototype.showPanels=function(b){if(typeof b=="undefined"){b=["left","right","top","bottom"]}var c=[];for(var a=0;a<b.length;a++){if(!this._panels[b[a]].on){c.push(b[a]);this._panels[b[a]].on=true}}this.notifyOf("panel_change",{action:"multi_show",sides:b});this.firePluginEvent("onPanelChange","multi_show",b)};Xinha.objectProperties=function(c){var b=[];for(var a in c){b[b.length]=a}return b};Xinha.prototype.editorIsActivated=function(){try{return Xinha.is_designMode?this._doc.designMode=="on":this._doc.body.contentEditable}catch(a){return false}};Xinha._someEditorHasBeenActivated=false;Xinha._currentlyActiveEditor=null;Xinha.prototype.activateEditor=function(){if(this.currentModal){return}if(Xinha._currentlyActiveEditor){if(Xinha._currentlyActiveEditor==this){return true}Xinha._currentlyActiveEditor.deactivateEditor()}if(Xinha.is_designMode&&this._doc.designMode!="on"){try{if(this._iframe.style.display=="none"){this._iframe.style.display="";this._doc.designMode="on";this._iframe.style.display="none"}else{this._doc.designMode="on"}if(Xinha.is_opera){this.setEditorEvents(true)}}catch(b){}}else{if(Xinha.is_ie&&this._doc.body.contentEditable!==true){this._doc.body.contentEditable=true}}Xinha._someEditorHasBeenActivated=true;Xinha._currentlyActiveEditor=this;var a=this;this.enableToolbar()};Xinha.prototype.deactivateEditor=function(){this.disableToolbar();if(Xinha.is_designMode&&this._doc.designMode!="off"){try{this._doc.designMode="off"}catch(a){}}else{if(!Xinha.is_designMode&&this._doc.body.contentEditable!==false){this._doc.body.contentEditable=false}}if(Xinha._currentlyActiveEditor!=this){return}Xinha._currentlyActiveEditor=false};Xinha.prototype.initIframe=function(){this.disableToolbar();var g=null;var b=this;try{if(b._iframe.contentDocument){this._doc=b._iframe.contentDocument}else{this._doc=b._iframe.contentWindow.document}g=this._doc;if(!g){if(Xinha.is_gecko){setTimeout(function(){b.initIframe()},50);return false}else{alert("ERROR: IFRAME can\'t be initialized.")}}}catch(f){setTimeout(function(){b.initIframe()},50);return false}Xinha.freeLater(this,"_doc");g.open("text/html","replace");var e="",a;if(b.config.browserQuirksMode===false){a=\'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\'}else{if(b.config.browserQuirksMode===true){a=""}else{a=Xinha.getDoctype(document)}}if(!b.config.fullPage){e+=a+"\\n";e+="<html>\\n";e+="<head>\\n";e+=\'<meta http-equiv="Content-Type" content="text/html; charset=\'+b.config.charSet+\'">\\n\';if(typeof b.config.baseHref!="undefined"&&b.config.baseHref!==null){e+=\'<base href="\'+b.config.baseHref+\'"/>\\n\'}e+=Xinha.addCoreCSS();if(typeof b.config.pageStyleSheets!=="undefined"){for(var d=0;d<b.config.pageStyleSheets.length;d++){if(b.config.pageStyleSheets[d].length>0){e+=\'<link rel="stylesheet" type="text/css" href="\'+b.config.pageStyleSheets[d]+\'">\'}}}if(b.config.pageStyle){e+=\'<style type="text/css">\\n\'+b.config.pageStyle+"\\n</style>"}e+="</head>\\n";e+="<body"+(b.config.bodyID?(\' id="\'+b.config.bodyID+\'"\'):"")+(b.config.bodyClass?(\' class="\'+b.config.bodyClass+\'"\'):"")+">\\n";e+=b.inwardHtml(b._textArea.value);e+="</body>\\n";e+="</html>"}else{e=b.inwardHtml(b._textArea.value);if(e.match(Xinha.RE_doctype)){b.setDoctype(RegExp.$1)}var c=e.match(/<link\\s+[\\s\\S]*?["\']\\s*\\/?>/gi);e=e.replace(/<link\\s+[\\s\\S]*?["\']\\s*\\/?>\\s*/gi,"");if(c){e=e.replace(/<\\/head>/i,c.join("\\n")+"\\n</head>")}}g.write(e);g.close();if(this.config.fullScreen){this._fullScreen()}this.setEditorEvents();if((typeof b.config.autofocus!="undefined")&&b.config.autofocus!==false&&((b.config.autofocus==b._textArea.id)||b.config.autofocus==true)){b.activateEditor();b.focusEditor()}};Xinha.prototype.whenDocReady=function(a){var b=this;if(this._doc&&this._doc.body){a()}else{setTimeout(function(){b.whenDocReady(a)},50)}};Xinha.prototype.setMode=function(b){var a;if(typeof b=="undefined"){b=this._editMode=="textmode"?"wysiwyg":"textmode"}switch(b){case"textmode":this.firePluginEvent("onBeforeMode","textmode");this._toolbarObjects.htmlmode.swapImage(this.config.iconList.wysiwygmode);this.setCC("iframe");a=this.outwardHtml(this.getHTML());this.setHTML(a);this.deactivateEditor();this._iframe.style.display="none";this._textArea.style.display="";if(this.config.statusBar){this._statusBarTree.style.display="none";this._statusBarTextMode.style.display=""}this.findCC("textarea");this.notifyOf("modechange",{mode:"text"});this.firePluginEvent("onMode","textmode");break;case"wysiwyg":this.firePluginEvent("onBeforeMode","wysiwyg");this._toolbarObjects.htmlmode.swapImage([this.imgURL("images/ed_buttons_main.png"),7,0]);this.setCC("textarea");a=this.inwardHtml(this.getHTML());this.deactivateEditor();this.setHTML(a);this._iframe.style.display="";this._textArea.style.display="none";this.activateEditor();if(this.config.statusBar){this._statusBarTree.style.display="";this._statusBarTextMode.style.display="none"}this.findCC("iframe");this.notifyOf("modechange",{mode:"wysiwyg"});this.firePluginEvent("onMode","wysiwyg");break;default:alert("Mode <"+b+"> not defined!");return false}this._editMode=b};Xinha.prototype.setFullHTML=function(c){var a=RegExp.multiline;RegExp.multiline=true;if(c.match(Xinha.RE_doctype)){this.setDoctype(RegExp.$1)}RegExp.multiline=a;if(0){if(c.match(Xinha.RE_head)){this._doc.getElementsByTagName("head")[0].innerHTML=RegExp.$1}if(c.match(Xinha.RE_body)){this._doc.getElementsByTagName("body")[0].innerHTML=RegExp.$1}}else{var d=this.editorIsActivated();if(d){this.deactivateEditor()}var b=/<html>((.|\\n)*?)<\\/html>/i;c=c.replace(b,"$1");this._doc.open("text/html","replace");this._doc.write(c);this._doc.close();if(d){this.activateEditor()}this.setEditorEvents();return true}};Xinha.prototype.setEditorEvents=function(c){var a=this;var b=this._doc;a.whenDocReady(function(){if(!c){Xinha._addEvents(b,["mousedown"],function(){a.activateEditor();return true});if(Xinha.is_ie){Xinha._addEvent(a._doc.getElementsByTagName("html")[0],"click",function(){if(a._iframe.contentWindow.event.srcElement.tagName.toLowerCase()=="html"){var f=a._doc.body.createTextRange();f.collapse();f.select()}return true})}}Xinha._addEvents(b,["keydown","keypress","mousedown","mouseup","drag"],function(f){return a._editorEvent(Xinha.is_ie?a._iframe.contentWindow.event:f)});Xinha._addEvents(b,["dblclick"],function(f){return a._onDoubleClick(Xinha.is_ie?a._iframe.contentWindow.event:f)});if(c){return}for(var e in a.plugins){var d=a.plugins[e].instance;Xinha.refreshPlugin(d)}if(typeof a._onGenerate=="function"){a._onGenerate()}Xinha.addDom0Event(window,"resize",function(f){if(Xinha.ie_version>7&&!window.parent){if(a.execResize){a.sizeEditor();a.execResize=false}else{a.execResize=true}}else{a.sizeEditor()}});a.removeLoadingMessage()})};Xinha.getPluginConstructor=function(a){return Xinha.plugins[a]||window[a]};Xinha.prototype.registerPlugin=function(){if(!Xinha.isSupportedBrowser){return}var a=arguments[0];if(a===null||typeof a=="undefined"||(typeof a=="string"&&Xinha.getPluginConstructor(a)=="undefined")){return false}var b=[];for(var c=1;c<arguments.length;++c){b.push(arguments[c])}return this.registerPlugin2(a,b)};Xinha.prototype.registerPlugin2=function(b,c){if(typeof b=="string"&&typeof Xinha.getPluginConstructor(b)=="function"){var a=b;b=Xinha.getPluginConstructor(b)}if(typeof b=="undefined"){return false}if(!b._pluginInfo){b._pluginInfo={name:a}}var f=new b(this,c);if(f){var g={};var e=b._pluginInfo;for(var d in e){g[d]=e[d]}g.instance=f;g.args=c;this.plugins[b._pluginInfo.name]=g;return f}else{Xinha.debugMsg("Can\'t register plugin "+b.toString()+".","warn")}};Xinha.getPluginDir=function(a,b){if(Xinha.externalPlugins[a]){return Xinha.externalPlugins[a][0]}if(b||(Xinha.getPluginConstructor(a)&&(typeof Xinha.getPluginConstructor(a).supported!="undefined")&&!Xinha.getPluginConstructor(a).supported)){return _editor_url+"unsupported_plugins/"+a}return _editor_url+"plugins/"+a};Xinha.loadPlugin=function(b,e,d){if(!Xinha.isSupportedBrowser){return}Xinha.setLoadingMessage(Xinha._lc("Loading plugin $plugin="+b+"$"));if(typeof Xinha.getPluginConstructor(b)!="undefined"){if(e){e(b)}return true}Xinha._pluginLoadStatus[b]="loading";function a(j,f){var m,i,l,k;switch(j){case"start":m="old_naming";i=Xinha.getPluginDir(f);l=f+".js";break;case"old_naming":m="unsupported";i=Xinha.getPluginDir(f);l=f.replace(/([a-z])([A-Z])([a-z])/g,function(p,o,n,q){return o+"-"+n.toLowerCase()+q}).toLowerCase()+".js";k="You are using an obsolete naming scheme for the Xinha plugin "+f+". Please rename "+l+" to "+f+".js";break;case"unsupported":m="unsupported_old_name";i=Xinha.getPluginDir(f,true);l=f+".js";k="You are using the unsupported Xinha plugin "+f+". If you wish continued support, please see http://trac.xinha.org/ticket/1297";break;case"unsupported_old_name":m="";i=Xinha.getPluginDir(f,true);l=f.replace(/([a-z])([A-Z])([a-z])/g,function(p,o,n,q){return o+"-"+n.toLowerCase()+q}).toLowerCase()+".js";k="You are using the unsupported Xinha plugin "+f+". If you wish continued support, please see http://trac.xinha.org/ticket/1297";break;default:Xinha._pluginLoadStatus[f]="failed";Xinha.debugMsg("Xinha was not able to find the plugin "+f+". Please make sure the plugin exists.","warn");return}var h=i+"/"+l;function g(n){Xinha.getPluginConstructor(n).supported=j.indexOf("unsupported")!==0;e(n)}Xinha._loadback(h,g,this,f);Xinha.ping(h,function(){if(k){Xinha.debugMsg(k)}},function(){Xinha.removeFromParent(document.getElementById(h));a(m,f)})}if(!d){if(Xinha.externalPlugins[b]){Xinha._loadback(Xinha.externalPlugins[b][0]+Xinha.externalPlugins[b][1],e,this,b)}else{var c=this;a("start",b)}}else{Xinha._loadback(d,e,this,b)}return false};Xinha._pluginLoadStatus={};Xinha.externalPlugins={};Xinha.plugins={};Xinha.loadPlugins=function(f,c,d){if(!Xinha.isSupportedBrowser){return}var b,e;for(e=0;e<f.length;e++){if(typeof f[e]=="object"){b=f[e].url.match(/(.*)(\\/[^\\/]*)$/);Xinha.externalPlugins[f[e].plugin]=[b[1],b[2]];f[e]=f[e].plugin}}var h=true;var a=Xinha.cloneObject(f);for(e=0;e<a.length;e++){var g=a[e];if(g=="FullScreen"&&!Xinha.externalPlugins.FullScreen){continue}if(typeof Xinha._pluginLoadStatus[g]=="undefined"){Xinha.loadPlugin(g,function(i){Xinha.setLoadingMessage(Xinha._lc("Finishing"));if(typeof Xinha.getPluginConstructor(i)!="undefined"){Xinha._pluginLoadStatus[i]="ready"}else{Xinha._pluginLoadStatus[i]="failed"}},d);h=false}else{if(Xinha._pluginLoadStatus[g]=="loading"){h=false}}}if(h){return true}if(c){setTimeout(function(){if(Xinha.loadPlugins(f,c)){c()}},50)}return h};Xinha.refreshPlugin=function(a){if(a&&typeof a.onGenerate=="function"){a.onGenerate()}if(a&&typeof a.onGenerateOnce=="function"){a._ongenerateOnce=a.onGenerateOnce;delete (a.onGenerateOnce);a._ongenerateOnce();delete (a._ongenerateOnce)}};Xinha.prototype.firePluginEvent=function(c){var e=[];for(var b=1;b<arguments.length;b++){e[b-1]=arguments[b]}for(b in this.plugins){var a=this.plugins[b].instance;if(a==this._browserSpecificPlugin){continue}if(a&&typeof a[c]=="function"){var d=(b=="Events")?this:a;if(a[c].apply(d,e)){return true}}}a=this._browserSpecificPlugin;if(a&&typeof a[c]=="function"){if(a[c].apply(a,e)){return true}}return false};Xinha.loadStyle=function(e,a,g,d){var b=_editor_url||"";if(a){b=Xinha.getPluginDir(a)+"/"}b+=e;if(/^\\//.test(e)){b=e}var c=document.getElementsByTagName("head")[0];var f=document.createElement("link");f.rel="stylesheet";f.href=b;f.type="text/css";if(g){f.id=g}if(d&&c.getElementsByTagName("link")[0]){c.insertBefore(f,c.getElementsByTagName("link")[0])}else{c.appendChild(f)}};Xinha.loadScript=function(c,a,d){var b=_editor_url||"";if(a){b=Xinha.getPluginDir(a)+"/"}b+=c;if(/^\\//.test(c)){b=c}Xinha._loadback(b,d)};Xinha.includeAssets=function(){var b={pendingAssets:[],loaderRunning:false,loadedScripts:[]};b.callbacks=[];b.loadNext=function(){var d=this;this.loaderRunning=true;if(this.pendingAssets.length){var c=this.pendingAssets[0];this.pendingAssets.splice(0,1);switch(c.type){case"text/css":Xinha.loadStyle(c.url,c.plugin);return this.loadNext();case"text/javascript":Xinha.loadScript(c.url,c.plugin,function(){d.loadNext()})}}else{this.loaderRunning=false;this.runCallback()}};b.loadScript=function(e,c){var d=this;this.pendingAssets.push({type:"text/javascript",url:e,plugin:c});if(!this.loaderRunning){this.loadNext()}return this};b.loadScriptOnce=function(d,c){for(var e=0;e<this.loadedScripts.length;e++){if(this.loadedScripts[e].url==d&&this.loadedScripts[e].plugin==c){return this}}return this.loadScript(d,c)};b.loadStyle=function(e,c){var d=this;this.pendingAssets.push({type:"text/css",url:e,plugin:c});if(!this.loaderRunning){this.loadNext()}return this};b.whenReady=function(c){this.callbacks.push(c);if(!this.loaderRunning){this.loadNext()}return this};b.runCallback=function(){while(this.callbacks.length){var c=this.callbacks.splice(0,1);c[0]();c=null}return this};for(var a=0;a<arguments.length;a++){if(typeof arguments[a]=="string"){if(arguments[a].match(/\\.css$/i)){b.loadStyle(arguments[a])}else{b.loadScript(arguments[a])}}else{if(arguments[a].type){if(arguments[a].type.match(/text\\/css/i)){b.loadStyle(arguments[a].url,arguments[a].plugin)}else{if(arguments[a].type.match(/text\\/javascript/i)){b.loadScript(arguments[a].url,arguments[a].plugin)}}}else{if(arguments[a].length>=1){if(arguments[a][0].match(/\\.css$/i)){b.loadStyle(arguments[a][0],arguments[a][1])}else{b.loadScript(arguments[a][0],arguments[a][1])}}}}}return b};Xinha.prototype.debugTree=function(){var c=document.createElement("textarea");c.style.width="100%";c.style.height="20em";c.value="";function b(d,e){for(;--d>=0;){c.value+=" "}c.value+=e+"\\n"}function a(e,h){var d=e.tagName.toLowerCase(),f;var g=Xinha.is_ie?e.scopeName:e.prefix;b(h,"- "+d+" ["+g+"]");for(f=e.firstChild;f;f=f.nextSibling){if(f.nodeType==1){a(f,h+2)}}}a(this._doc.body,0);document.body.appendChild(c)};Xinha.getInnerText=function(c){var a="",b;for(b=c.firstChild;b;b=b.nextSibling){if(b.nodeType==3){a+=b.data}else{if(b.nodeType==1){a+=Xinha.getInnerText(b)}}}return a};Xinha.prototype._wordClean=function(){var b=this;var e={empty_tags:0,cond_comm:0,mso_elmts:0,mso_class:0,mso_style:0,mso_xmlel:0,orig_len:this._doc.body.innerHTML.length,T:new Date().getTime()};var g={empty_tags:"Empty tags removed: ",cond_comm:"Conditional comments removed",mso_elmts:"MSO invalid elements removed",mso_class:"MSO class names removed: ",mso_style:"MSO inline style removed: ",mso_xmlel:"MSO XML elements stripped: "};function f(){var j="Xinha word cleaner stats: \\n\\n";for(var k in e){if(g[k]){j+=g[k]+e[k]+"\\n"}}j+="\\nInitial document length: "+e.orig_len+"\\n";j+="Final document length: "+b._doc.body.innerHTML.length+"\\n";j+="Clean-up took "+((new Date().getTime()-e.T)/1000)+" seconds";alert(j)}function h(j){var k=j.className.replace(/(^|\\s)mso.*?(\\s|$)/ig," ");if(k!=j.className){j.className=k;if(!/\\S/.test(j.className)){j.removeAttribute("className");++e.mso_class}}}function a(k){var l=k.style.cssText.split(/\\s*;\\s*/);for(var j=l.length;--j>=0;){if(/^mso|^tab-stops/i.test(l[j])||/^margin\\s*:\\s*0..\\s+0..\\s+0../i.test(l[j])){++e.mso_style;l.splice(j,1)}}k.style.cssText=l.join("; ")}function c(j){if(("link"==j.tagName.toLowerCase()&&(j.attributes&&/File-List|Edit-Time-Data|themeData|colorSchemeMapping/.test(j.attributes.rel.nodeValue)))||/^(style|meta)$/i.test(j.tagName)){Xinha.removeFromParent(j);++e.mso_elmts;return true}return false}function d(j){if(/^(a|span|b|strong|i|em|font|div|p)$/i.test(j.tagName)&&!j.firstChild){Xinha.removeFromParent(j);++e.empty_tags;return true}return false}function i(j){h(j);a(j);var m;for(var l=j.firstChild;l;l=m){m=l.nextSibling;if(l.nodeType==1&&i(l)){if((Xinha.is_ie&&j.scopeName!="HTML")||(!Xinha.is_ie&&/:/.test(l.tagName))){for(var k=l.childNodes&&l.childNodes.length-1;l.childNodes&&l.childNodes.length&&l.childNodes[k];--k){if(l.nextSibling){l.parentNode.insertBefore(l.childNodes[k],l.nextSibling)}else{l.parentNode.appendChild(l.childNodes[k])}}Xinha.removeFromParent(l);continue}if(d(l)){continue}if(c(l)){continue}}else{if(l.nodeType==8){if(/(\\s*\\[\\s*if\\s*(([gl]te?|!)\\s*)?(IE|mso)\\s*(\\d+(\\.\\d+)?\\s*)?\\]>)/.test(l.nodeValue)){Xinha.removeFromParent(l);++e.cond_comm}}}}return true}i(this._doc.body);this.updateToolbar()};Xinha.prototype._clearFonts=function(){var a=this.getInnerHTML();if(confirm(Xinha._lc("Would you like to clear font typefaces?"))){a=a.replace(/face="[^"]*"/gi,"");a=a.replace(/font-family:[^;}"\']+;?/gi,"")}if(confirm(Xinha._lc("Would you like to clear font sizes?"))){a=a.replace(/size="[^"]*"/gi,"");a=a.replace(/font-size:[^;}"\']+;?/gi,"")}if(confirm(Xinha._lc("Would you like to clear font colours?"))){a=a.replace(/color="[^"]*"/gi,"");a=a.replace(/([^\\-])color:[^;}"\']+;?/gi,"$1")}a=a.replace(/(style|class)="\\s*"/gi,"");a=a.replace(/<(font|span)\\s*>/gi,"");this.setHTML(a);this.updateToolbar()};Xinha.prototype._splitBlock=function(){this._doc.execCommand("formatblock",false,"div")};Xinha.prototype.forceRedraw=function(){this._doc.body.style.visibility="hidden";this._doc.body.style.visibility=""};Xinha.prototype.focusEditor=function(){switch(this._editMode){case"wysiwyg":try{if(Xinha._someEditorHasBeenActivated){this.activateEditor();this._iframe.contentWindow.focus()}}catch(a){}break;case"textmode":try{this._textArea.focus()}catch(b){}break;default:alert("ERROR: mode "+this._editMode+" is not defined")}return this._doc};Xinha.prototype._undoTakeSnapshot=function(){++this._undoPos;if(this._undoPos>=this.config.undoSteps){this._undoQueue.shift();--this._undoPos}var b=true;var a=this.getInnerHTML();if(this._undoPos>0){b=(this._undoQueue[this._undoPos-1]!=a)}if(b){this._undoQueue[this._undoPos]=a}else{this._undoPos--}};Xinha.prototype.undo=function(){if(this._undoPos>0){var a=this._undoQueue[--this._undoPos];if(a){this.setHTML(a)}else{++this._undoPos}}};Xinha.prototype.redo=function(){if(this._undoPos<this._undoQueue.length-1){var a=this._undoQueue[++this._undoPos];if(a){this.setHTML(a)}else{--this._undoPos}}};Xinha.prototype.disableToolbar=function(a){if(this._timerToolbar){clearTimeout(this._timerToolbar)}if(typeof a=="undefined"){a=[]}else{if(typeof a!="object"){a=[a]}}for(var c in this._toolbarObjects){var b=this._toolbarObjects[c];if(a.contains(c)){continue}if(typeof b.state!="function"){continue}b.state("enabled",false)}};Xinha.prototype.enableToolbar=function(){this.updateToolbar()};Xinha.prototype.updateToolbar=function(noStatus){if(this.suspendUpdateToolbar){return}var doc=this._doc;var text=(this._editMode=="textmode");var ancestors=null;if(!text){ancestors=this.getAllAncestors();if(this.config.statusBar&&!noStatus){while(this._statusBarItems.length){var item=this._statusBarItems.pop();item.el=null;item.editor=null;item.onclick=null;item.oncontextmenu=null;item._xinha_dom0Events.click=null;item._xinha_dom0Events.contextmenu=null;item=null}this._statusBarTree.innerHTML=" ";this._statusBarTree.appendChild(document.createTextNode(Xinha._lc("Path")+": "));for(var i=ancestors.length;--i>=0;){var el=ancestors[i];if(!el){continue}var a=document.createElement("a");a.href="javascript:void(0);";a.el=el;a.editor=this;this._statusBarItems.push(a);Xinha.addDom0Event(a,"click",function(){this.blur();this.editor.selectNodeContents(this.el);this.editor.updateToolbar(true);return false});Xinha.addDom0Event(a,"contextmenu",function(){this.blur();var info="Inline style:\\n\\n";info+=this.el.style.cssText.split(/;\\s*/).join(";\\n");alert(info);return false});var txt=el.tagName.toLowerCase();switch(txt){case"b":txt="strong";break;case"i":txt="em";break;case"strike":txt="del";break}if(typeof el.style!="undefined"){a.title=el.style.cssText}if(el.id){txt+="#"+el.id}if(el.className){txt+="."+el.className}a.appendChild(document.createTextNode(txt));this._statusBarTree.appendChild(a);if(i!==0){this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(187)))}Xinha.freeLater(a)}}}for(var cmd in this._toolbarObjects){var btn=this._toolbarObjects[cmd];var inContext=true;if(typeof btn.state!="function"){continue}if(btn.context&&!text){inContext=false;var context=btn.context;var attrs=[];if(/(.*)\\[(.*?)\\]/.test(context)){context=RegExp.$1;attrs=RegExp.$2.split(",")}context=context.toLowerCase();var match=(context=="*");for(var k=0;k<ancestors.length;++k){if(!ancestors[k]){continue}if(match||(ancestors[k].tagName.toLowerCase()==context)){inContext=true;var contextSplit=null;var att=null;var comp=null;var attVal=null;for(var ka=0;ka<attrs.length;++ka){contextSplit=attrs[ka].match(/(.*)(==|!=|===|!==|>|>=|<|<=)(.*)/);att=contextSplit[1];comp=contextSplit[2];attVal=contextSplit[3];if(!eval(ancestors[k][att]+comp+attVal)){inContext=false;break}}if(inContext){break}}}}btn.state("enabled",(!text||btn.text)&&inContext);if(typeof cmd=="function"){continue}var dropdown=this.config.customSelects[cmd];if((!text||btn.text)&&(typeof dropdown!="undefined")){dropdown.refresh(this);continue}switch(cmd){case"fontname":case"fontsize":if(!text){try{var value=(""+doc.queryCommandValue(cmd)).toLowerCase();if(!value){btn.element.selectedIndex=0;break}var options=this.config[cmd];var sIndex=0;for(var j in options){if((j.toLowerCase()==value)||(options[j].substr(0,value.length).toLowerCase()==value)){btn.element.selectedIndex=sIndex;throw"ok"}++sIndex}btn.element.selectedIndex=0}catch(ex){}}break;case"formatblock":var blocks=[];for(var indexBlock in this.config.formatblock){if(typeof this.config.formatblock[indexBlock]=="string"){blocks[blocks.length]=this.config.formatblock[indexBlock]}}var deepestAncestor=this._getFirstAncestor(this.getSelection(),blocks);if(deepestAncestor){for(var x=0;x<blocks.length;x++){if(blocks[x].toLowerCase()==deepestAncestor.tagName.toLowerCase()){btn.element.selectedIndex=x}}}else{btn.element.selectedIndex=0}break;case"textindicator":if(!text){try{var style=btn.element.style;style.backgroundColor=Xinha._makeColor(doc.queryCommandValue(Xinha.is_ie?"backcolor":"hilitecolor"));if(/transparent/i.test(style.backgroundColor)){style.backgroundColor=Xinha._makeColor(doc.queryCommandValue("backcolor"))}style.color=Xinha._makeColor(doc.queryCommandValue("forecolor"));style.fontFamily=doc.queryCommandValue("fontname");style.fontWeight=doc.queryCommandState("bold")?"bold":"normal";style.fontStyle=doc.queryCommandState("italic")?"italic":"normal"}catch(ex){}}break;case"htmlmode":btn.state("active",text);break;case"lefttoright":case"righttoleft":var eltBlock=this.getParentElement();while(eltBlock&&!Xinha.isBlockElement(eltBlock)){eltBlock=eltBlock.parentNode}if(eltBlock){btn.state("active",(eltBlock.style.direction==((cmd=="righttoleft")?"rtl":"ltr")))}break;default:cmd=cmd.replace(/(un)?orderedlist/i,"insert$1orderedlist");try{btn.state("active",(!text&&doc.queryCommandState(cmd)))}catch(ex){}break}}if(this._customUndo&&!this._timerUndo){this._undoTakeSnapshot();var editor=this;this._timerUndo=setTimeout(function(){editor._timerUndo=null},this.config.undoTimeout)}this.firePluginEvent("onUpdateToolbar")};Xinha.getEditor=function(c){for(var b=__xinhas.length;b--;){var a=__xinhas[b];if(a&&(a._textArea.id==c||a._textArea.name==c||a._textArea==c)){return a}}return null};Xinha.prototype.getPluginInstance=function(a){if(this.plugins[a]){return this.plugins[a].instance}else{return null}};Xinha.prototype.getAllAncestors=function(){var c=this.getParentElement();var b=[];while(c&&(c.nodeType==1)&&(c.tagName.toLowerCase()!="body")){b.push(c);c=c.parentNode}b.push(this._doc.body);return b};Xinha.prototype._getFirstAncestor=function(e,d){var c=this.activeElement(e);if(c===null){try{c=(Xinha.is_ie?this.createRange(e).parentElement():this.createRange(e).commonAncestorContainer)}catch(b){return null}}if(typeof d=="string"){d=[d]}while(c){if(c.nodeType==1){if(d===null){return c}for(var a=0;a<d.length;++a){if(typeof d[a]=="string"&&d[a]==c.tagName.toLowerCase()){return c}else{if(typeof d[a]=="function"&&d[a](this,c)){return c}}}if(c.tagName.toLowerCase()=="body"){break}if(c.tagName.toLowerCase()=="table"){break}}c=c.parentNode}return null};Xinha.prototype._getAncestorBlock=function(b){var a=(Xinha.is_ie?this.createRange(b).parentElement:this.createRange(b).commonAncestorContainer);while(a&&(a.nodeType==1)){switch(a.tagName.toLowerCase()){case"div":case"p":case"address":case"blockquote":case"center":case"del":case"ins":case"pre":case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":case"h7":return a;case"body":case"noframes":case"dd":case"li":case"th":case"td":case"noscript":return null;default:break}}return null};Xinha.prototype._createImplicitBlock=function(b){var c=this.getSelection();if(Xinha.is_ie){c.empty()}else{c.collapseToStart()}var a=this.createRange(c)};Xinha.prototype.surroundHTML=function(c,a){var b=this.getSelectedHTML();this.insertHTML(c+b+a)};Xinha.prototype.hasSelectedText=function(){return this.getSelectedHTML()!==""};Xinha.prototype._comboSelected=function(b,a){this.focusEditor();var c=b.options[b.selectedIndex].value;switch(a){case"fontname":case"fontsize":this.execCommand(a,false,c);break;case"formatblock":if(!c){this.updateToolbar();break}if(!Xinha.is_gecko||c!=="blockquote"){c="<"+c+">"}this.execCommand(a,false,c);break;default:var d=this.config.customSelects[a];if(typeof d!="undefined"){d.action(this,c,b,a)}else{alert("FIXME: combo box "+a+" not implemented")}break}};Xinha.prototype._colorSelector=function(h){var d=this;if(Xinha.is_gecko){try{d._doc.execCommand("useCSS",false,false);d._doc.execCommand("styleWithCSS",false,true)}catch(g){}}var f=d._toolbarObjects[h].element;var c;if(h=="hilitecolor"){if(Xinha.is_ie){h="backcolor";c=Xinha._colorToRgb(d._doc.queryCommandValue("backcolor"))}else{c=Xinha._colorToRgb(d._doc.queryCommandValue("hilitecolor"))}}else{c=Xinha._colorToRgb(d._doc.queryCommandValue("forecolor"))}var b=function(i){d._doc.execCommand(h,false,i)};if(Xinha.is_ie){var a=d.createRange(d.getSelection());b=function(i){a.select();d._doc.execCommand(h,false,i)}}var e=new Xinha.colorPicker({cellsize:d.config.colorPickerCellSize,callback:b,granularity:d.config.colorPickerGranularity,websafe:d.config.colorPickerWebSafe,savecolors:d.config.colorPickerSaveColors});e.open(d.config.colorPickerPosition,f,c)};Xinha.prototype.execCommand=function(h,f,g){var a=this;this.focusEditor();h=h.toLowerCase();if(this.firePluginEvent("onExecCommand",h,f,g)){this.updateToolbar();return false}switch(h){case"htmlmode":this.setMode();break;case"hilitecolor":case"forecolor":this._colorSelector(h);break;case"createlink":this._createLink();break;case"undo":case"redo":if(this._customUndo){this[h]()}else{this._doc.execCommand(h,f,g)}break;case"inserttable":this._insertTable();break;case"insertimage":this._insertImage();break;case"showhelp":this._popupDialog(a.config.URIs.help,null,this);break;case"killword":this._wordClean();break;case"cut":case"copy":case"paste":this._doc.execCommand(h,f,g);if(this.config.killWordOnPaste){this._wordClean()}break;case"lefttoright":case"righttoleft":if(this.config.changeJustifyWithDirection){this._doc.execCommand((h=="righttoleft")?"justifyright":"justifyleft",f,g)}var b=(h=="righttoleft")?"rtl":"ltr";var e=this.getParentElement();while(e&&!Xinha.isBlockElement(e)){e=e.parentNode}if(e){if(e.style.direction==b){e.style.direction=""}else{e.style.direction=b}}break;case"justifyleft":case"justifyright":h.match(/^justify(.*)$/);var d=this.activeElement(this.getSelection());if(d&&d.tagName.toLowerCase()=="img"){d.align=d.align==RegExp.$1?"":RegExp.$1}else{this._doc.execCommand(h,f,g)}break;default:try{this._doc.execCommand(h,f,g)}catch(c){if(this.config.debug){alert(c+"\\n\\nby execCommand("+h+");")}}break}this.updateToolbar();return false};Xinha.prototype._editorEvent=function(b){var a=this;if(typeof a._textArea["on"+b.type]=="function"){a._textArea["on"+b.type](b)}if(this.isKeyEvent(b)){if(a.firePluginEvent("onKeyPress",b)){return false}if(this.isShortCut(b)){this._shortCuts(b)}}if(b.type=="mousedown"){if(a.firePluginEvent("onMouseDown",b)){return false}}if(a._timerToolbar){clearTimeout(a._timerToolbar)}if(!this.suspendUpdateToolbar){a._timerToolbar=setTimeout(function(){a.updateToolbar();a._timerToolbar=null},250)}};Xinha.prototype._onDoubleClick=function(d){var c=this;var e=Xinha.is_ie?d.srcElement:d.target;var a=e.tagName;var b=e.className;if(a){a=a.toLowerCase();if(b&&(this.config.dblclickList[a+"."+b]!=undefined)){this.config.dblclickList[a+"."+b][0](c,e)}else{if(this.config.dblclickList[a]!=undefined){this.config.dblclickList[a][0](c,e)}}}};Xinha.prototype._shortCuts=function(b){var a=this.getKey(b).toLowerCase();var d=null;var c=null;switch(a){case"b":d="bold";break;case"i":d="italic";break;case"u":d="underline";break;case"s":d="strikethrough";break;case"l":d="justifyleft";break;case"e":d="justifycenter";break;case"r":d="justifyright";break;case"j":d="justifyfull";break;case"z":d="undo";break;case"y":d="redo";break;case"v":d="paste";break;case"n":d="formatblock";c="p";break;case"0":d="killword";break;case"1":case"2":case"3":case"4":case"5":case"6":d="formatblock";c="h"+a;break}if(d){this.execCommand(d,false,c);Xinha._stopEvent(b)}};Xinha.prototype.convertNode=function(a,c){var b=this._doc.createElement(c);while(a.firstChild){b.appendChild(a.firstChild)}return b};Xinha.prototype.scrollToElement=function(b){if(!b){b=this.getParentElement();if(!b){return}}var a=Xinha.getElementTopLeft(b);this._iframe.contentWindow.scrollTo(a.left,a.top)};Xinha.prototype.getEditorContent=function(){return this.outwardHtml(this.getHTML())};Xinha.prototype.setEditorContent=function(a){this.setHTML(this.inwardHtml(a))};Xinha.updateTextareas=function(){var b;for(var a=0;a<__xinhas.length;a++){b=__xinhas[a];b._textArea.value=b.getEditorContent()}};Xinha.prototype.getHTML=function(){var a="";switch(this._editMode){case"wysiwyg":if(!this.config.fullPage){a=Xinha.getHTML(this._doc.body,false,this).trim()}else{a=this.doctype+"\\n"+Xinha.getHTML(this._doc.documentElement,true,this)}break;case"textmode":a=this._textArea.value;break;default:alert("Mode <"+this._editMode+"> not defined!");return false}return a};Xinha.prototype.outwardHtml=function(d){for(var c in this.plugins){var a=this.plugins[c].instance;if(a&&typeof a.outwardHtml=="function"){d=a.outwardHtml(d)}}d=d.replace(/<(\\/?)b(\\s|>|\\/)/ig,"<$1strong$2");d=d.replace(/<(\\/?)i(\\s|>|\\/)/ig,"<$1em$2");d=d.replace(/<(\\/?)strike(\\s|>|\\/)/ig,"<$1del$2");d=d.replace(/(<[^>]*on(click|mouse(over|out|up|down))=[\'"])if\\(window\\.parent &amp;&amp; window\\.parent\\.Xinha\\)\\{return false\\}/gi,"$1");var b=location.href.replace(/(https?:\\/\\/[^\\/]*)\\/.*/,"$1")+"/";d=d.replace(/https?:\\/\\/null\\//g,b);d=d.replace(/((href|src|background)=[\\\'\\"])\\/+/ig,"$1"+b);d=this.outwardSpecialReplacements(d);d=this.fixRelativeLinks(d);if(this.config.sevenBitClean){d=d.replace(/[^ -~\\r\\n\\t]/g,function(e){return(e!=Xinha.cc)?"&#"+e.charCodeAt(0)+";":e})}d=d.replace(/(<script[^>]*((type=[\\"\\\']text\\/)|(language=[\\"\\\'])))(freezescript)/gi,"$1javascript");if(this.config.fullPage){d=Xinha.stripCoreCSS(d)}if(typeof this.config.outwardHtml=="function"){d=this.config.outwardHtml(d)}return d};Xinha.prototype.inwardHtml=function(c){for(var b in this.plugins){var a=this.plugins[b].instance;if(a&&typeof a.inwardHtml=="function"){c=a.inwardHtml(c)}}c=c.replace(/<(\\/?)del(\\s|>|\\/)/ig,"<$1strike$2");c=c.replace(/(<[^>]*on(click|mouse(over|out|up|down))=["\'])/gi,"$1if(window.parent &amp;&amp; window.parent.Xinha){return false}");c=this.inwardSpecialReplacements(c);c=c.replace(/(<script[^>]*((type=[\\"\\\']text\\/)|(language=[\\"\\\'])))(javascript)/gi,"$1freezescript");var d=new RegExp("((href|src|background)=[\'\\"])/+","gi");c=c.replace(d,"$1"+location.href.replace(/(https?:\\/\\/[^\\/]*)\\/.*/,"$1")+"/");c=this.fixRelativeLinks(c);if(this.config.fullPage){c=Xinha.addCoreCSS(c)}if(typeof this.config.inwardHtml=="function"){c=this.config.inwardHtml(c)}return c};Xinha.prototype.outwardSpecialReplacements=function(b){for(var a in this.config.specialReplacements){var e=this.config.specialReplacements[a];var d=a;if(typeof e.replace!="function"||typeof d.replace!="function"){continue}var c=new RegExp(Xinha.escapeStringForRegExp(e),"g");b=b.replace(c,d.replace(/\\$/g,"$$$$"))}return b};Xinha.prototype.inwardSpecialReplacements=function(b){for(var a in this.config.specialReplacements){var e=a;var d=this.config.specialReplacements[a];if(typeof e.replace!="function"||typeof d.replace!="function"){continue}var c=new RegExp(Xinha.escapeStringForRegExp(e),"g");b=b.replace(c,d.replace(/\\$/g,"$$$$"))}return b};Xinha.prototype.fixRelativeLinks=function(f){if(typeof this.config.expandRelativeUrl!="undefined"&&this.config.expandRelativeUrl){if(f==null){return""}var c=f.match(/(src|href)="([^"]*)"/gi);var j=document.location.href;if(c){var d,l,k,m,h;for(var e=0;e<c.length;++e){d=c[e].match(/(src|href)="([^"]*)"/i);l=d[2].match(/\\.\\.\\//g);if(l){k=new RegExp("(.*?)(([^/]*/){"+l.length+"})[^/]*$");m=j.match(k);h=d[2].replace(/(\\.\\.\\/)*/,m[1]);f=f.replace(new RegExp(Xinha.escapeStringForRegExp(d[2])),h)}}}}if(typeof this.config.stripSelfNamedAnchors!="undefined"&&this.config.stripSelfNamedAnchors){var g=new RegExp(\'((href|src|background)=")(\'+Xinha.escapeStringForRegExp(window.unescape(document.location.href.replace(/&/g,"&amp;")))+")([#?][^\'\\" ]*)","g");f=f.replace(g,"$1$4")}if(typeof this.config.stripBaseHref!="undefined"&&this.config.stripBaseHref){var a=null;if(typeof this.config.baseHref!="undefined"&&this.config.baseHref!==null){a=new RegExp(\'((href|src|background|action)=")(\'+Xinha.escapeStringForRegExp(this.config.baseHref.replace(/([^\\/]\\/)(?=.+\\.)[^\\/]*$/,"$1"))+")","g");f=f.replace(a,"$1")}a=new RegExp(\'((href|src|background|action)=")(\'+Xinha.escapeStringForRegExp(document.location.href.replace(/^(https?:\\/\\/[^\\/]*)(.*)/,"$1"))+")","g");f=f.replace(a,"$1")}return f};Xinha.prototype.getInnerHTML=function(){if(!this._doc.body){return""}var a="";switch(this._editMode){case"wysiwyg":if(!this.config.fullPage){a=this._doc.body.innerHTML}else{a=this.doctype+"\\n"+this._doc.documentElement.innerHTML}break;case"textmode":a=this._textArea.value;break;default:alert("Mode <"+this._editMode+"> not defined!");return false}return a};Xinha.prototype.setHTML=function(a){if(!this.config.fullPage){this._doc.body.innerHTML=a}else{this.setFullHTML(a)}this._textArea.value=a};Xinha.prototype.setDoctype=function(a){this.doctype=a};Xinha._object=null;Array.prototype.isArray=true;RegExp.prototype.isRegExp=true;Xinha.cloneObject=function(obj){if(!obj){return null}var newObj=obj.isArray?[]:{};if(obj.constructor.toString().match(/\\s*function Function\\(/)||typeof obj=="function"){newObj=obj}else{if(obj.isRegExp){newObj=eval(obj.toString())}else{for(var n in obj){var node=obj[n];if(typeof node=="object"){newObj[n]=Xinha.cloneObject(node)}else{newObj[n]=node}}}}return newObj};Xinha.extend=function(a,c){function b(){}b.prototype=c.prototype;a.prototype=new b();a.prototype.constructor=a;a.parentConstructor=c;a.superClass=c.prototype};Xinha.flushEvents=function(){var a=0;var c=Xinha._eventFlushers.pop();while(c){try{if(c.length==3){Xinha._removeEvent(c[0],c[1],c[2]);a++}else{if(c.length==2){c[0]["on"+c[1]]=null;c[0]._xinha_dom0Events[c[1]]=null;a++}}}catch(b){}c=Xinha._eventFlushers.pop()}};Xinha._eventFlushers=[];if(document.addEventListener){Xinha._addEvent=function(b,a,c){b.addEventListener(a,c,false);Xinha._eventFlushers.push([b,a,c])};Xinha._removeEvent=function(b,a,c){b.removeEventListener(a,c,false)};Xinha._stopEvent=function(a){a.preventDefault();a.stopPropagation()}}else{if(document.attachEvent){Xinha._addEvent=function(b,a,c){b.attachEvent("on"+a,c);Xinha._eventFlushers.push([b,a,c])};Xinha._removeEvent=function(b,a,c){b.detachEvent("on"+a,c)};Xinha._stopEvent=function(b){try{b.cancelBubble=true;b.returnValue=false}catch(a){}}}else{Xinha._addEvent=function(b,a,c){alert("_addEvent is not supported")};Xinha._removeEvent=function(b,a,c){alert("_removeEvent is not supported")};Xinha._stopEvent=function(a){alert("_stopEvent is not supported")}}}Xinha._addEvents=function(c,a,d){for(var b=a.length;--b>=0;){Xinha._addEvent(c,a[b],d)}};Xinha._removeEvents=function(c,a,d){for(var b=a.length;--b>=0;){Xinha._removeEvent(c,a[b],d)}};Xinha.addOnloadHandler=function(b,a){a=a?a:window;var c=function(){if(arguments.callee.done){return}arguments.callee.done=true;if(Xinha.onloadTimer){clearInterval(Xinha.onloadTimer)}b()};if(Xinha.is_ie){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);c()}});if(document.documentElement.doScroll&&typeof window.frameElement==="undefined"){(function(){if(arguments.callee.done){return}try{document.documentElement.doScroll("left")}catch(d){setTimeout(arguments.callee,0);return}c()})()}}else{if(/applewebkit|KHTML/i.test(navigator.userAgent)){Xinha.onloadTimer=a.setInterval(function(){if(/loaded|complete/.test(a.document.readyState)){c()}},10)}else{a.document.addEventListener("DOMContentLoaded",c,false)}}Xinha._addEvent(a,"load",c)};Xinha.addDom0Event=function(b,c,a){Xinha._prepareForDom0Events(b,c);b._xinha_dom0Events[c].unshift(a)};Xinha.prependDom0Event=function(b,c,a){Xinha._prepareForDom0Events(b,c);b._xinha_dom0Events[c].push(a)};Xinha.getEvent=function(a){return a||window.event};Xinha._prepareForDom0Events=function(a,b){if(typeof a._xinha_dom0Events=="undefined"){a._xinha_dom0Events={};Xinha.freeLater(a,"_xinha_dom0Events")}if(typeof a._xinha_dom0Events[b]=="undefined"){a._xinha_dom0Events[b]=[];if(typeof a["on"+b]=="function"){a._xinha_dom0Events[b].push(a["on"+b])}a["on"+b]=function(e){var c=a._xinha_dom0Events[b];var f=true;for(var d=c.length;--d>=0;){a._xinha_tempEventHandler=c[d];if(a._xinha_tempEventHandler(e)===false){a._xinha_tempEventHandler=null;f=false;break}a._xinha_tempEventHandler=null}return f};Xinha._eventFlushers.push([a,b])}};Xinha.prototype.notifyOn=function(b,a){if(typeof this._notifyListeners[b]=="undefined"){this._notifyListeners[b]=[];Xinha.freeLater(this,"_notifyListeners")}this._notifyListeners[b].push(a)};Xinha.prototype.notifyOf=function(c,a){if(this._notifyListeners[c]){for(var b=0;b<this._notifyListeners[c].length;b++){this._notifyListeners[c][b](c,a)}}};Xinha._blockTags=" body form textarea fieldset ul ol dl li div p h1 h2 h3 h4 h5 h6 quote pre table thead tbody tfoot tr td th iframe address blockquote title meta link style head ";Xinha.isBlockElement=function(a){return a&&a.nodeType==1&&(Xinha._blockTags.indexOf(" "+a.tagName.toLowerCase()+" ")!=-1)};Xinha._paraContainerTags=" body td th caption fieldset div ";Xinha.isParaContainer=function(a){return a&&a.nodeType==1&&(Xinha._paraContainerTags.indexOf(" "+a.tagName.toLowerCase()+" ")!=-1)};Xinha._closingTags=" a abbr acronym address applet b bdo big blockquote button caption center cite code del dfn dir div dl em fieldset font form frameset h1 h2 h3 h4 h5 h6 i iframe ins kbd label legend map menu noframes noscript object ol optgroup pre q s samp script select small span strike strong style sub sup table textarea title tt u ul var ";Xinha.needsClosingTag=function(a){return a&&a.nodeType==1&&(Xinha._closingTags.indexOf(" "+a.tagName.toLowerCase()+" ")!=-1)};Xinha.htmlEncode=function(a){if(!a){return""}if(typeof a.replace=="undefined"){a=a.toString()}a=a.replace(/&/ig,"&amp;");a=a.replace(/</ig,"&lt;");a=a.replace(/>/ig,"&gt;");a=a.replace(/\\xA0/g,"&nbsp;");a=a.replace(/\\x22/g,"&quot;");return a};Xinha.prototype.stripBaseURL=function(b){if(this.config.baseHref===null||!this.config.stripBaseHref){return b}var c=this.config.baseHref.replace(/^(https?:\\/\\/[^\\/]+)(.*)$/,"$1");var a=new RegExp(c);return b.replace(a,"")};if(typeof String.prototype.trim!="function"){String.prototype.trim=function(){return this.replace(/^\\s+/,"").replace(/\\s+$/,"")}}Xinha._makeColor=function(c){if(typeof c!="number"){return c}var e=c&255;var d=(c>>8)&255;var a=(c>>16)&255;return"rgb("+e+","+d+","+a+")"};Xinha._colorToRgb=function(c){if(!c){return""}var h,f,a;function e(b){return(b<16)?("0"+b.toString(16)):b.toString(16)}if(typeof c=="number"){h=c&255;f=(c>>8)&255;a=(c>>16)&255;return"#"+e(h)+e(f)+e(a)}if(c.substr(0,3)=="rgb"){var d=/rgb\\s*\\(\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*\\)/;if(c.match(d)){h=parseInt(RegExp.$1,10);f=parseInt(RegExp.$2,10);a=parseInt(RegExp.$3,10);return"#"+e(h)+e(f)+e(a)}return null}if(c.substr(0,1)=="#"){return c}return null};Xinha.prototype._popupDialog=function(b,a,c){Dialog(this.popupURL(b),a,c)};Xinha.prototype.imgURL=function(b,a){if(typeof a=="undefined"){return _editor_url+b}else{return Xinha.getPluginDir(a)+"/img/"+b}};Xinha.prototype.popupURL=function(d){var c="";if(d.match(/^plugin:\\/\\/(.*?)\\/(.*)/)){var b=RegExp.$1;var a=RegExp.$2;if(!/\\.(html?|php)$/.test(a)){a+=".html"}c=Xinha.getPluginDir(b)+"/popups/"+a}else{if(d.match(/^\\/.*?/)||d.match(/^https?:\\/\\//)){c=d}else{c=_editor_url+this.config.popupURL+d}}return c};Xinha.getElementById=function(a,e){var c,b,d=document.getElementsByTagName(a);for(b=d.length;--b>=0&&(c=d[b]);){if(c.id==e){return c}}return null};Xinha.prototype._toggleBorders=function(){var a=this._doc.getElementsByTagName("TABLE");if(a.length!==0){if(!this.borders){this.borders=true}else{this.borders=false}for(var b=0;b<a.length;b++){if(this.borders){Xinha._addClass(a[b],"htmtableborders")}else{Xinha._removeClass(a[b],"htmtableborders")}}}return true};Xinha.addCoreCSS=function(b){var a=\'<style title="XinhaInternalCSS" type="text/css">.htmtableborders, .htmtableborders td, .htmtableborders th {border : 1px dashed lightgrey ! important;}\\nhtml, body { border: 0px; } \\nbody { background-color: #ffffff; } \\nimg, hr { cursor: default } \\n</style>\\n\';if(b&&/<head>/i.test(b)){return b.replace(/<head>/i,"<head>"+a)}else{if(b){return a+b}else{return a}}};Xinha.prototype.addEditorStylesheet=function(a){var b=this._doc.createElement("link");b.rel="stylesheet";b.type="text/css";b.title="XinhaInternalCSS";b.href=a;this._doc.getElementsByTagName("HEAD")[0].appendChild(b)};Xinha.stripCoreCSS=function(a){return a.replace(/<style[^>]+title="XinhaInternalCSS"(.|\\n)*?<\\/style>/ig,"").replace(/<link[^>]+title="XinhaInternalCSS"(.|\\n)*?>/ig,"")};Xinha._removeClass=function(e,c){if(!(e&&e.className)){return}var a=e.className.split(" ");var b=[];for(var d=a.length;d>0;){if(a[--d]!=c){b[b.length]=a[d]}}e.className=b.join(" ")};Xinha._addClass=function(b,a){Xinha._removeClass(b,a);b.className+=" "+a};Xinha.addClasses=function(g,e){if(g!==null){var f=g.className.trim().split(" ");var d=e.split(" ");for(var a=0;a<d.length;a++){var b=false;for(var c=0;b===false&&c<f.length;c++){if(f[c]==d[a]){b=true}}if(b===false){f[f.length]=d[a]}}g.className=f.join(" ").trim()}};Xinha.removeClasses=function(e,d){var b=e.className.trim().split();var f=[];var h=d.trim().split();for(var c=0;c<b.length;c++){var g=false;for(var a=0;a<h.length&&!g;a++){if(b[c]==h[a]){g=true}}if(!g){f[f.length]=b[c]}}return f.join(" ")};Xinha.addClass=Xinha._addClass;Xinha.removeClass=Xinha._removeClass;Xinha._addClasses=Xinha.addClasses;Xinha._removeClasses=Xinha.removeClasses;Xinha._hasClass=function(d,b){if(!(d&&d.className)){return false}var a=d.className.split(" ");for(var c=a.length;c>0;){if(a[--c]==b){return true}}return false};Xinha._postback_send_charset=true;Xinha._postback=function(b,g,h,d){var f=null;f=Xinha.getXMLHTTPRequestObject();var e="";if(typeof g=="string"){e=g}else{if(typeof g=="object"){for(var c in g){e+=(e.length?"&":"")+c+"="+encodeURIComponent(g[c])}}}function a(){if(f.readyState==4){if(((f.status/100)==2)||Xinha.isRunLocally&&f.status===0){if(typeof h=="function"){h(f.responseText,f)}}else{if(Xinha._postback_send_charset){Xinha._postback_send_charset=false;Xinha._postback(b,g,h,d)}else{if(typeof d=="function"){d(f)}else{alert("An error has occurred: "+f.statusText+"\\nURL: "+b)}}}}}f.onreadystatechange=a;f.open("POST",b,true);f.setRequestHeader("Content-Type","application/x-www-form-urlencoded"+(Xinha._postback_send_charset?"; charset=UTF-8":""));f.send(e)};Xinha._getback=function(b,e,c){var d=null;d=Xinha.getXMLHTTPRequestObject();function a(){if(d.readyState==4){if(((d.status/100)==2)||Xinha.isRunLocally&&d.status===0){e(d.responseText,d)}else{if(typeof c=="function"){c(d)}else{alert("An error has occurred: "+d.statusText+"\\nURL: "+b)}}}}d.onreadystatechange=a;d.open("GET",b,true);d.send(null)};Xinha.ping=function(d,c,b){var e=null;e=Xinha.getXMLHTTPRequestObject();function a(){if(e.readyState==4){if(((e.status/100)==2)||Xinha.isRunLocally&&e.status===0){if(c){c(e)}}else{if(b){b(e)}}}}var f="GET";e.onreadystatechange=a;e.open(f,d,true);e.send(null)};Xinha._geturlcontent=function(a,c){var b=null;b=Xinha.getXMLHTTPRequestObject();b.open("GET",a,false);b.send(null);if(((b.status/100)==2)||Xinha.isRunLocally&&b.status===0){return(c)?b.responseXML:b.responseText}else{return""}};if(typeof dumpValues=="undefined"){dumpValues=function(c){var b="";for(var d in c){if(window.console&&typeof window.console.log=="function"){if(typeof console.firebug!="undefined"){console.log(c)}else{console.log(d+" = "+c[d]+"\\n")}}else{b+=d+" = "+c[d]+"\\n"}}if(b){if(document.getElementById("errors")){document.getElementById("errors").value+=b}else{var a=window.open("","debugger");a.document.write("<pre>"+b+"</pre>")}}}}if(!Array.prototype.contains){Array.prototype.contains=function(c){var b=this;for(var a=0;a<b.length;a++){if(c==b[a]){return true}}return false}}if(!Array.prototype.indexOf){Array.prototype.indexOf=function(c){var b=this;for(var a=0;a<b.length;a++){if(c==b[a]){return a}}return null}}if(!Array.prototype.append){Array.prototype.append=function(b){for(var c=0;c<b.length;c++){this.push(b[c])}return this}}if(!Array.prototype.forEach){Array.prototype.forEach=function(d){var a=this.length;if(typeof d!="function"){throw new TypeError()}var c=arguments[1];for(var b=0;b<a;b++){if(b in this){d.call(c,this[b],b,this)}}}}Xinha.getElementsByClassName=function(d,a){if(d.getElementsByClassName){return Array.prototype.slice.call(d.getElementsByClassName(a))}else{var c=d.getElementsByTagName("*");var e=[];var f;for(var b=0;b<c.length;b++){f=c[b].className.split(" ");if(f.contains(a)){e.push(c[b])}}return e}};Xinha.arrayContainsArray=function(c,b){var e=true;for(var a=0;a<b.length;a++){var f=false;for(var d=0;d<c.length;d++){if(c[d]==b[a]){f=true;break}}if(!f){e=false;break}}return e};Xinha.arrayFilter=function(c,b){var d=[];for(var a=0;a<c.length;a++){if(b(c[a])){d[d.length]=c[a]}}return d};Xinha.collectionToArray=function(c){try{return c.length?Array.prototype.slice.call(c):[]}catch(b){}var d=[];for(var a=0;a<c.length;a++){d.push(c.item(a))}return d};Xinha.uniq_count=0;Xinha.uniq=function(a){return a+Xinha.uniq_count++};Xinha._loadlang=function(context,url){var lang;if(typeof _editor_lcbackend=="string"){url=_editor_lcbackend;url=url.replace(/%lang%/,_editor_lang);url=url.replace(/%context%/,context)}else{if(!url){if(context!="Xinha"){url=Xinha.getPluginDir(context)+"/lang/"+_editor_lang+".js"}else{Xinha.setLoadingMessage("Loading language");url=_editor_url+"lang/"+_editor_lang+".js"}}}var langData=Xinha._geturlcontent(url);if(langData!==""){try{eval("lang = "+langData)}catch(ex){alert("Error reading Language-File ("+url+"):\\n"+Error.toString());lang={}}}else{lang={}}return lang};Xinha._lc=function(d,b,c){var a,h;if(typeof b=="object"&&b.url&&b.context){a=b.url+_editor_lang+".js";b=b.context}var f=null;if(typeof d=="string"){f=d.match(/\\$(.*?)=(.*?)\\$/g)}if(f){if(!c){c={}}for(var g=0;g<f.length;g++){var e=f[g].match(/\\$(.*?)=(.*?)\\$/);c[e[1]]=e[2];d=d.replace(e[0],"$"+e[1])}}if(_editor_lang=="en"){if(typeof d=="object"&&d.string){h=d.string}else{h=d}}else{if(typeof Xinha._lc_catalog=="undefined"){Xinha._lc_catalog=[]}if(typeof b=="undefined"){b="Xinha"}if(typeof Xinha._lc_catalog[b]=="undefined"){Xinha._lc_catalog[b]=Xinha._loadlang(b,a)}var j;if(typeof d=="object"&&d.key){j=d.key}else{if(typeof d=="object"&&d.string){j=d.string}else{j=d}}if(typeof Xinha._lc_catalog[b][j]=="undefined"){if(b=="Xinha"){if(typeof d=="object"&&d.string){h=d.string}else{h=d}}else{return Xinha._lc(d,"Xinha",c)}}else{h=Xinha._lc_catalog[b][j]}}if(typeof d=="object"&&d.replace){c=d.replace}if(typeof c!="undefined"){for(g in c){h=h.replace("$"+g,c[g])}}return h};Xinha.hasDisplayedChildren=function(c){var b=c.childNodes;for(var a=0;a<b.length;a++){if(b[a].tagName){if(b[a].style.display!="none"){return true}}}return false};Xinha._loadback=function(a,e,d,f){if(document.getElementById(a)){return true}var b=!Xinha.is_ie?"onload":"onreadystatechange";var c=document.createElement("script");c.type="text/javascript";c.src=a;c.id=a;if(e){c[b]=function(){if(Xinha.is_ie&&(!/loaded|complete/.test(window.event.srcElement.readyState))){return}e.call(d?d:this,f);c[b]=null}}document.getElementsByTagName("head")[0].appendChild(c);return false};Xinha.makeEditors=function(d,f,g){if(!Xinha.isSupportedBrowser){return}if(typeof f=="function"){f=f()}var b={};var e;for(var a=0;a<d.length;a++){if(typeof d[a]=="string"){e=Xinha.getElementById("textarea",d[a]);if(!e){d[a]=null;continue}}else{if(typeof d[a]=="object"&&d[a].tagName&&d[a].tagName.toLowerCase()=="textarea"){e=d[a];if(!e.id){e.id="xinha_id_"+a}}}var c=new Xinha(e,Xinha.cloneObject(f));c.registerPlugins(g);b[e.id]=c}return b};Xinha.startEditors=function(a){if(!Xinha.isSupportedBrowser){return}for(var b in a){if(a[b].generate){a[b].generate()}}};Xinha.prototype.registerPlugins=function(b){if(!Xinha.isSupportedBrowser){return}if(b){for(var a=0;a<b.length;a++){this.setLoadingMessage(Xinha._lc("Register plugin $plugin","Xinha",{plugin:b[a]}));this.registerPlugin(b[a])}}};Xinha.base64_encode=function(d){var c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var b="";var k,h,g;var l,j,f,e;var a=0;do{k=d.charCodeAt(a++);h=d.charCodeAt(a++);g=d.charCodeAt(a++);l=k>>2;j=((k&3)<<4)|(h>>4);f=((h&15)<<2)|(g>>6);e=g&63;if(isNaN(h)){f=e=64}else{if(isNaN(g)){e=64}}b=b+c.charAt(l)+c.charAt(j)+c.charAt(f)+c.charAt(e)}while(a<d.length);return b};Xinha.base64_decode=function(d){var c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var b="";var k,h,g;var l,j,f,e;var a=0;d=d.replace(/[^A-Za-z0-9\\+\\/\\=]/g,"");do{l=c.indexOf(d.charAt(a++));j=c.indexOf(d.charAt(a++));f=c.indexOf(d.charAt(a++));e=c.indexOf(d.charAt(a++));k=(l<<2)|(j>>4);h=((j&15)<<4)|(f>>2);g=((f&3)<<6)|e;b=b+String.fromCharCode(k);if(f!=64){b=b+String.fromCharCode(h)}if(e!=64){b=b+String.fromCharCode(g)}}while(a<d.length);return b};Xinha.removeFromParent=function(b){if(!b.parentNode){return}var a=b.parentNode;return a.removeChild(b)};Xinha.hasParentNode=function(a){if(a.parentNode){if(a.parentNode.nodeType==11){return false}return true}return false};Xinha.viewportSize=function(b){b=(b)?b:window;var a,c;if(b.innerHeight){a=b.innerWidth;c=b.innerHeight}else{if(b.document.documentElement&&b.document.documentElement.clientHeight){a=b.document.documentElement.clientWidth;c=b.document.documentElement.clientHeight}else{if(b.document.body){a=b.document.body.clientWidth;c=b.document.body.clientHeight}}}return{x:a,y:c}};Xinha.pageSize=function(d){d=(d)?d:window;var a,e;var c=d.document.body.scrollHeight;var b=d.document.documentElement.scrollHeight;if(c>b){a=d.document.body.scrollWidth;e=d.document.body.scrollHeight}else{a=d.document.documentElement.scrollWidth;e=d.document.documentElement.scrollHeight}return{x:a,y:e}};Xinha.prototype.scrollPos=function(b){b=(b)?b:window;var a,c;if(typeof b.pageYOffset!="undefined"){a=b.pageXOffset;c=b.pageYOffset}else{if(b.document.documentElement&&typeof document.documentElement.scrollTop!="undefined"){a=b.document.documentElement.scrollLeft;c=b.document.documentElement.scrollTop}else{if(b.document.body){a=b.document.body.scrollLeft;c=b.document.body.scrollTop}}}return{x:a,y:c}};Xinha.getElementTopLeft=function(b){var c=0;var a=0;if(b.offsetParent){c=b.offsetLeft;a=b.offsetTop;while(b=b.offsetParent){c+=b.offsetLeft;a+=b.offsetTop}}return{top:a,left:c}};Xinha.findPosX=function(a){var b=0;if(a.offsetParent){return Xinha.getElementTopLeft(a).left}else{if(a.x){b+=a.x}}return b};Xinha.findPosY=function(b){var a=0;if(b.offsetParent){return Xinha.getElementTopLeft(b).top}else{if(b.y){a+=b.y}}return a};Xinha.createLoadingMessages=function(b){if(Xinha.loadingMessages||!Xinha.isSupportedBrowser){return}Xinha.loadingMessages=[];for(var a=0;a<b.length;a++){if(!document.getElementById(b[a])){continue}Xinha.loadingMessages.push(Xinha.createLoadingMessage(Xinha.getElementById("textarea",b[a])))}};Xinha.createLoadingMessage=function(d,e){if(document.getElementById("loading_"+d.id)||!Xinha.isSupportedBrowser){return}var a=document.createElement("div");a.id="loading_"+d.id;a.className="loading";a.style.left=(Xinha.findPosX(d)+d.offsetWidth/2)-106+"px";a.style.top=(Xinha.findPosY(d)+d.offsetHeight/2)-50+"px";var b=document.createElement("div");b.className="loading_main";b.id="loading_main_"+d.id;b.appendChild(document.createTextNode(Xinha._lc("Loading in progress. Please wait!")));var c=document.createElement("div");c.className="loading_sub";c.id="loading_sub_"+d.id;e=e?e:Xinha._lc("Loading Core");c.appendChild(document.createTextNode(e));a.appendChild(b);a.appendChild(c);document.body.appendChild(a);Xinha.freeLater(a);Xinha.freeLater(b);Xinha.freeLater(c);return c};Xinha.prototype.setLoadingMessage=function(b,a){if(!document.getElementById("loading_sub_"+this._textArea.id)){return}document.getElementById("loading_main_"+this._textArea.id).innerHTML=a?a:Xinha._lc("Loading in progress. Please wait!");document.getElementById("loading_sub_"+this._textArea.id).innerHTML=b};Xinha.setLoadingMessage=function(b){if(!Xinha.loadingMessages){return}for(var a=0;a<Xinha.loadingMessages.length;a++){Xinha.loadingMessages[a].innerHTML=b}};Xinha.prototype.removeLoadingMessage=function(){if(document.getElementById("loading_"+this._textArea.id)){document.body.removeChild(document.getElementById("loading_"+this._textArea.id))}};Xinha.removeLoadingMessages=function(c){for(var b=0;b<c.length;b++){if(!document.getElementById(c[b])){continue}var a=document.getElementById("loading_"+document.getElementById(c[b]).id);a.parentNode.removeChild(a)}Xinha.loadingMessages=null};Xinha.toFree=[];Xinha.freeLater=function(a,b){Xinha.toFree.push({o:a,p:b})};Xinha.free=function(c,d){if(c&&!d){for(var b in c){Xinha.free(c,b)}}else{if(c){if(d.indexOf("src")==-1){try{c[d]=null}catch(a){}}}}};Xinha.collectGarbageForIE=function(){Xinha.flushEvents();for(var a=0;a<Xinha.toFree.length;a++){Xinha.free(Xinha.toFree[a].o,Xinha.toFree[a].p);Xinha.toFree[a].o=null}};Xinha.prototype.insertNodeAtSelection=function(a){Xinha.notImplemented("insertNodeAtSelection")};Xinha.prototype.getParentElement=function(a){Xinha.notImplemented("getParentElement")};Xinha.prototype.activeElement=function(a){Xinha.notImplemented("activeElement")};Xinha.prototype.selectionEmpty=function(a){Xinha.notImplemented("selectionEmpty")};Xinha.prototype.saveSelection=function(){Xinha.notImplemented("saveSelection")};Xinha.prototype.restoreSelection=function(a){Xinha.notImplemented("restoreSelection")};Xinha.prototype.selectNodeContents=function(a,b){Xinha.notImplemented("selectNodeContents")};Xinha.prototype.insertHTML=function(a){Xinha.notImplemented("insertHTML")};Xinha.prototype.getSelectedHTML=function(){Xinha.notImplemented("getSelectedHTML")};Xinha.prototype.getSelection=function(){Xinha.notImplemented("getSelection")};Xinha.prototype.createRange=function(a){Xinha.notImplemented("createRange")};Xinha.prototype.isKeyEvent=function(a){Xinha.notImplemented("isKeyEvent")};Xinha.prototype.isShortCut=function(a){if(a.ctrlKey&&!a.altKey){return true}return false};Xinha.prototype.getKey=function(a){Xinha.notImplemented("getKey")};Xinha.getOuterHTML=function(a){Xinha.notImplemented("getOuterHTML")};Xinha.getXMLHTTPRequestObject=function(){try{if(typeof XMLHttpRequest!="undefined"&&typeof XMLHttpRequest.constructor=="function"){return new XMLHttpRequest()}else{if(typeof ActiveXObject=="function"){return new ActiveXObject("Microsoft.XMLHTTP")}}}catch(a){Xinha.notImplemented("getXMLHTTPRequestObject")}};Xinha.prototype._activeElement=function(a){return this.activeElement(a)};Xinha.prototype._selectionEmpty=function(a){return this.selectionEmpty(a)};Xinha.prototype._getSelection=function(){return this.getSelection()};Xinha.prototype._createRange=function(a){return this.createRange(a)};HTMLArea=Xinha;Xinha.init();if(Xinha.ie_version<8){Xinha.addDom0Event(window,"unload",Xinha.collectGarbageForIE)}Xinha.debugMsg=function(a,b){if(typeof console!="undefined"&&typeof console.log=="function"){if(b&&b=="warn"&&typeof console.warn=="function"){console.warn(a)}else{if(b&&b=="info"&&typeof console.info=="function"){console.info(a)}else{console.log(a)}}}else{if(typeof opera!="undefined"&&typeof opera.postError=="function"){opera.postError(a)}}};Xinha.notImplemented=function(a){throw new Error("Method Not Implemented","Part of Xinha has tried to call the "+a+" method which has not been implemented.")};
 
 ]]></string> </value>
         </item>
diff --git a/bt5/erp5_xinha_editor/bt/revision b/bt5/erp5_xinha_editor/bt/revision
index c7930257df..301160a930 100644
--- a/bt5/erp5_xinha_editor/bt/revision
+++ b/bt5/erp5_xinha_editor/bt/revision
@@ -1 +1 @@
-7
\ No newline at end of file
+8
\ No newline at end of file
-- 
2.30.9