<!--
 $Source: /home/cvs/cvsroot/cms/integration/web/components/editor/editor.htc,v $
 $Author: mami $
 $Revision: 1.38 $
 $Date: 2010/01/27 00:45:02 $
-->

<html>
<head>

<public:component tagname="editor" literalcontent="true">
  <public:attach event="oncontentready" onevent="initEditor()" />
  <public:attach event="ondocumentready" onevent="initForm()" />
  <public:attach event="onfocus" onevent="doFocus()" />
  <public:attach event="onkeydown" onevent="doKeyDownAttach()" />
  <public:method name="save" internalname="doSave" />
  <public:method name="refresh" internalname="refreshVisualEditor" />
  <public:method name="hideSavePopup" internalname="hideSavePopup" />
  <public:method name="replace" internalname="doReplace" />
  <public:method name="search" internalname="doSearch" />
  <public:method name="startSearch" internalname="startSearch" />
  <public:method name="setProperty" internalname="setProperty" />
  <public:method name="getFormElements" internalname="getFormElements" />
  <public:method name="registerComponentType" 
                 internalname="registerComponentType" />
  <public:method name="loadComponent" internalname="loadComponent" />
  <public:method name="doEditSource" internalname="doEditSource" />
  <public:method name="doInsertComponent" internalname="doInsertComponent" />
  <public:method name="doFormElement" internalname="doFormElement" />
  <public:method name="doFormElementInsert" internalname="doFormElementInsert" />
  <public:method name="menuFormProperties" internalname="menuFormProperties" />
  <public:method name="doInsertLink" internalname="doInsertLink" />
  <public:method name="menuLinkProperties" internalname="menuLinkProperties" />
  <public:property name="textElement" get="getTextElement" />
  <public:property name="height" put="setHeight" get="getHeight" />
  <public:property name="value" put="setValue" get="getValue" />
  <public:property name="styleSheet" put="setStyleSheet" />
  <public:property name="pageURL" put="setPageURL" />
  <public:property name="subsiteID" put="setSubsiteID" />
  <public:property name="folderID" put="setFolderID" />
  <public:property name="itemID" put="setItemID" />
  <public:property name="typeID" put="setTypeID" />
  <public:property name="formID" put="setFormID" />
  <public:property name="isModified" get="isModifiedGet" put="isModifiedPut"/>
  <public:property name="config" put="setConfiguration" />
  <public:property name="mode" put="setMode" />
  <public:property name="convertStyles" put="setConvertStyles" />
  <public:property name="insertFormElementState" put="setInsertFormElementState" />
  <public:property name="isRTF" put="setIsRTF" />
  <public:event name="onsave" id="saveEventID" />
  <public:event name="oninit" id="initEventID" />
</public:component>

<link rel="stylesheet" type="text/css" href="/components/toolbar/toolbar.css">

<style>
  #visualContainer {
    border-style:solid; 
    border-color:#cccccc;
    border-width:1px;
    position:relative; 
    height:100%; 
    top:0;
  }

  .frontleaf-editor {
    border:1px solid #cccccc; 
    position:relative; 
  }

  #sourceEditor {
    background-color:white; 
    overflow:scroll;
    position:relative;
    height:100%;
    width:100%;
    padding:6;
    border:0 none;
    border-collapse:collapse;
    border-spacing:0;
  }

  #visualEditor {
    background-color:white;
    overflow:scroll; 
    width:100%;
    height:100%;
    position:relative;
    padding:6;
    margin-top:2;
  }

  .visualEditor {
    position:relative;
    height:400px;
    padding:6;
    margin-top:2;
    overflow:auto; 
  }

  #visualEditor table {
    border-collapse:collapse;
  }

  #visualEditor a {
    border-bottom:expression(this.name ? "1 dashed black" : "0 none");
  }

  #visualEditor td {
    border: dotted 1 #999999;
  }
</style>

<script>
  var BASE_URL = "/components/";
  var EDITOR_URL = BASE_URL + "editor/";
  var EDITOR_IMG_URL = EDITOR_URL + "buttons/";
  var EDITOR_SC_IMG_URL = EDITOR_URL + "special-characters/";
  var EDITOR_FORM_IMG_URL = "/assets/icons/16x16/form/";
  var POPUP_URL = BASE_URL + "popmenu/";
  var POPUP_IMG_URL = POPUP_URL + "images/";

  var TOOLBARS = new Array();
  var COMPONENTS = new Array();

  var FORM_ACTION_ELEMENT = "formActions";

  var contextElements = new Array();
  contextElements["TD"] = true;
  contextElements["TH"] = true;
  contextElements["IMG"] = true;
  contextElements["INPUT"] = true;
  contextElements["TEXTAREA"] = true;
  contextElements["SELECT"] = true;
  contextElements["A"] = true;
  contextElements["P"] = true;
</script>

<script src="/components/x-browser.js"></script>
<script src="/components/editor/fonts.js"></script>
<script src="/components/editor/commands.js"></script>
<script src="/components/popmenu/popmenu-ie.js"></script>
<script src="/components/editor/dom.js"></script>
<script src="/components/editor/colors.js"></script>
<script src="/components/editor/special-characters.js"></script>
<script src="/components/table/table.js"></script>
<script src="/components/toolbar/toolbar.js"></script>
<script src="/components/rpc/rpc.js"></script>

<script>
  element.style.display = "block";

  var gMode = "html";
  var gPageURL = "";
  var gTypeID = 0;
  var gItemID = 0;
  var gFolderID = 0;
  var gSubsiteID = 0;
  var gToolbars = new Array();
  var gProperties = new Array();
  var gStyleSheets = new Array();

  var gCursorElements = new Object();

  var gIsFormEditor = false;
  var gFormID = null;
  var gFormActionElement = null;
  var gMenuSelection = null;
  var gLinkElement = null;
  var gMenuElement = null;
  var gContextElement = null;
  var gMenuX = null;
  var gMenuY = null;
  var gIsRTF = null;

  var gLastUndoTyping = false;

  var gIsInitialized = false;
  var gNeedFocus = false;
  var gNoCollapse = false;
  var gRefreshComponent = false;
  var gFormElement;
  var gConfig = "full";
  var gConvertStyles = true;
  var gConvertStatus = "NONE";

  var originalHashValue = 0;
  var originalLength = 0;
  var gCommandPopup;
  var gSavePopup;
  var gCancelKey;

  var gDisableFormElementInsert = false;
  var gRemoveFormElementInsert = false;

  // var bugWin = window.open("", "debug", 
  //  "resizable=yes,scrollbars=yes,width=200,height=600");

  // flag for removing font element when setting back to default (IE hack)
  var gClearFont = false;

  var editorMenu = 
    new PopupMenu("editorMenu", POPUP_IMG_URL, element.document);
  window.editorMenu = editorMenu;

  TOOLBARS["basic"] = [
    "Cut Copy Paste | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | SelectAll RemoveFormat | EditSource"
  ];

  TOOLBARS["basicwithchoosers"] = [
    "Cut Copy Paste | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertImage InsertLink | SelectAll RemoveFormat | EditSource"
  ];

  TOOLBARS["intermediate"] = [
    "Cut Copy Paste | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertLink | EditSource",
    "FontName FontSize | ForeColor | SelectAll RemoveFormat"
  ];

  TOOLBARS["semiadvanced"] = [
    "Cut Copy Paste Find | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertImage AttachFile InsertLink CreateBookmark FolderTree | EditSource",
    "JustifyLeft JustifyCenter JustifyRight | FormatBlock FontName FontSize | InsertTable | ForeColor InsertHorizontalRule InsertBreak SpecialCharacter | SelectAll RemoveFormat"
  ];

  TOOLBARS["advanced"] = [
    "Open | Cut Copy Paste Spell Find | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertImage AttachFile InsertLink CreateBookmark InsertComponent FolderTree | EditSource",
    "JustifyLeft JustifyCenter JustifyRight | FormatBlock FontName FontSize | InsertTable InsertFormElement | ForeColor InsertHorizontalRule InsertBreak SpecialCharacter | SelectAll RemoveFormat"
  ];

  TOOLBARS["full"] = [
    "Open Save | Cut Copy Paste Spell Find | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertImage AttachFile InsertLink CreateBookmark InsertComponent FolderTree | EditSource",
    "JustifyLeft JustifyCenter JustifyRight | FormatBlock FontName FontSize | InsertTable InsertFormElement | ForeColor InsertHorizontalRule InsertBreak SpecialCharacter | SelectAll RemoveFormat"
  ];

  TOOLBARS["noform"] = [
    "Open Save | Cut Copy Paste Spell Find | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertImage AttachFile InsertLink CreateBookmark InsertComponent FolderTree | EditSource",
    "JustifyLeft JustifyCenter JustifyRight | FormatBlock FontName FontSize | InsertTable | ForeColor InsertHorizontalRule InsertBreak SpecialCharacter | SelectAll RemoveFormat"
  ];

  TOOLBARS["standalone"] = [
    "Cut Copy Paste | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertHorizontalRule InsertBreak | InsertLink CreateBookmark | EditSource",
    "JustifyLeft JustifyCenter JustifyRight | FormatBlock FontName FontSize | InsertTable | ForeColor SpecialCharacter | SelectAll RemoveFormat"
  ];

  TOOLBARS["template"] = [
    "Cut Copy Paste Spell | Undo Redo | Bold Italic Underline | Outdent Indent | InsertUnorderedList InsertOrderedList | InsertImage InsertLink CreateBookmark InsertTemplateField InsertComponent FolderTree | EditSource",
    "JustifyLeft JustifyCenter JustifyRight | FormatBlock FontName FontSize | InsertTable | ForeColor InsertHorizontalRule InsertBreak SpecialCharacter | SelectAll RemoveFormat"
  ];

  function getTextElement() {
    
    return visualEditor;
  }

  // IE reformats url attributes in various ways.  this method uses
  // getAttribute(attrName, 2) to preserve the original url value.
  function conserveLinks(textElement, tagName, attrName) {

    var linkElements = textElement.getElementsByTagName(tagName);

    for (var i = 0; i < linkElements.length; i++) {
      linkElement = linkElements[i];
      
      var originalURI = linkElement.getAttribute(attrName, 2);
      
      if (originalURI != null && originalURI.length > 0) {
        linkElement.setAttribute('__original__' + attrName, originalURI);
      }
    }
  }

  function removeFormattedLinks(textElement, tagName, attrName) {
    var linkElements = textElement.getElementsByTagName(tagName);
    for (var i = 0; i < linkElements.length; i++) {

      linkElement = linkElements[i];

      if (tagName == "A") {
        removeBorder(linkElement.style);
        if (linkElement.innerHTML == "" && (! linkElement.name)) { 
          linkElement.removeNode(); 
          continue;
        }
      }

      var originalURI = linkElement.getAttribute('__original__' + attrName);
      if (originalURI != null) {
        linkElement.removeAttribute(attrName);
      }
    }
  }

  function setMode(mode) {

    if (mode == gMode) { return; }

    if (mode != "html" && mode != "source") {
      alert("Invalid mode parameter " + mode + " (should be html or source)");
      return;
    }

    gMode = mode;

    if (! gIsInitialized) {
      return;
    }

    if (mode == "source") {
      doEditSource();
    } else if (mode == "html") {
      doEditVisual();
    }
  }

  function setProperty(name, value) {
    gProperties[name] = value;
  }

  function getProperty (name) {
    return gProperties[name];
  }

  function focusVisual() {
    gNoCollapse = true;
    visualEditor.focus();
  }

  function doFocus() {

    if (gNoCollapse) {
      gNoCollapse = false;
      return;
    }

    if (! gIsInitialized) { 
      gNeedFocus = true; 
      return;
    } 

    var isVisual = (visualEditor.style.display != "none");
    if (isVisual) {

      visualEditor.focus();
      if (document.selection.type == "None") {
        var range = document.body.createTextRange();
        range.moveToElementText(visualEditor);
        range.collapse(true);
        range.select();
      } else {
        var range = document.selection.createRange();
        if (range.parentElement && range.parentElement().tagName == "BODY") {
          range.moveToElementText(visualEditor);
          range.collapse();
        }
        range.select();
      }

    } else {
      sourceEditor.focus();
    }
  }

  function initEditor() {

    for (i = 0; i < document.all.length; i++) {
      document.all(i).unselectable = "on";
    }

    visualEditor.unselectable = "off";
    sourceEditor.unselectable = "off";

    defaults.viewLink = document;
    defaults.tabStop = true;

    setStyleSheet(EDITOR_URL + "style.css");

    document.execCommand("2D-Position", false, false);

    var toolbarConfig = TOOLBARS[gConfig];
    if (! toolbarConfig) { 
      alert('No such toolbar configuration ' + gConfig); 
      return;
    }

    for (var i = 0; i < toolbarConfig.length; i++) {
      var tools = toolbarConfig[i].split(" ");
      if (toolbarConfig[i].indexOf("InsertFormElement") != -1) { 
        gIsFormEditor = true; 
      }
      gToolbars.push(createToolbar("toolbar" + i, tools));
    }

    if (gIsFormEditor) {
      addFormContainer();
    }      

    gSavePopup = window.createPopup();
    gSavePopup.document.body.innerHTML = document.all.saveStatus.outerHTML;

    gCommandPopup = window.createPopup();
    var styleSheet = gCommandPopup.document.createStyleSheet();
    styleSheet.addRule(".picker", 
      "border:outset white 2;background-color:#D4D0C8;");
    styleSheet.addRule(".pickerLabel", "font-family:Arial;font-size:9pt;" +
      "text-align:center;cursor:default;border:solid #D4D0C8 2;");
    styleSheet.addRule(".tablePickerCellOut", 
      "background-color:white;border:0 none;");
    styleSheet.addRule(".tablePickerCellIn", 
      "background-color:darkblue;border:0 none;");

    gCommandPopup.document.body.innerHTML = 
      document.all.popupContent.innerHTML;
      
    toggleFormControlEnabled(false);
  
  }

  function toggleFormControlEnabled(isVisual) {
    for (var i = 0; i < gToolbars.length; i++) {
      var toolbar = gToolbars[i];
      for (var j = 0; j < toolbar.commands.length; j++) {
        var tool = toolbar.commands[j];
        if (tool.id == 'InsertFormElement' && gDisableFormElementInsert) tool.setAlwaysDisabled();
      }
    }
  }

  function addFormContainer() {
    var formContainer = document.createElement("FORM");
    formContainer.style.display = "inline";
    formContainer.id = "formContainer";
    var visualDiv = document.all.visualEditor;
    visualDiv.replaceNode(formContainer);
    formContainer.appendChild(visualDiv);
  }

  function setConvertStyles(convertStyles) {
    gConvertStyles = (convertStyles == "true") ? true : false;
  }

  function setConfiguration(config) {
    gConfig = config;
    if (config == "full" || config == "advanced") {
      gProperties["useContextMenus"] = true;
    }
  }

  function initForm() {

    var parentForm = element.parentElement;
    while (parentForm != null && parentForm.tagName != "FORM") {
      parentForm = parentForm.parentElement;
    }

    if (parentForm == null) {
      alert("Error initializing the HTML editor: " +
            "the parent form was not found.");
      return;
    }

    gFormElement = parentForm.elements[element.name];
    if (gFormElement && 
        (gFormElement.tagName != "INPUT" || gFormElement.type != "hidden")) {
      alert("Error initializing the HTML editor: " +
            "the parent form has a form element with the same name.");
      return;
    }

    gFormActionElement = parentForm.elements[FORM_ACTION_ELEMENT];

    if (! gFormElement) {
      gFormElement = element.document.createElement(
        "<input type=hidden name=" + element.name + ">");
      gFormElement.htmlEditor = element;
      parentForm.appendChild(gFormElement);
    }

    parentForm.attachEvent("onsubmit", doSubmit);

    if (gFormElement.value) {
      setValue(gFormElement.value);
    } else {
      setValue(element.innerHTML);
    }

    setTimeout(embedCheck, 100);

    var evt = createEventObject();
    initEventID.fire(evt);
  
    gIsInitialized = true;

    if (gMode == "source") {
      setTimeout(doEditSource, 20);
    }

    if (gNeedFocus) {
      doFocus();
    }

    addStyleSheets();
    loadComponents();
  }

  function embedCheck() {
    var embeddedObjects = visualEditor.getElementsByTagName("EMBED");
  if (embeddedObjects.length > 0) {
    alert("The editor cannot save this content because it contains an EMBED tag. " +
          "Please edit this template or page as source instead.");
    return;
  }
  }

  function setStyleSheet(url) {
    gStyleSheets.push(url);
  }

  function addStyleSheets() {

    for (var i = gStyleSheets.length - 1; i >= 0; i--) {

      var url = gStyleSheets[i];

      var link = document.createElement("LINK");
 
      link.href = url;
      link.rel = "stylesheet";
      link.type = "text/css";
  
      var heads = document.getElementsByTagName("HEAD");
      heads[0].appendChild(link);
    }
  }

  function setPageURL(url) {
    gPageURL = url;
  }

  function setSubsiteID(id) {
    gSubsiteID = id;
  }

  function setFolderID(id) {
    gFolderID = id;
  }

  function setItemID(id) {
    gItemID = id;
  }

  function setTypeID(id) {
    gTypeID = id;
  }

  function setFormID(id) {
    if (id) {
      gFormID = id;
    }
  }
  
  function setInsertFormElementState(insertFormElementState) {
    if (insertFormElementState == 'enabled') { gDisableFormElementInsert = false; }
    if (insertFormElementState == 'disabled') { gDisableFormElementInsert = true; }
    if (insertFormElementState == 'removed') { gRemoveFormElementInsert = true; } 
  }
  function setIsRTF(isRTF) {
    if(isRTF) {
    gIsRTF = isRTF;
	}
  }
  function updateFormStatus() {

    if (gIsFormEditor) {
      var inputs = visualEditor.getElementsByTagName("INPUT");
      var selects = visualEditor.getElementsByTagName("SELECT");
      var textareas = visualEditor.getElementsByTagName("TEXTAREA");
      if (inputs.length > 0 || selects.length > 0 || textareas.length > 0) {
        gFormID = gItemID;
        gHasFormElements = true;
      }
    }
  }

  function getFormElements() {
    var formElements = null;
    if (gIsFormEditor) {
      var inputs = visualEditor.getElementsByTagName("INPUT");
      var selects = visualEditor.getElementsByTagName("SELECT");
      var textareas = visualEditor.getElementsByTagName("TEXTAREA");

      formElements = new Array(inputs.length + selects.length + textareas.length);

      var j=0;
      for (var i = 0; i < inputs.length; i++) {
        formElements[j] = inputs[i];
        j++;
      }
      for (var i = 0; i < selects.length; i++) {
        formElements[j] = selects[i];
        j++;
      }
      for (var i = 0; i < textareas.length; i++) {
        formElements[j] = textareas[i];
        j++;
      }
    }
    return formElements;
  }

  function getHeight() {
    return visualEditor.style.height;
  }

  function setHeight(height) {
    if (height < 100) return;
    visualEditor.style.height = height;
    sourceEditor.style.height = height;
  }

  function convertFontStyles(element) {

    if (! element) { element = visualEditor; }
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {

      var child = children[i];

      if (child.tagName == "BR" || child.tagName == "HR") { continue; }

      var style = child.style;
      if (child.nodeType != 1) { continue; }
      if (child.tagName == "INPUT") { continue; }

      if (style.cssText == "") {
        convertFontStyles(child);
        if (gConvertStatus == "FAILURE") { return; }
        continue;
      }

      var tagName = child.tagName;
      if (tagName == "EM" || tagName == "B" || 
          tagName == "STRONG" || tagName == "I") {
        child.removeNode(false);
        gConvertStatus = "SUCCESS";
        continue;
      }

      if (style.textAlign) {
        child.align = style.textAlign;
        style.removeAttribute("textAlign");
        gConvertStatus = "SUCCESS";
      }

      if (style.fontFamily || style.fontSize || style.color) {
        var fontElement = createFontElement(child);
        if (fontElement.color || fontElement.face || fontElement.size) {

          if (! moveChildren(child, fontElement, 0)) {
            gConvertStatus = "FAILURE";
            return;
          }

          if (child.tagName == "SPAN" && ! child.id && ! child.className) {
            child.replaceNode(fontElement);
          } else {
            child.insertBefore(fontElement);
          }
          gConvertStatus = "SUCCESS";
          child = fontElement;
        }
      }
      convertFontStyles(child);
      if (gConvertStatus == "FAILURE") { return; }
    }
  }

  function createFontElement(element) {
  
    var fontElement = document.createElement("FONT");

    if (element.style.fontFamily) {
      fontElement.face = element.style.fontFamily;
      element.style.removeAttribute("fontFamily");
    }
    if (element.style.color) {
      fontElement.color = element.style.color;
      element.style.removeAttribute("color");
    }
    if (element.style.fontSize) {
      var size = FONT_SIZE_MAP[element.style.fontSize];
      if (size) { 
        fontElement.size = size;
        element.style.removeAttribute("fontSize");
      }
    }

    return fontElement;
  } 

  function setStyle(element, fontElement) {

    if (fontElement.face) {
      element.style.fontFamily = fontElement.face;
    }
    if (fontElement.color) {
      element.style.color = fontElement.color;
    }
    if (fontElement.size) {
      var size = FONT_SIZE_MAP[fontElement.size];
      if (size) { 
        element.style.fontSize = size;
      }
    }
  } 

  function convertAlignAttributes(element) {

    if (! element) { return; }

    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {
      var child = children[i];
      if (child.nodeType != 1 || child.tagName == "IMG" || 
          child.tagName == "TABLE" || 
	  child.tagName == "OBJECT" || child.tagName == "INPUT" || 
          child.tagName == "EMBED" || child.tagName == "SELECT") { continue; }
      if (child.align) {
        child.style.textAlign = child.align;
        child.removeAttribute("align");
      }
      convertAlignAttributes(child);
    }
  }

  function updateEditorValue() {
    if (visualEditor.style.display == "none") {

      if (gIsFormEditor && (sourceEditor.innerText.indexOf("<form") != -1 ||
        sourceEditor.innerText.indexOf("<FORM") != -1)) {
        gIsFormEditor = false;
        document.all.formContainer.removeNode(false);
      }
      
      setVisualText(sourceEditor.innerText);
    }
  }

  function getValue() {

    updateEditorValue();

    var areas = visualEditor.getElementsByTagName("AREA");
    var shapes = new Array();
    for (var i = 0; i < areas.length; i++) {
      var area = areas[i];
      if (! area.id) { area.id = "area-" + i; }
      shapes[area.id] = area.outerHTML;
    }
 
    var scripts = visualEditor.getElementsByTagName("SCRIPT");
    var originals = new Array();
    for (var i = 0; i < scripts.length; i++) {
      var script = scripts[i];
      script._uniqueID = document.uniqueID;
      originals[script._uniqueID] = script;
    }

    var editorCopy = CmsXBrowser.cloneNode(visualEditor);
    areas = editorCopy.getElementsByTagName("AREA");
    for (var i = 0; i < areas.length; i++) {
      var area = areas[i];
      if (! area.id) { continue; }
      var areaCopy = document.createElement(shapes[area.id]);
      area.replaceNode(areaCopy);
    }

    var divs = editorCopy.getElementsByTagName("DIV");
    for (var i = 0; i < divs.length; i++) {
      var div = divs[i];
      if (div.className && div.className.match(/^frontleaf-/)) {
        div.innerHTML = "";
        var textBox = document.createElement("<TEXTAREA name='" + 
                      div.name + "'>");
        if (div.validation) { textBox.validation = div.validation; };
        div.appendChild(textBox);
      }
    }

    for (var i = 0; i < divs.length; i++) {
      var div = divs[i];
      if (div.className && div.className == "templateComponent") {
        div.innerHTML = "";
      }
    }

    if (gConvertStyles) { 
      convertAlignAttributes(editorCopy);
    }

    removeFormattedLinks(editorCopy, "A", "href");
    removeFormattedLinks(editorCopy, "IMG", "src");

    var scripts = editorCopy.getElementsByTagName("SCRIPT");
    for (var i = 0; i < scripts.length; i++) {
      var script = scripts[i];
      if (inComponent(script)) { continue; }
      var original = originals[script._uniqueID];
      var clone = CmsXBrowser.cloneNode(original);
      clone.text = "/** __BEGIN_SCRIPT " + original.text + " __END_SCRIPT **/";
      script = script.replaceNode(clone);
      clone.removeAttribute("_uniqueID");
    }

    var result = editorCopy.innerHTML;
    result = result.replace(/\/\*\* __BEGIN_SCRIPT /g, "");
    result = result.replace(/ __END_SCRIPT \*\*\//g, "");

    result = result.replace(/__original__href/g, "href");
    result = result.replace(/__original__src/g, "src");

    result = result.replace(/&amp;/g, "&");
    
    return result;
  }

  function inComponent(element) {

    for (;element != null; element = element.parentNode) {
      if (element.className == "templateComponent") return true;
    }

    return false;
  }

  function removeBorder(style) {

    var properties = style.cssText.toLowerCase().split(";");
    var cssText = "";

    for (var i = 0; i < properties.length; i++) {
      var property = properties[i];
      if (property.match(/^\s*border/)) {
        continue;
      }
      if (i > 0) { cssText += ";"; }
      cssText += property;
    }

    style.cssText = cssText;
  }

  function setValue(text) {

    if (text == "") { text = "<p>&nbsp;</p>"; }

    if (gIsFormEditor && (text.indexOf("<form") != -1 ||
			  text.indexOf("<FORM") != -1)) {
      gIsFormEditor = false;
      document.all.formContainer.removeNode(false);
    }

    setVisualText(text);

    updateFormStatus();

    gConvertStatus = "NONE";
    
    convertFontStyles(visualEditor);

    if (! gConvertStyles && gConvertStatus != "NONE") {
      if (! window.confirm("This HTML has different styling conventions " +
      "than those used by the editor.  Would you like to update the " +
      "content to be consistent with the WYSIWYG editor tools?")) {
        visualEditor.innerHTML = text;
      }
    }

    var divs = visualEditor.getElementsByTagName("DIV");
    for (var i = 0; i < divs.length; i++) {
      var div = divs[i];
      if (div.className == "frontleaf-editor") {
        createEditorMockup(div.id);
      }
    }

    originalHashValue = hashValue();
    originalLength = visualEditor.innerHTML.length;
  }

  function setVisualText(text) {
    text = "<div id=__IE_PROTECT__>&nbsp;</div>" + text;

    var iframe = document.getElementById('textFrame');
  
    var frameDoc = iframe.contentWindow.document;
    frameDoc.open();
    frameDoc.write('<html><body>');
    frameDoc.write(text);
    frameDoc.write('</body></html>');
    frameDoc.close();
  
    var body = frameDoc.body;

    conserveLinks(body, "A", "href");
    conserveLinks(body, "IMG", "src");
    conserveLinks(body, "INPUT", "src");
    
    visualEditor.innerHTML = body.innerHTML;
    visualEditor.firstChild.removeNode(true);
  }

  function isModifiedGet() {

    updateEditorValue();

    if (getProperty("modified")) { return true; }

    var value = visualEditor.innerHTML;
    var newLength = value.length;
 
    if (newLength != originalLength) { return true; }

    var newHashValue = hashValue();

    return (newHashValue != originalHashValue);
  }

  function isModifiedPut(isModified) {

    updateEditorValue();  

    if (! isModified) {
      var value = visualEditor.innerHTML;
      originalLength = value.length;
      originalHashValue = hashValue();
    }
  }

  function hashValue() {

    var hashValue = 5381;
    var value = visualEditor.innerHTML;

    for (var i = 0; i < value.length; i++) {
      hashValue = ((hashValue << 5) + hashValue) + value.charCodeAt(i);
    }

    return hashValue;
  }

  function doDrop() {

    if (event.dataTransfer.dropEffect == "none") { return; }
    event.returnValue = false;
    event.cancelBubble = true;

    var range = null;

    // append link if cannot MS does not find an element in the editor
    // to insert
    if (! visualEditorHasSelection(true)) {
      focusVisual();

      if (visualEditor.innerHTML == "") {
        visualEditor.innerHTML = "<p>&nbsp;</p>";
      }
      range = document.selection.createRange();

      var nodeLen = visualEditor.childNodes.length;
      var lastNode = visualEditor.childNodes[nodeLen - 1];
      range.moveToElementText(lastNode);

      range.collapse(false);
      range.select();
    }

    if (range == null) {
      range = getRange();
    }

    if (range == null) {
	      return;	
    }

    var dropText = event.dataTransfer.getData("text")
    dropText = dropText.replace("<NOIMG", "<IMG");

    trackUndo(true);

    range.pasteHTML(dropText);
  }
  
  function doSelectionChange() {
    updateToolbars();
  }

  function doKeyDownAttach() {

    if (event.keyCode == 8 && document.selection.type == "Control") {

      var ctrlRange = document.selection.createRange();
      if (ctrlRange.length > 0) {
        trackUndo(true);
        ctrlRange.item(0).removeNode(true);
      }

      event.returnValue = false;
      event.cancelBubble = true;
    }
  }

  function doKeyDown() {

    if (event.ctrlKey) {
      switch (event.keyCode) { 
        case 65:
          document.execCommand("SelectAll");
          break;
        case 66:
          document.execCommand("Bold");
          break;
        case 67:
          document.execCommand("Copy");
          break;
        case 70:
	  gCancelKey = true;
          doFind();
          break;
        case 73:
          document.execCommand("Italic");
          break;
        case 85:
          document.execCommand("Underline");
          break;
        case 86:
          doPaste();
          break;
        case 88:
          document.execCommand("Cut");
          break;
        case 89:
          doRedo();
          break;
        case 90:
          doUndo();
          break;
      }
      event.returnValue = false;
      event.cancelBubble = true;
      return;
    }

    // control key?
    if (event.keyCode == 17) { return; }

    // arrow keys
    if (event.keyCode > 32 && event.keyCode < 41) { return; }

    var range = getRange();
    if (range == null) return;

    if (event.keyCode == 9) { tabToNextCell(range); return; }

    if (! gLastUndoTyping) {
      trackUndo(true);
    }

    // check for backspacing over a link to avoid MSHTML deleting the link
    // rather than the last character of the link text
    var cursorElements = getCursorElements(range, -1);
      
    if (cursorElements != null &&
        cursorElements.lastTag == "A" && cursorElements.thisTag != "A") {

      var keyCode = event.keyCode;
      var range = document.selection.createRange();

      if (keyCode == 8) {

        range.moveStart('word', -1);
        range.pasteHTML(range.text.substring(0, range.text.length - 1));
        event.returnValue = false;
        event.cancelBubble = true;

      } else if (keyCode == 190) {

        putTextAfterElement(range, '. ', "A");

      } else if (keyCode > 32 && keyCode != 46 && keyCode != 127) {
  
        // hack to ensure that IE inserts correct character
        range.moveStart('character', -1);
        if (range.text.length > 0) {
          var lastChar = range.text;
          range.pasteHTML(lastChar + lastChar);
          range.moveStart('character', -1);
          range.select();
        }
      }
    } 

    if (event.keyCode == 8) {

      var cursorElements = getCursorElements(range, -2);

      if (cursorElements != null &&
        (cursorElements.lastTag == "TD" || cursorElements.lastTag == "TH") &&
        (cursorElements.thisTag != "TD" && cursorElements.lastTag != "TH")) {

        var table = cursorElements.lastParent.parentNode.parentNode.parentNode;
        var isOut = true;
        for (var parent = cursorElements.thisParent; parent != null; 
             parent = parent.parentNode) {
          if (parent == table) {
            isOut = false;
            break;
          }
        }
        if (isOut) {
          if (window.confirm("You are about to backspace over a table.  " +
            "Are you sure you want to delete the entire table?")) {
            while (table.childNodes.length > 0) {
              table.childNodes[0].removeNode(true);
            }
          } else {
            event.returnValue = false;
            event.cancelBubble = true;
          }
        }
      }
    }

    if (event.keyCode == 13) {
      trackUndo(true);
    }
  }

  function doSourceKeyDown() {

    if (event.ctrlKey) {
      switch (event.keyCode) { 
        case 65:
          document.execCommand("SelectAll");
          break;
        case 86:
          doPaste();
          break;
        case 88:
          document.execCommand("Cut");
          break;
        case 89:
          doRedo();
          break;
        case 90:
          doUndo();
          break;
      }
      event.returnValue = false;
      event.cancelBubble = true;
      return;
    }

    // control key?
    if (event.keyCode == 17) { return; }

    // arrow keys
    if (event.keyCode > 32 && event.keyCode < 41) { return; }

    if (event.keyCode == 13) {
      trackUndo(true, sourceEditor.innerText);
    }
  }

  function doKeyPress() {

    if (gCancelKey) {
      gCancelKey = false;
      event.returnValue = false;
      event.cancelBubble = true;
      return;
    }

    if (! gClearFont || event.keyCode == 13) {
      return;
    }

    var range = getRange();
    if (range == null) return;

    putTextAfterElement(range, String.fromCharCode(event.keyCode), "FONT");

    gClearFont = false;
  }

  function doSourceKeyPress() {

    if (gCancelKey) {
      gCancelKey = false;
      event.returnValue = false;
      event.cancelBubble = true;
    }
  }

  function putTextAfterElement(range, text, elementName) {

    var parent = range.parentElement();
    if (parent.tagName != elementName) return;

    // hack to prevent IE from assigning font tags to default text
    var textNode = document.createTextNode(text);

    var next = parent.nextSibling;
    var grandParent = parent.parentNode;
    grandParent.insertBefore(textNode, next);
    range.move("character", 1);
    range.select();

    event.returnValue = false;
    event.cancelBubble = true;
  }

  function getContextElement() {

   var contextElement = gMenuElement;

   for (;contextElement != null; contextElement = contextElement.parentNode) {

     if (contextElement.unselectable == "on") {
       continue;
     }

     if (contextElement.className == "frontleaf-editor") break;
     if (contextElement.className == "templateComponent") break;
     if (contextElements[contextElement.tagName]) break;
   }

   if (contextElement != null) {
     gMenuElement = contextElement;
     gContextElement = contextElement;
   }
  }

  function doContextMenu() {
	if (! gProperties["useContextMenus"]) {
      return;
    }

    var isStandalone = gProperties["isStandalone"];

    // save editor selection because editor loses focus on menu selection
    gMenuSelection = document.selection.createRange();
    gMenuElement = event.srcElement;
    gLinkElement = null;

    getContextElement();

    if (gMenuElement.tagName == "A") {
      gLinkElement = gMenuElement;
      gMenuElement = gMenuElement.parentNode;
      getContextElement();
    }

    var inTable = false;
    var tableCell = gMenuElement;
    while (tableCell != null) {
      if (tableCell.tagName == "TD" || tableCell.tagName == "TH") {
        inTable = true;
        break;
      }
      tableCell = tableCell.parentNode;
    }

    var editorDiv = gMenuElement;
    while (editorDiv != null) {
      if (editorDiv.tagName == "DIV" && 
          editorDiv.className == "frontleaf-editor") {
        gMenuElement = editorDiv;
        inTable = false;
        break;
      }
      editorDiv = editorDiv.parentNode;
    }

    gMenuX = event.x;
    gMenuY = event.y;

    editorMenu.clear();

    editorMenu.addItem("Cut", menuCut);
    editorMenu.addItem("Copy", menuCopy);
    editorMenu.addItem("Paste", menuPaste);
    editorMenu.addSeparator();
    editorMenu.addItem("Select All", menuSelectAll);

    if (gMenuElement.tagName == "P") {
      editorMenu.addSeparator();
      editorMenu.addItem("Paragraph Properties...", menuParaProperties);
    }

    if (inTable) {
      editorMenu.addSeparator();
      editorMenu.addItem("Insert Row", menuInsertRow);
      editorMenu.addItem("Insert Column", menuInsertColumn);
      editorMenu.addSeparator();
      editorMenu.addItem("Delete Row", menuDeleteRow);
      editorMenu.addItem("Delete Column", menuDeleteColumn);
      editorMenu.addItem("Delete Table", menuDeleteTable);
      editorMenu.addSeparator();
      editorMenu.addItem("Merge Right", menuMergeCellRight);
      editorMenu.addItem("Merge Down", menuMergeCellDown);

      if ((tableCell.rowSpan && tableCell.rowSpan > 1) || 
          (tableCell.colSpan && tableCell.colSpan > 1)) {
        editorMenu.addItem("Split Cell", menuSplitCell);
      }

      editorMenu.addSeparator();
      editorMenu.addItem("Table Properties...", menuTableProperties);
      editorMenu.addItem("Cell Properties...", menuCellProperties);
    }

    var isImage = (gMenuElement.tagName == "IMG" || 
      (gMenuElement.id && gMenuElement.id.match(/image-\d+/)));

    var isCaptchaImage = 
      isImage && (gMenuElement.id && gMenuElement.id == "captcha-image");

    if (! isStandalone && isImage && ! isCaptchaImage) {
      editorMenu.addSeparator();
      editorMenu.addItem("Image Layout...", menuImageLayout);
      editorMenu.addItem("Choose Another Image...", menuImageSource);
      editorMenu.addItem("Manage This Image...", menuImageManage);

      var imgParent = gMenuElement.parentElement;
      if (imgParent.tagName == "A") {
        gLinkElement = imgParent;
      }
    }

    if (gFormID != null) {
      if (editorDiv) {
        addFormItem("Rich Text Properties...", menuRichTextProperties);
      } else if (gMenuElement.tagName == "SELECT") {
        addFormItem("Drop-Down Menu Properties...", menuSelectProperties);
      } else if (gMenuElement.tagName == "TEXTAREA") {
        addFormItem("Text Box Properties...", menuTextBoxProperties);
      } else if (gMenuElement.tagName == "INPUT") {
        switch (gMenuElement.type) {
          case "hidden": 
            addFormItem("Hidden Field Properties...", menuHiddenFieldProperties);
            break;
          case "text": 
            var isCaptchaInput = (gMenuElement.model && gMenuElement.model == "captcha");
            if (! isCaptchaInput) {
              addFormItem("Text Field Properties...", menuTextFieldProperties);
            }
            break;
          case "checkbox": 
            addFormItem("Checkbox Properties...", menuCheckboxProperties);
            break;
          case "radio": 
            addFormItem("Radio Button Properties...", menuRadioProperties);
            break;
          case "file": 
            addFormItem("File Upload Properties...", menuFileUploadProperties);
            break;
          case "submit": 
          case "reset": 
            addFormItem("Button Properties...", menuFormButtonProperties);
            break;
        }
      } else {
        addFormItem();
      }
    }

    if (gLinkElement != null) {

      var isCaptchaLink = 
        (gLinkElement.className && gLinkElement.className == "captchaLink");

      if (gLinkElement.href && ! isCaptchaLink) {
        editorMenu.addSeparator();
        editorMenu.addItem("Link Properties...", menuLinkProperties);
        editorMenu.addItem("Remove Link", menuLinkRemove);
      }

      if (gLinkElement.name && ! isCaptchaLink) {
        editorMenu.addSeparator();
        editorMenu.addItem("Edit Bookmark...", menuBookmarkProperties);
        editorMenu.addItem("Remove Bookmark", menuLinkRemove);
      }
    }

    if (gMenuElement.tagName == "DIV" && 
        gMenuElement.className == "templateComponent" && ! isImage) {
      editorMenu.addSeparator();
      addComponentMenuOptions();
    }

    var top = event.clientY;
    var left = event.clientX;

    if (gConfig == "template") {
      editorMenu.addSeparator();

      var spans = gMenuElement.getElementsByTagName("SPAN");
      for (var i = 0; i < spans.length; i++) {

         if (inBounds(spans[i], left, top)) { 
           gMenuElement = spans[i];
           break;
         }
      }

      if (gMenuElement.className == "templateVariable") {
        var name = gMenuElement.innerText;
        name = name.substring(1, name.length - 1);
        var templateFields = getProperty("templateFields");
        var type = "";
        for (var i = 0; i < templateFields.length; i++) {
          var fieldData = templateFields[i];
          if (fieldData[1] == name) {
            type = fieldData[2];
            break;
          }
        }
        switch (type) {
          case "categoryarray":
            editorMenu.addItem("Category Properties...", menuCategories);
            break;
        }
      } else {
        editorMenu.addItem("Repeat...", menuRepeat);
      }
    }

    var top = event.clientY;
    var left = event.clientX;
    var parent = element;
    while (parent != null) {
      top += parent.offsetTop;
      left += parent.offsetLeft;
      parent = parent.offsetParent;
    }

    editorMenu.show(top, left, element.document.body);

    event.returnValue = false;
    event.cancelBubble = true;
  }

  function addFormItem(label, handler) {

    if (label) {
      editorMenu.addSeparator();
      editorMenu.addItem(label, handler);
   }

    if (! getProperty("hideFormProperties")) {
      if (! label) {
        editorMenu.addSeparator();
      }      
      // editorMenu.addItem("Form Actions...", menuFormActions);
      editorMenu.addItem("Form Properties...", menuFormProperties);
      editorMenu.addItem("Form Submissions...", menuFormSubmissions);
    }
  }

  function hideMenu() {
    editorMenu.hide();
  }

  function menuRepeat() {

    hideMenu();

    if (gMenuSelection == null) { 
      alert("Please select an area to repeat.");
      return; 
    }

    trackUndo(false);

    var elements = getSelectedElements(gMenuSelection);
    if (elements == null || elements.length == 0) { 
      alert("Please select an area to repeat.");
      return; 
    }
    if (elements.length == 1 && elements[0] == visualEditor) {
      elements = new Array();
      for (var i = 0; i < visualEditor.childNodes.length; i++) {
        elements.push(visualEditor.childNodes[i]);
      }
    }

    var repeatDiv = document.createElement("DIV");
    repeatDiv.className = "templateRepeat";
    
    elements[0].parentNode.insertBefore(repeatDiv, elements[0]);

    for (var i = 0; i < elements.length; i++) {
      var moveNode = elements[i];
      repeatDiv.appendChild(moveNode);
    }
  }

  function menuCategories() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var lastText = visualEditor.innerHTML;

    var path = "template-category-dialog.jsp";
    if (showDialog(path, gMenuElement)) {
      trackUndo(false, lastText);
    }

    gMenuElement = null;
  }

  function menuCut() {

    hideMenu();

    if (gMenuSelection == null) { return; }

    trackUndo(false);
    gMenuSelection.select();
    document.execCommand("Cut");

    gMenuSelection == null;    
  }

  function menuCopy() {

    hideMenu();

    if (gMenuSelection == null) { return; }

    trackUndo(false);
    gMenuSelection.select();
    document.execCommand("Copy");

    gMenuSelection == null;    
  }

  function menuPaste() {

    hideMenu();

    if (gMenuSelection == null) { return; }

    trackUndo(false);
    gMenuSelection.select();

    doPaste();

    gMenuSelection = null;
  }

  function menuSelectAll() {

    hideMenu();

    focusVisual();
    document.execCommand("SelectAll");
  }

  function menuImageManage() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var image = gMenuElement;
    if (image.tagName == "IMG") {
      var manageWindow = 
        window.open("/admin/item/actions/status-url-redirect.jsp?url=" + 
	  image.src);
    } else {
      var pageletData = gMenuElement.id.split("-");
      var pageletID = pageletData.pop();
      var manageWindow = 
        window.open("/admin/item/actions/status-pagelet-redirect.jsp?" +
	  "pageletID=" + pageletID + "&param=imageID");
    }
  }

  function menuImageSource() {

    hideMenu();

    if (gMenuElement == null) { return; }
    var image = gMenuElement;

    var assetFolderID = getProperty("assetFolderID");
 
    if (isNaN(assetFolderID)) { assetFolderID = gFolderID; }

    if (isNaN(assetFolderID)) {
      alert("A folder ID is required to use the image chooser.");
      return;
    }

    var path = "/admin/components/explorer/dialog.jsp?" +
      "&baseType=image&selectionType=image&view=gallery&folderID=" + 
      assetFolderID;

    var dialogResult = showDialog(path, null, "newimage");

    if (dialogResult == null) { return; }

    trackUndo(false);

    var element = null;

    if (dialogResult.content) {

      element = document.createElement("DIV");
      element.contentEditable = false;
      element.className = "templateComponent";
      element.innerHTML = dialogResult.content;
      element.id = dialogResult.pageletID;

      for (i = 0; i < element.all.length; i++) {
        if (element.all(i) == element) { continue; }
        element.all(i).unselectable = "on";
      }
 
    } else {

      element = document.createElement("IMG");
      element.src = dialogResult.url;
      if (gMenuElement.style.borderWidth) {
	element.style.borderWidth = gMenuElement.style.borderWidth;
      }
   }

    gMenuElement.parentNode.replaceChild(element, gMenuElement);
    gMenuElement = null;
  }

  function menuImageLayout() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var lastText = visualEditor.innerHTML;

    var path = "image-layout-dialog.jsp?pageID=" + gItemID;

    if (gMenuElement.tagName == "DIV") {
      var pageletData = gMenuElement.id.split("-");
      var pageletID = pageletData.pop();
      path += "&pageletID=" + pageletID;
    } else {
      path += "&imageURL=" + gMenuElement.src;
    }

    var image = gMenuElement;

    arguments = new Object();
    arguments.image = image;

    if (showDialog(path, arguments, "imagelayout")) {
      trackUndo(false, lastText);
    }

    refreshVisualEditor();

    gMenuElement = null;
  }

  function doImageTool(tool) {

    hideMenu();

    if (gMenuElement == null) { return; }

    var image = gMenuElement;

    arguments = new Object();
    arguments.image = image;

    var path = "image-" + tool + "-dialog.jsp?folderID=" + gFolderID;
    if (image.tagName == "IMG") {
      path += "&imageURL=" + image.src;
    } else {
      var pageletData = gMenuElement.id.split("-");
      var pageletID = pageletData.pop();
      path += "&pageletID=" + pageletID;
    }
    var result = showDialog(path, arguments, "imagetool");

    if (gMenuElement.tagName == "IMG") {
      image.src = image.src;
    } else {
      var images = gMenuElement.getElementsByTagName("IMG");
      for (var i = 0; i < images.length; i++) {
        images[i].src = images[i].src;
      }
    }

    gMenuElement = null;
  }

  function menuFormProperties() {
    
    hideMenu();
    var url = "/components/editor/form-properties-dialog.jsp?itemID=" + gItemID;
    showDialog(url);
    gMenuElement = null;
  }

  function menuFormActions() {
    
    hideMenu();
    showFormActionsDialog();
    gMenuElement = null;
  }

  function showFormActionsDialog(create) {
  
    var url = "/components/editor/dialogs/form-actions.jsp?itemID=" + gItemID;
    if (create) {
      url += "&create=true";
    }

    var formActions = getProperty("formActions");
    var formActions = showDialog(url, formActions, "formactions");
    
    if (formActions) {
      setProperty("formActions", formActions);
      setProperty("modified", true);
      return true;
    } else {
      return false;
    }
  }

  function menuFormSubmissions() {
    
    hideMenu();
  
    var url = "/admin/item/actions/status.jsp?itemID=" + gItemID + 
      "&pane=form";

    window.open(url, "_blank");

    gMenuElement = null;
  }

  function menuSelectProperties() {
    menuFormElementProperties('select');
  }

  function menuCheckboxProperties() {
    menuFormElementProperties('checkbox');
  }

  function menuRadioProperties() {
    menuFormElementProperties('radio');
  }

  function menuHiddenFieldProperties() {
    menuFormElementProperties('hidden');
  }

  function menuTextFieldProperties() {
    menuFormElementProperties('textfield');
  }

  function menuFileUploadProperties() {
    menuFormElementProperties('file');
  }

  function menuTextBoxProperties() {
    menuFormElementProperties('textbox');
  }

  function menuFormButtonProperties() {
    menuFormElementProperties('button');
  }

  function menuRichTextProperties() {
    menuFormElementProperties('richtext');
  }

  function menuFormElementProperties(elementType) {

    hideMenu();

    if (gMenuElement == null) { return; }

    showFormElementDialog(elementType, gMenuElement);

    refreshVisualEditor();

    var range = document.selection.createRange();
    range.moveToElementText(gMenuElement);
    range.collapse(false);
    range.select();

    gMenuElement = null;
  }

  function showFormElementDialog(elementType, formElement, isNew) {

    var lastText = visualEditor.innerHTML;

    var today = new Date();
    var millis = Date.parse(today);

    var contentTypeForm = true;
    if (gItemID) {
      contentTypeForm = false;
    }
    
    var arguments = new Object();
    arguments.input = formElement;
    arguments.doc = document;
    arguments.isNew = isNew;
    arguments.propertyNames = getProperty("propertyNames");
    arguments.standardFields = getProperty("standardFields");
    arguments.form = document.getElementById("formContainer");
    arguments.elementType = elementType;
    arguments.formID = gFormID;
    
    var dialogType = (elementType == "checkbox" || elementType == "radio") ? 
      "option-button" : elementType;

    var extension = "html";
    if (elementType == "select") {
       extension = "jsp?folderID=" + gFolderID;
       if (formElement.model) {
       var params = formElement.model.split(";");
         extension += "&" + params[1];
       }
       if (contentTypeForm == true) {
         extension += "&contentTypeForm=true";
       }
    } else if (elementType == "textfield") {
       extension = "jsp";
       if (contentTypeForm == true) {
         extension += "?contentTypeForm=true";
       }
    }

    var result = 
      showDialog(dialogType + "-dialog." + extension, arguments, elementType);

    if (result) {
      trackUndo(false, lastText);
      if (elementType == "richtext") {
        createEditorMockup(formElement.id); 
      }
      gMenuElement = result.formElement;
      return result.buttonValue;
    }

    return "Done";
  }

  function menuBookmarkProperties() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var dialogArgs = new Object();
    dialogArgs.bookmark = gLinkElement;

    var name = showDialog("bookmark-dialog.html", dialogArgs, "bookmark");
  }

  function menuLinkProperties() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var range = document.body.createTextRange();
    range.moveToElementText(gLinkElement);
    range.select();

    doInsertLink();
  }

  function menuLinkRemove() {

    hideMenu();

    if (gMenuElement == null) { return; }

    trackUndo(false);

    var linkNode = gLinkElement;
    if (gMenuElement.tagName == "IMG") {
      linkNode = gMenuElement.parentElement;
    }
    linkNode.removeNode(false);

    var range = document.body.createTextRange();
    range.moveToPoint(gMenuX, gMenuY);
    // range.select();

    setTimeout(updateToolbars, 10);
  }

  function menuParaProperties() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var lastText = visualEditor.innerHTML;

    arguments = new Object();
    if (gMenuSelection.parentElement) {
      arguments.paras = getSelectedParas(gMenuSelection);
    } else {
      arguments.paras = new Array();
      arguments.paras.push(gMenuElement);
    }

    if (showDialog("paragraph-dialog.html", arguments, "paragraph")) {
      trackUndo(false, lastText);
    }

    gMenuElement = null;
  }

  function menuCellInit() {

    hideMenu();

    if (gMenuElement == null) { return null; }

    var cell = gMenuElement;

    while (cell != null && cell.tagName != "TD") {
      cell = cell.parentElement;
    }

    if (cell == null) { return null; }

    trackUndo(false);

    return cell;
  }

  function menuSplitCell() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    splitCell(gMenuElement);
    gMenuElement == null;
  }

  function menuInsertRow() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    insertRow(cell);
    gMenuElement = null;
  }

  function menuDeleteRow() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    deleteRow(cell);
    gMenuElement = null;
  }

  function menuInsertColumn() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    insertColumn(cell);
    gMenuElement = null;
  }

  function menuDeleteColumn() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    deleteColumn(cell);
    gMenuElement == null;
  }

  function menuDeleteTable() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    deleteTable(cell);
    gMenuElement == null;
  }

  function menuMergeCellRight() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    mergeCells(cell, "right");
    gMenuElement = null;
  }

  function menuMergeCellDown() {

    var cell = menuCellInit();
    if (cell == null) { return; }

    mergeCells(cell, "down");
    gMenuElement = null;
  }

  function menuCellProperties() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var cell = gMenuElement;

    while (cell != null && cell.tagName != "TD" && cell.tagName != "TH") {
      cell = cell.parentElement;
    }
    if (cell == null) { return; }

    var range = document.selection.createRange();
    var lastText = visualEditor.innerHTML;

    if (showDialog("cell-dialog.html", cell, "cell")) {
      trackUndo(false, lastText);
    }

    refreshVisualEditor();
    range.select();

    gMenuElement = null;
  }

  function menuTableProperties() {

    hideMenu();

    if (gMenuElement == null) { return; }

    var table = gMenuElement;

    while (table != null && table.tagName != "TABLE") {
      table = table.parentElement;
    }
    if (table == null) { return; }

    arguments = new Object();
    arguments.table = table;
    arguments.tableDocument = document;

    var range = document.selection.createRange();
    var lastText = visualEditor.innerHTML;

    if (showDialog("table-dialog.html", arguments, "table")) {
      trackUndo(false, lastText);
    }

    refreshVisualEditor();
    range.select();

    gMenuElement = null;
  }

  function tabToNextCell(range) {

    if (! range.parentElement) { return; }

    var cell = range.parentElement();
    if (cell.tagName != "TD" && cell.tagName != "TH") { return; }

    var row = cell.parentElement;
    var cells = row.childNodes;
    var colIndex = 0;
    for (var i = 0; i < cells.length; i++) {
      if (cells[i] == cell) { colIndex = i; break; }
    }

    if (colIndex < cells.length - 1) {
      // get next cell in this row
      cell = cells[colIndex + 1];
    } else {
      // get first cell of next row
      var tbody = row.parentElement;
      var rows = tbody.childNodes;
      var rowIndex = 0;
      for (var i = 0; i < rows.length; i++) {
        if (rows[i] == row) { rowIndex = i; break; }
      }
      if (rowIndex < rows.length - 1) {
        row = rows[rowIndex + 1];
        cell = row.childNodes[0];
      } else {
        // no more rows, check for another body or head element
        var nextBody = tbody.nextSibling;
        if (nextBody == null || nextBody.tagName != "TBODY") {
          // insert a new row
          var copyRow = rows[rows.length - 1];
          var newRow = document.createElement("TR");
          for (var i = 0; i < copyRow.childNodes.length; i++) {
            var copyCell = copyRow.childNodes[i];
            var newCell = document.createElement(copyCell.tagName);
            newCell.colSpan = copyCell.colSpan;
            newCell.innerHTML = "&nbsp;";
            newRow.appendChild(newCell);
          }
          tbody.appendChild(newRow);
          cell = newRow.childNodes[0];
        } else {
          tbody = nextBody;
          if (tbody.childNodes.length == 0) { return; }
          row = tbody.childNodes[0];
          if (row.childNodes.length == 0) { return; }
          cell = row.childNodes[0];
        }
      }
    }
    range.moveToElementText(cell);
    range.select();
    event.returnValue = false;
  }

  function getCursorElements(range, size) {

    // range.moveStart('character', 1);
    range.collapse(false);

    gCursorElements.thisParent = range.parentElement();
    gCursorElements.thisTag = gCursorElements.thisParent.tagName;

    range = document.selection.createRange();
    range.moveStart('character', size);
    range.collapse(true);
    if (! range.parentElement()) { 
      return null; 
    }

    gCursorElements.lastParent = range.parentElement();
    gCursorElements.lastTag = gCursorElements.lastParent.tagName;

    return gCursorElements;
  }

  // tests whether the insertion point is at the end of a link
  function atLinkEnd(cursorElements) {

    range.moveStart('character', 1);
    range.collapse(false);

    var thisTag = range.parentElement().tagName;

    range = document.selection.createRange();
    range.moveStart('character', -1);
    range.collapse(true);
    if (! range.parentElement()) { 
      return false; 
    }

    var lastTag = range.parentElement().tagName;
    if (lastTag == "A" && thisTag != "A") {
      return true;
    }

    return false;
  }

  function doBlur() {

    gClearFont = false;
  }

  function visualEditorHasSelection(controlAllowed) {

    var parent = getRangeElement(controlAllowed);
 
    if (parent == null) { 
      return false;  
    }

    while (parent != null) {
      if (parent.id == "visualEditor") { 
        return true;
      }
      parent = parent.parentElement;
    }

    return false;
  }

  function getFormElementCount() {
    
    var inputs = visualEditor.getElementsByTagName("INPUT");
    var selects = visualEditor.getElementsByTagName("SELECT");
    var textareas = visualEditor.getElementsByTagName("TEXTAREA");

    return (inputs.length + selects.length + textareas.length);
  }

  function refreshVisualEditor() {

    sourceEditor.style.display = "block";
    visualEditor.style.display = "none";
    sourceEditor.focus();

    visualEditor.style.display = "block";
    sourceEditor.style.display = "none";
    focusVisual();
  }

  // dummy methods to prevent errors from pasted word docs
  function msoCommentShow() {}
  function msoCommentHide() {}

  // keep a bookmark on location so that search and replace
  // always moves forward

  var searchLocation = null;

  function startSearch() {
    searchLocation = null;
  }

  function doSearch(string) {

    var range = document.body.createTextRange();
    if (searchLocation != null) {
      range.moveToBookmark(searchLocation);
    }

    if (range.findText(string, 1000000, 2)) {

      var nextRange = document.body.createTextRange();
      nextRange.moveToBookmark(range.getBookmark());
      nextRange.collapse(false);
      searchLocation = nextRange.getBookmark();

      range.select();
    }
  }

  // replace current selection and move on from there
  function doReplace(fromString, toString, replaceAll) {

    var range = document.body.createTextRange();
    var bookmark = range.getBookmark();
    
    while (range.findText(fromString, 1000000, 2)) {
      range.text = toString;
      if (! replaceAll) { break; }
      range.moveToBookmark(bookmark);
    }
  }

  /**
   * Parses a pagelet tag, returning an object containing a pagelet ID (possibly null),
   * and a pagelet type key.
   *
   * @param pageletTag the pagelet tag
   */
  function _parsePageletTag(pageletTag) {
    var pageletData = pageletTag.split("-");

    var pageletID, pageletTypeKey;

    if (pageletData.length == 1) {
      // e.g., "poweredBy"

      pageletID = null;
      pageletTypeKey = pageletTag;
    } else {
      // e.g., "poweredBy-12435, printer-friendly"

      pageletID = pageletData.pop();

      if (isNaN(pageletID)) {
        pageletID = null;
        pageletTypeKey = pageletTag;
      } else {
        pageletTypeKey = pageletData.join("-");
      }
    }
        
    var result = {
      id : pageletID,
      key : pageletTypeKey
    };

    return result;
  }

  function getPageletID(componentID) {
    if (! componentID) { 
      alert("This component is invalid.  " +
            "Please delete it and try to recreate it by adding " +
            "a new component.");
      return null;
    }

    return _parsePageletTag(componentID).id;
  }

  function getPageletType(componentID) {

    if (! componentID) { 
      alert("This component is invalid.  " +
            "Please delete it and try to recreate it by adding " +
            "a new component.");
      return null;
    }

    return _parsePageletTag(componentID).key;
  }

  function loadComponents() {

    if (gFolderID == null) {
      alert("A folder must be specified to insert a component.");
    }

    var divs = visualEditor.getElementsByTagName("DIV");
    for (var i = 0; i < divs.length; i++) {
      var div = divs[i];
      if (div.className && div.className == "templateComponent" && 
          div.innerHTML == "" && div.id) {

        div.innerHTML = "&nbsp;";
        div.contentEditable = false;
        loadComponent(div.id);
        break;
      }
    }
  }

  var gLoadingComponentID = null;

  function loadComponent(componentID) {

    var now = new Date();
    var millis = Date.parse(now);

    var pageletID = getPageletID(componentID);
    if (pageletID == null) { return; }

    gLoadingComponentID = componentID;

    var pageletData = _parsePageletTag(componentID);
    var pageletID = pageletData.id;
    var pageletType = pageletData.key;

    var path = "pagelet.jsp?folderID=" + gFolderID;
    path += "&millis=" + millis;
    if (pageletID != null) { 
      path += "&pageletID=" + pageletID;
    } else {
      path += "&pageletType=" + escape(pageletType);
    }
    if (gItemID) {
      path += "&itemID=" + gItemID;
    }
    if (gTypeID) {
      path += "&typeID=" + gTypeID;
    }

    document.getElementById('componentFrame').src = EDITOR_URL + path;
  }

  function registerComponentType(typeName, menuInitHandler, insertHandler, 
   	typeLabel, adminPath) {

    var componentType = new Object();
    componentType.menuInitHandler = menuInitHandler;
    componentType.insertHandler = insertHandler;
    componentType.typeLabel = typeLabel;
    componentType.adminPath = adminPath;

    COMPONENTS[typeName] = componentType;
    
    return componentType;
  }

  function addComponentMenuOptions() {

    if (gMenuElement.tagName != "DIV") { return; }
    if (gMenuElement.className != "templateComponent") { return; }

    var typeName = getPageletType(gMenuElement.id);
    if (typeName == null) { return; }

    var componentType = COMPONENTS[typeName];
    if (componentType) {
      editorMenu.addItem("Component Style and Layout...", 
                         doComponentLayoutProperties);
      editorMenu.addSeparator();
      componentType.menuInitHandler(gMenuElement);
    }
  }

  function doComponentLayoutProperties() {

    editorMenu.hide();
    var pageletID = getPageletID(gMenuElement.id);
    if (pageletID == null) { return; }

    var path = "component-layout-dialog.jsp?pageletID=" + pageletID;

    if (showDialog(path, gMenuElement, "")) {
      loadComponent(gMenuElement.id);
    }
  }

  var isFirstComponentLoad = true;

  function replaceUnrenderableTags(content, doc) {
    hideUnrenderableTag(content, doc, "EMBED");
    hideUnrenderableTag(content, doc, "OBJECT");
  }

  function hideUnrenderableTag(content, doc, tagname) {
    // Replace all <TAGNAME></TAGNAME> tags with a <div></div> tags of equal size.
    // In editor mode, the embed tag was causing the browser to crash.
    var embeddedObjects = content.getElementsByTagName(tagname);
    while (embeddedObjects.length > 0) {
      var oldObject = embeddedObjects[0];
      var parent = oldObject.parentNode;

      if (parent != null) {
	var newObject = doc.createElement("DIV");
	newObject.setAttribute("align", "center");
	var embedWidth = oldObject.getAttribute("width");
	if (embedWidth != null) {
	  newObject.style.width = embedWidth;
	}
	var embedHeight = oldObject.getAttribute("height");
	if (embedHeight != null) {
	  newObject.style.height = embedHeight;
	}
	var emElement = doc.createElement("em");
	var textMessageNode = doc.createTextNode(tagname + " tag cannot be displayed in the editor.");
	emElement.appendChild(textMessageNode);
	newObject.appendChild(emElement);

	parent.insertBefore(newObject, oldObject);
	oldObject.removeNode(true);
      }
    }
    embeddedObjects = content.getElementsByTagName("/" + tagname);
    while (embeddedObjects.length > 0) {
      embeddedObjects[0].removeNode(true);
    }

  }

  function doComponentLoad() {

    if (isFirstComponentLoad) { 
      isFirstComponentLoad = false;
      return;
    }

    var componentDoc = 
      document.getElementById('componentFrame').contentWindow.document;

    var codeElement = componentDoc.all.resultCode;

    var resultCode = (codeElement) ? codeElement.innerText : "error";
    if (resultCode == "error") {
      var exceptionElement = componentDoc.all.exception;
      var args = new Object();
      args.message = "Failed to create component";
      if (exceptionElement) {
        args.details = exceptionElement.innerText;
      } else {
	args.details = componentDoc.body.innerHTML;
      }
      showDialog("/components/dialog/error.html", args);
      return;
    }

    var pageletID = componentDoc.all.pageletID.innerText;

    var componentContainers = getElementsById("DIV", pageletID);
    if (componentContainers.length > 0) {

      for (var c = 0; c < componentContainers.length; c++) {

        var componentContainer = componentContainers[c];
        var componentContent = componentDoc.all.content;

        var forms = componentContent.getElementsByTagName("FORM");
        while (forms.length > 0) {
          forms[0].removeNode(false);
        }

	replaceUnrenderableTags(componentContent, componentDoc);

        // copy the content from pagelet.jsp to the DIV in the editor content
        componentContainer.innerHTML = componentContent.innerHTML;
        if (componentContainer.innerHTML == "") {
          componentContainer.innerHTML = "&nbsp;";
        }
        for (i = 0; i < componentContainer.all.length; i++) {
          var e = componentContainer.all(i);
          if (e.id == "editorConfig" && e.firstChild) {
            var configScript = e.firstChild.nodeValue;
            var config = new Function(configScript);
            config();
            e.removeNode(true); 
          }
          if (e == componentContainer) { continue; }
          e.unselectable = "on";
          if (e.tagName == "A") { e.href = "#"; }
        }
        if (componentDoc.styleSheets.length > 0) {
          var rules = componentDoc.styleSheets[0].rules;
          var editorStyleSheet = document.styleSheets[0];
          for (var i = 0; i < rules.length; i++) {
            var rule = rules.item(i);
            if (! rule.style.cssText) { continue; }
            editorStyleSheet.addRule(rule.selectorText, rule.style.cssText);
          }
        }
        if (gRefreshComponent) {
          var range = document.selection.createRange();
	  range.moveToElementText(componentContainer);
          range.collapse(false);
	  range.move('character');
          range.select();
          gRefreshComponent = false;
        }
      }
      
      var adminPath = componentDoc.all.adminPath ? 
         componentDoc.all.adminPath.innerText : null;
      if (adminPath) {
        var typeName = componentDoc.all.typeName.innerText;
        var componentType = COMPONENTS[typeName];
        if (! componentType) {
          var typeLabel = componentDoc.all.typeLabel.innerText;
  	      componentType = registerComponentType(typeName, 
    	      initMenuDefaultComponent, showDialogDefaultComponent, 
      	    typeLabel, adminPath);
   	    }
      }

    } else if (gLoadingComponentID != null) {
      componentContainer = document.getElementById(gLoadingComponentID);
      if (componentContainer) {
        componentContainer.innerHTML = "<em>The component ID " + 
	gLoadingComponentID + " is invalid.  Please delete this component " +
        "and insert a new one.";
      }
    }

    loadComponents();
  }

  function getComponentsByType(type) {

    var result = new Array();

    var elements = document.getElementsByTagName("DIV");
    for (var i = 0; i < elements.length; i++) {
      var id = elements[i].id;
      if (! id) { continue; }

      var pageletData = id.split("-");
      pageletData.pop();
      var pageletType = pageletData.join("-");

      if (pageletType == type) {
        result.push(elements[i]);
      }
    }

    return result;
  }

  function getElementsById(tagName, id) {

    var result = new Array();

    var elements = document.getElementsByTagName(tagName);
    for (var i = 0; i < elements.length; i++) {
      if (elements[i].id == id) {
        result.push(elements[i]);
      }
    }

    return result;
  }

</script>
<script src="/components/editor/config.jsp">
// This needs to be last so it can override the above functions as necessary
</script>
</head>

<body style="overflow:hidden;margin:0">

<div id="visualContainer">
<div id="toolbarContainer" style="display:inline;position:relative"></div>
<div id="visualEditor" style="display:block" onkeypress="doKeyPress()" 
     onmouseup="doSelectionChange()" onclick="doComponentClick()"
     oncontextmenu="doContextMenu()" ondrop="doDrop()" 
     onkeydown="doKeyDown()" onblur="doBlur()" contenteditable>
</div>
<textarea id="sourceEditor" wrap="on" onkeypress="doSourceKeyPress()"
     onkeydown="doKeyDown()" style="display:none"></textarea>
</div>

<div id="popupContent" style="display:none">
  <div id="tablePicker" class="picker">
  <table cellspacing=2 cellpadding=0>
  </table>
  <div id="cellDimensions" class="pickerLabel">&nbsp;</div>
  <div id="customDimensions" class="pickerLabel"
  onmouseout="this.style.border = 'solid #D4D0C8 2'"
  onmouseover="this.style.border = 'outset white 2'">Custom Size</div>
  </div>
  
  <div id="colorPicker" class="picker">
  <table cellspacing=0 cellpadding=0 style="margin:4">
  </table>
  <div id="colorName" class="pickerLabel">&nbsp;</div>
  </div>

  <div id="specialCharacterPicker" class="picker">
  <table cellspacing=0 cellpadding=0 style="margin:4">
  </table>
  <div id="specialCharacter" class="pickerLabel">&nbsp;</div>
  </div>

  <div id="formElementPicker" class="picker">
  <table cellspacing=0 cellpadding=0 style="margin:4">
  </table>
  <div id="formElement" class="pickerLabel">&nbsp;</div>
  </div>

  <div id="saveStatus" style="background-color:#DDDDDD;padding:16 32 16 32;font-weight:bold;font-family:Arial;font-size:16px;position:absolute;border:2 white outset">
    Saving...
  </div>

</div>

<iframe name="textFrame" id="textFrame" 
        src="about:blank" style="width:1;height:1"></iframe>

<iframe name="componentFrame" id="componentFrame" onload="doComponentLoad()"
        src="/system/blank.html" style="width:1;height:1"></iframe>

<iframe id='rpc' name='rpc'
        src='/system/blank.html' onload='RPCHandler.notify()'
        style='border:0 none;width:1px;height:1px'></iframe>

</body>

</html>
