var ASPxClientCommandConsts = {
 BOLD_COMMAND : "bold",
 ITALIC_COMMAND: "italic",
 UNDERLINE_COMMAND: "underline", 
 STRIKETHROUGH_COMMAND: "strikethrough",
 SUPERSCRIPT_COMMAND: "superscript",
 SUBSCRIPT_COMMAND: "subscript",
 JUSTIFYCENTER_COMMAND: "justifycenter",
 JUSTIFYLEFT_COMMAND: "justifyleft",
 INDENT_COMMAND: "indent",
 OUTDENT_COMMAND: "outdent",
 JUSTIFYRIGHT_COMMAND: "justifyright",
 JUSTIFYFULL_COMMAND: "justifyfull",
 FONTSIZE_COMMAND : "fontsize",
 FONTNAME_COMMAND : "fontname",
 FONTCOLOR_COMMAND: "forecolor",
 BACKCOLOR_COMMAND: "backcolor",
 FORMATBLOCK_COMMAND: "formatblock",
 APPLYCSS_COMMAND: "applycss",
 REMOVEFORMAT_COMMAND: "removeformat",
 UNDO_COMMAND: "undo",
 REDO_COMMAND: "redo",
 COPY_COMMAND: "copy",
 KBCOPY_COMMAND: "kbcopy",
 PASTE_COMMAND: "paste",
 KBPASTE_COMMAND: "kbpaste",
 PASTEFROMWORD_COMMAND: "pastefromword", 
 PASTEFROMWORDDIALOG_COMMAND: "pastefromworddialog",
 CUT_COMMAND: "cut",
 KBCUT_COMMAND: "kbcut",
 SELECT_ALL: "selectall",
 DELETE_COMMAND: "delete", 
 KBDELETE_COMMAND: "kbdelete",
 TEXTTYPE_COMMAND: "texttype",
 NEWPARAGRAPHTYPE_COMMAND: "newparagraphtype",
 LINEBREAKETYPE_COMMAND: "linebreaktype",
 PASTEHTML_COMMAND: "pastehtml",
 RESIZEOBJECT_COMMAND: "resizeobject",
 DRAGDROPOBJECT_COMMAND: "dragdropobject",
 DROPOBJECTFROMEXTERNAL_COMMAND: "dropobjectfromexternal",
 INSERTORDEREDLIST_COMMAND: "insertorderedlist",
 INSERTUNORDEREDLIST_COMMAND: "insertunorderedlist",
 UNLINK_COMMAND: "unlink",
 INSERTLINK_COMMAND: "insertlink",
 INSERTIMAGE_COMMAND: "insertimage",
 CHANGEIMAGE_COMMAND: "changeimage",
 CHECKSPELLING_COMMAND: "checkspelling",
 INSERTIMAGE_DIALOG_COMMAND: "insertimagedialog",
 CHANGEIMAGE_DIALOG_COMMAND: "changeimagedialog",
 INSERTLINK_DIALOG_COMMAND: "insertlinkdialog",
 CHANGELINK_DIALOG_COMMAND: "changelinkdialog",
 INSERTTABLE_DIALOG_COMMAND: "inserttabledialog",
 TABLEPROPERTIES_DIALOG_COMMAND: "tablepropertiesdialog",
 TABLECELLPROPERTIES_DIALOG_COMMAND: "tablecellpropertiesdialog",
 TABLECOLUMNPROPERTIES_DIALOG_COMMAND: "tablecolumnpropertiesdialog",
 TABLEROWPROPERTIES_DIALOG_COMMAND: "tablerowpropertiesdialog",
 PRINT_COMMAND: "print",
 INSERTTABLE_COMMAND: "inserttable",
 CHANGETABLE_COMMAND: "changetable",
 CHANGETABLECELL_COMMAND: "changetablecell",
 CHANGETABLEROW_COMMAND: "changetablerow",
 CHANGETABLECOLUMN_COMMAND: "changetablecolumn",
 DELETETABLE_COMMAND: "deletetable",
 DELETETABLEROW_COMMAND: "deletetablerow",
 DELETETABLECOLUMN_COMMAND: "deletetablecolumn",
 INSERTTABLECOLUMNTOLEFT_COMMAND: "inserttablecolumntoleft",
 INSERTTABLECOLUMNTORIGHT_COMMAND: "inserttablecolumntoright", 
 INSERTTABLEROWBELOW_COMMAND: "inserttablerowbelow",
 INSERTTABLEROWABOVE_COMMAND: "inserttablerowabove",
 SPLITTABLECELLHORIZONTALLY_COMMAND: "splittablecellhorizontally",
 SPLITTABLECELLVERTICALLY_COMMAND: "splittablecellvertically", 
 MERGETABLECELLRIGHT_COMMAND: "mergetablecellright",
 MERGETABLECELLDOWN_COMMAND: "mergetablecelldown",
 CheckSpellingCore_COMMAND: "checkspellingcore",
 Start_COMMAND: "start"
};
var ASPxCommandMessageConsts = new Object();
ASPxCommandMessageConsts[ASPxClientCommandConsts.CUT_COMMAND] = "Please use Ctrl+X to Cut";
ASPxCommandMessageConsts[ASPxClientCommandConsts.PASTE_COMMAND] = "Please use Ctrl+V to Paste";
ASPxCommandMessageConsts[ASPxClientCommandConsts.COPY_COMMAND] = "Please use Ctrl+C to Copy";
Command = _aspxCreateClass(null, {
 constructor: function(cmdID) {
  this.commandID = cmdID;
 },
 Execute: function(cmdValue, editor) {
  return true;
 },
 GetCommandID: function() {
  return this.commandID;
 }, 
 GetState: function(editor) {
  return true;
 },
 GetValue: function(editor) {
  return null;
 },
 IsDefaultAction: function(editor) {
  return false; 
 },
 IsImmediateExecution: function() {
  return false;
 },
 IsHtmlChangeable: function() {
  return true;
 },
 IsLocked: function(editor) {
  return false;
 },
 IsReversable: function() {
  return true;
 }
});
HtmlProcessingCommand = _aspxCreateClass(Command, {
 SaveSelectionRangeInfo: function(selectionInfo, editor) {
  this.startR = null;
  this.endR = null;  
  if (__aspxIE && !selectionInfo.IsControl()) {
   var range = editor.GetDesignViewIFrameDocument().selection.createRange();
   this.startR = range.duplicate();
   this.endR = range.duplicate();
   this.startR.collapse();
   this.endR.collapse(false);
  }
 },
 RestoreSelectionRange: function(editor) {
  if (__aspxIE) {
   try {
    var newRange = editor.GetDesignViewIFrameDocument().selection.createRange();
    newRange.setEndPoint("StartToStart",this.startR);
    newRange.setEndPoint("EndToEnd",this.endR);
    newRange.select();
   }
   catch (e) {
   }
  } else {
   if (__aspxOpera)
    editor.GetDesignViewIFrameDocument().body.focus();
   if (!__aspxWebKitFamily) {
    var selection = editor.GetDesignViewIFrameWindow().getSelection();
    var rng = selection.getRangeAt(0);
    rng.collapse(false);
   }
  }
 }
});
BrowserCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  Command.prototype.Execute.call(this);
  var contentAreaDoc = editor.GetDesignViewIFrameDocument();
  if (!this.NeedUseCss())
      contentAreaDoc.execCommand(this.GetUseCSSCommandName(), false, false);
     var isSuccessfully = contentAreaDoc.execCommand(this.GetCommandName(), false, this.GetCorrectedValue(cmdValue));
  if (!this.NeedUseCss())
      contentAreaDoc.execCommand(this.GetUseCSSCommandName(), false, true);
  editor.SetFocus();
  return isSuccessfully;
 },
 GetCommandName: function() {
  return this.commandID;
 }, 
 GetCorrectedValue: function(value) {
  return value;  
 },
 GetState: function(editor) {
  var ret = true;
  if (!this.IsAlwaysEnabledCommand(this.commandID)) {      
   try {
    ret = this.TryGetState(editor);
   }
   catch(ex) { ret = false; }
  }
  return ret;
 },
 GetValue: function(editor) {  
  var ret = null;
  try {
   ret = this.TryGetValue(editor);
  }
  catch(e) {}
  return ret;
 },
 GetUseCSSCommandName: function(doc) {
  return __aspxNetscapeFamily ? "styleWithCSS" : "useCSS";
 },
 IsLocked: function(editor) {
  var ret = this.TryGetIsLocked(editor);
  if (__aspxOpera && ret) {
   try { 
    ret = !this.TryGetState(editor); 
   }
   catch(ex) { ret = false; }
  }
  return ret;
 },
 TryGetState: function(editor) {
  return editor.GetDesignViewIFrameDocument().queryCommandState(this.GetCommandName()); 
 },
 TryGetValue: function(editor) {
  return editor.GetDesignViewIFrameDocument().queryCommandValue(this.GetCommandName());
 },
 TryGetIsLocked: function(editor) {
  try {
   return !editor.GetDesignViewIFrameDocument().queryCommandEnabled(this.GetCommandName());
  } catch(e) {}
  return true;
 },
 IsAlwaysEnabledCommand: function(commandID) {
  return this.commandID == ASPxClientCommandConsts.FONTSIZE_COMMAND || this.commandID == ASPxClientCommandConsts.FONTNAME_COMMAND;
 },
 NeedUseCss: function() {
  return true;
 }
});
var __aspxHEFakeElementClassName = "dxHClass";
ApplyCssCommand = _aspxCreateClass(HtmlProcessingCommand, {
 Execute: function(cmdValue, editor) {
  cmdValue.tagName = _aspxTrim(cmdValue.tagName);
  cmdValue.cssClass = _aspxTrim(cmdValue.cssClass);
  if (this.IsExclusionTagName(cmdValue.tagName)) return false;
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  this.SaveSelectionRangeInfo(curSelection, editor);
  var parentTagName = curSelection.GetParentElement().tagName.toUpperCase();
  if (this.IsExclusionTagName(parentTagName) && (cmdValue.tagName == "")) {
   this.SetClassNameAttribute(curSelection.GetParentElement(), cmdValue.cssClass);
  }
  else if (curSelection.GetText()!= "") {
   var selInfo = editor.GetEditorSelectionInfo(true);
   for (var i = 0; i < selInfo.allElements.length; i++) {
    var curElem = selInfo.allElements[i];    
    var targetParentElem = this.GetEqualParentElement(curElem, cmdValue.tagName, cmdValue.cssClass);
    if (!_aspxIsExists(targetParentElem)) {
     var elemInnerHtml = curElem.innerHTML;
     var newElement = null;
     if (cmdValue.tagName) {
      var newElement = null;
      targetParentElem = this.GetParentElementWithTagName(curElem, cmdValue.tagName);
      if (_aspxIsExists(targetParentElem)) 
       this.SetClassNameAttribute(targetParentElem, cmdValue.cssClass);
      else {
       newElement = editor.GetDesignViewIFrameDocument().createElement(cmdValue.tagName);
       this.SetClassNameAttribute(newElement, cmdValue.cssClass);
       }
     }
     else { 
      newElement = editor.GetDesignViewIFrameDocument().createElement("span");
      this.SetClassNameAttribute(newElement, __aspxHEFakeElementClassName);
      newElement.className += " " + cmdValue.cssClass;
     }
     if (newElement) {
      _aspxSetInnerHtml(newElement, elemInnerHtml);
      curElem.innerHTML = '';
      curElem.appendChild(newElement);
     }
    }
   }
   editor.DeleteNewAddedFontElements(selInfo);
   if (cmdValue.tagName == "")
    this.OptimizeChildCssClass(editor.GetDesignViewIFrameDocument().body, cmdValue.cssClass);
  }
  this.RestoreSelectionRange(editor);
  return true;
 },   
 GetValue: function(editor) {
  return (__aspxIE) ? this.GetValueIE(editor) : this.GetValueMoz(editor);
 },
 GetValueIE : function(editor) {    
  var contentAreaDoc = editor.GetDesignViewIFrameDocument();
  var curSelection = contentAreaDoc.selection;
  if (!curSelection) return "";
  var selRange = curSelection.createRange();
  var parentElement = (selRange.length > 0 ? selRange(0) : selRange.parentElement());
  return this.GetValueByElement(parentElement);
 },
 GetValueMoz: function(editor) {
  var contentWindow = editor.GetDesignViewIFrameWindow(); 
  var curSelection = contentWindow.getSelection();
  if (!curSelection || curSelection.rangeCount != 1) return "";
  var startNode = (curSelection.anchorNode.nodeType != 3
       ? curSelection.anchorNode
       : curSelection.anchorNode.parentNode);
  var endNode = (curSelection.focusNode.nodeType != 3
       ? curSelection.focusNode
       : curSelection.focusNode.parentNode);       
  if (startNode != endNode)
   return "";
  var restoreSelection = ASPxClientHtmlEditorSelection.Create(editor);
  return this.GetValueByElement(restoreSelection.GetParentElement());
 },
 GetValueByElement: function(element) {
  var tagName = "";
  var cssClass = "";
  if (element && element.nodeType == 1 && element.tagName.toLowerCase() != "body") {
   tagName = element.tagName.toLowerCase();
   cssClass = element.className;
  }
  return { tagName: tagName, cssClass: cssClass };
 },
 IsExclusionTagName: function(tagName) {
  tagName = tagName.toUpperCase();
  return tagName == "IMG" || tagName == "TABLE" || tagName == "OBJECT" || tagName == "EMBED";
 },
 OptimizeChildCssClass: function(parentElement, targetCssClass) {
  var fakeElementCollection = _aspxGetChildsByClassName(parentElement, __aspxHEFakeElementClassName);
  var newElementArray = new Array();
  for (var i = 0; i < fakeElementCollection.length; i++) {
   var newElement = this.TryRemoveFakeElement(fakeElementCollection[i], targetCssClass);
   if (!newElement)
    this.RemoveFakeCssClass(fakeElementCollection[i]);
   else
    _aspxArrayPush(newElementArray, newElement);
  }
  this.TryMoveCssClassToParent(newElementArray, targetCssClass);
 },
 TryRemoveFakeElement: function(fakeElement, targetCssClass) {
  var parentElement = fakeElement.parentNode;
  var ret = null;
  if ((parentElement.tagName.toUpperCase() != "BODY") && 
    (parentElement.childNodes.length == 1)) {
   var elemInnerHtml = fakeElement.innerHTML;
   _aspxRemoveElement(fakeElement);
   _aspxSetInnerHtml(parentElement, elemInnerHtml);
   this.SetClassNameAttribute(parentElement, targetCssClass);
   ret = parentElement;
  } else if(targetCssClass == "")
   _aspxRemoveOuterTags(fakeElement);
  return ret;
 },
 TryMoveCssClassToParent: function(elements, targetCssClass) {
  for (var i = 0; i < elements.length; i++) {
   var parentElement = elements[i].parentNode;
   var parentElementTagName = parentElement.tagName.toUpperCase();
   if ((parentElementTagName == "OL" || parentElementTagName == "UL") && 
    (elements[i].className == targetCssClass)) {
    this.ProcessListElements(parentElement, targetCssClass);
   }
  }
 },
 ProcessListElements: function(mainListElement, targetCssClass) {
  var listItemElements = _aspxGetElementsByTagName(mainListElement, "li");
  var isAllItemNeedClear = true;
  for (var i = 0 ; i< listItemElements.length; i++) {
   if (listItemElements[i].className != targetCssClass) {
    isAllItemNeedClear = false;
    return;
   }
  }
  if (isAllItemNeedClear) {
   this.SetClassNameAttribute(mainListElement, targetCssClass);
   for (var i = 0 ; i< listItemElements.length; i++)
    this.SetClassNameAttribute(listItemElements[i], "");
  }
 },
 RemoveFakeCssClass: function(sourceElement) {
  var sourceCssClass = sourceElement.className;
  sourceCssClass = sourceCssClass.replace(__aspxHEFakeElementClassName, "");
  sourceCssClass = _aspxTrim(sourceCssClass);
  sourceElement.className = sourceCssClass;
 },
 GetParentElementWithTagName: function(element, tagName) {
  var parentElement = element.parentNode;
  return  parentElement.tagName.toUpperCase() == tagName.toUpperCase() ? parentElement : null;
 },
 GetEqualParentElement: function(elem, tagName, cssClass) {
  var ret = null;
  if (tagName && cssClass)
   ret = _aspxGetParentByTagNameAndAttributeValue(elem, tagName, "class", cssClass);
  else if (cssClass)
   ret = _aspxGetParentByClassName(elem);
  return ret;
 }, 
 SetClassNameAttribute: function(element, className) {
  if (className)
   element.className = className;
  else
   _aspxRemoveAttribute(element, this.GetClassAttributeName());
 },
 GetClassAttributeName: function(){
  return !__aspxIE || __aspxBrowserVersion >= 8 ? "class" : "className";
 } 
});
FontColorBrowserCommand = _aspxCreateClass(BrowserCommand, {
 Execute: function(cmdValue, editor) {
  if (!cmdValue)
   cmdValue = editor.currentFontColor;
  else
   editor.currentFontColor = cmdValue;
  var hyperlinks;
  if(__aspxIE || __aspxWebKitFamily)
   hyperlinks = this.SaveHyperlinks(editor);
  var commandExecResult = BrowserCommand.prototype.Execute.call(this, cmdValue, editor);
  if(hyperlinks)
   this.RestoreHyperlinks(hyperlinks);
  return commandExecResult;
 },
 GetValue: function(editor) {
  return _aspxColorToHexadecimal(BrowserCommand.prototype.GetValue.call(this, editor));
 },
 NeedUseCss: function() {
  return !__aspxNetscapeFamily;
 },
 TryGetValue: function(editor) {
  return editor.currentFontColor;
 },
 SaveHyperlinks: function(htmlEditor) {
  var hyperlinks = [ ];
  var selection = ASPxClientHtmlEditorSelection.Create(htmlEditor);
  var selectionContainer = selection.GetParentElement();
  var anchors = _aspxGetElementsByTagName(selectionContainer, "A");
  for(var i = 0; i < anchors.length; i++) {
   var anchor = anchors[i];
   if(this.IsHyperlink(anchor)) {
    hyperlinks.push(
     {
      element: anchor,
      innerHTML: anchor.innerHTML
     }
    );
   }
  }
  return hyperlinks;
 },
 RestoreHyperlinks: function(hyperlinks) {
  for(var i = 0; i < hyperlinks.length; i++) {
   var hyperlink = hyperlinks[i];
   hyperlink.element.innerHTML = hyperlink.innerHTML;
  }
 },
 IsHyperlink: function(anchor) {
  return typeof(anchor.href) == "string" && anchor.href.length > 0;
 }
});
FontSizeBrowserCommand  = _aspxCreateClass(BrowserCommand, {
 GetValue: function(editor) {
  var value = BrowserCommand.prototype.GetValue.call(this, editor);
  if (__aspxWebKitFamily) {
   var index = _aspxGetDefaultSafariFontSizesInPixelHashTable()[value];
   value = index > -1 ? index + 1 : null;
  }
  return value;
 }
});
BgColorBrowserCommand = _aspxCreateClass(FontColorBrowserCommand, {
 Execute: function(cmdValue, editor) {
  if (!cmdValue)
   cmdValue = editor.currentBgColor;
  else
   editor.currentBgColor = cmdValue;
  BrowserCommand.prototype.Execute.call(this, cmdValue, editor);
 },
 GetCommandName: function() {
  return __aspxIE ? BrowserCommand.prototype.GetCommandName.call(this) : "HiliteColor";
 },
 NeedUseCss: function() {
  return true;
 },
 TryGetValue: function(editor) {
  return editor.currentBgColor;
 }
});
InsertListCommand = _aspxCreateClass(BrowserCommand, {
 GetState: function(editor) {
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  var tagName = "";
  switch (this.GetCommandName()) {
   case ASPxClientCommandConsts.INSERTORDEREDLIST_COMMAND:
    tagName = "OL";break;
   case ASPxClientCommandConsts.INSERTUNORDEREDLIST_COMMAND:
    tagName = "UL";break;
  }
  return _aspxIsExists(_aspxGetParentByTagName(curSelection.GetParentElement(), tagName));
 }
});
InsertListCommand = _aspxCreateClass(BrowserCommand, {
 GetState: function(editor) {
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  var tagName = "";
  switch (this.GetCommandName()) {
   case ASPxClientCommandConsts.INSERTORDEREDLIST_COMMAND:
    tagName = "OL";break;
   case ASPxClientCommandConsts.INSERTUNORDEREDLIST_COMMAND:
    tagName = "UL";break;
  }
  return _aspxIsExists(_aspxGetParentByTagName(curSelection.GetParentElement(), tagName));
 }
});
IndentCommand = _aspxCreateClass(BrowserCommand, {
 Execute: function(cmdValue, editor) {
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  var selectedList = IndentCommand.GetMainParentList(curSelection.GetParentElement());
  if (_aspxIsExists(selectedList))
   this.IndentList(selectedList, curSelection, editor);
  else
   BrowserCommand.prototype.Execute.call(this, cmdValue, editor);
  return true;
 },
 GetState: function(editor) {
  return false;
 },
 IsLocked: function(editor) {
  if (__aspxOpera)
   return this.TryGetIsLocked(editor);
  return BrowserCommand.prototype.IsLocked.call(this, editor);
 },
 TryGetIsLocked: function(editor) {
  var isLocked = false;
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  var selectedList = IndentCommand.GetParentList(curSelection.GetParentElement());
  if (_aspxIsExists(selectedList)) {
   selectedList = IndentCommand.GetMainParentList(curSelection.GetParentElement());
   isLocked = !this.IsIndentionAllowed(selectedList,
            curSelection.GetStartContainer(),
            curSelection.GetEndContainer(), editor);
  }
  else
   isLocked = BrowserCommand.prototype.TryGetIsLocked.call(this, editor);
  return isLocked;
 },
 IndentList: function(listNode, selection, editor) {
  var bookmark = selection.GetExtendedBookmark();
  selection = ASPxClientHtmlEditorSelection.Create(editor);
  var newlistNode = IndentCommand.IndentListCore(listNode, selection.GetStartContainer(),
              selection.GetEndContainer(), this.GetIndent());
  listNode.parentNode.replaceChild(newlistNode, listNode);
  selection.SelectExtendedBookmark(bookmark);
  if (!__aspxIE) 
   editor.SetFocus();
 },
 IsIndentionAllowed: function(listNode, startItemNode, endItemNode, htmlEditor) {
  startItemNode = IndentCommand.EnsureListItemNode(startItemNode);
  endItemNode = IndentCommand.EnsureListItemNode(endItemNode);
  var indent = this.GetIndent();
  var listItemArray = IndentCommand.GetListItemArray(listNode, 0, null);
  listItemArray = IndentCommand.IndentListItemsInItemArray(listItemArray, startItemNode, endItemNode, indent);
  if (listItemArray == null || listItemArray[0].level != 0)
   return false;
  for (var i = 1; i < listItemArray.length; i++) {
   if (indent > 0) {
    if (listItemArray[i].level - listItemArray[i - 1].level > indent)
     return false;
   }
   else if (listItemArray[i].level < 0)
    return false;
  }
  return true;
 },
 GetIndent: function() {
  var indent = 0;
  switch (this.GetCommandName()) {
   case ASPxClientCommandConsts.INDENT_COMMAND:
    indent = 1; break;
   case ASPxClientCommandConsts.OUTDENT_COMMAND:
    indent = -1; break;
  }
  return indent;
 }
});
IndentCommand.IndentListCore = function(listNode, startNode, endNode, indent) {
 startNode = IndentCommand.EnsureListItemNode(startNode);
 endNode = IndentCommand.EnsureListItemNode(endNode);
 var listItemArray = IndentCommand.GetListItemArray(listNode, 0, null);
 var itemArray = IndentCommand.IndentListItemsInItemArray(listItemArray, startNode, endNode, indent);
 return IndentCommand.GenerateListByItemArray(itemArray);
}
IndentCommand.GetListItemArray = function(listNode, currentLevel, itemArray, parentItemIndex) {
 if (!_aspxIsExists(itemArray))
  itemArray = new Array();
 if (!_aspxIsExists(parentItemIndex))
  parentItemIndex = -1;
 var curListItem = _aspxGetChildByTagName(listNode, "LI" ,0); 
 while(_aspxIsExists(curListItem)) {
  _aspxArrayPush(itemArray, { 'level': currentLevel, 'node' : curListItem, 'parentItemIndex' : parentItemIndex });
  var nestedListNode = IndentCommand.GetChildList(curListItem);
  if (_aspxIsExists(nestedListNode))
   itemArray = IndentCommand.GetListItemArray(nestedListNode, currentLevel + 1, itemArray, itemArray.length - 1);
  curListItem = IndentCommand.GetNextListItem(curListItem);
 }
 return itemArray;
}
IndentCommand.IndentListItemsInItemArray = function(itemArray, startListItem, endListItem, indent) {
 var startItemIndex = -1;
 var endItemIndex = -1;
 for (var i = 0; i < itemArray.length; i++) {
  if (itemArray[i].node == startListItem)
   startItemIndex = i;
  if (itemArray[i].node == endListItem)
   endItemIndex = i;
  if (startItemIndex != -1 && endItemIndex != -1)
   break;
 }
 if (startItemIndex == -1 || endItemIndex == -1)
  return null;
 for (var i = startItemIndex; i <= endItemIndex; i++)
  itemArray[i].level += indent;
 if (indent < 0) {
  for (var i = 0; i < itemArray.length; i++) {
   if (itemArray[i].parentItemIndex != -1) {
    var parentLevel = itemArray[itemArray[i].parentItemIndex].level;
    if (itemArray[i].level - parentLevel > 1)
     itemArray[i].level += indent;
   }
  }
 }
 return itemArray;
}
IndentCommand.GenerateListByItemArray = function(itemArray) {
 if (itemArray.length <= 0)
  return null;
 var doc = itemArray[0].node.document;
 var listNodeByLevel = [];
 var listItemNodeArray = [];
 var curLevel = 0;
 for (var i = 0; i < itemArray.length; i++) {
  var curItem = itemArray[i];
  if (curLevel > curItem.level) {
   for (var j = curItem.level + 1; j <= curLevel; j++)
    listNodeByLevel[j] = null;
  }
  if (!_aspxIsExists(listNodeByLevel[curItem.level])) {
   var oldListNode = IndentCommand.GetParentList(curItem.node);
   var newListNode = oldListNode.cloneNode(false);
   listNodeByLevel[curItem.level] = newListNode;
   if (curItem.level - 1 >= 0)
    listItemNodeArray[curItem.level - 1].appendChild(newListNode);
  }
  var clonedListItem = IndentCommand.CloneListItem(curItem.node, doc);
  listItemNodeArray[curItem.level] = clonedListItem;
  listNodeByLevel[curItem.level].appendChild(clonedListItem);
  curLevel = curItem.level;
 }
 return listNodeByLevel[0];
}
IndentCommand.EnsureListItemNode = function(node) {
 while (node) {
  var tagName = "";
  var parentNode = node.parentNode;
  if (parentNode && parentNode.nodeType == 1)
   tagName = parentNode.tagName.toUpperCase();
  if (tagName == "OL" || tagName == "UL")
   break;
  node = parentNode;
 }
 return node;
}
IndentCommand.CloneListItem = function(item, doc) {
 var newItem = item.cloneNode(true);
 newItem.innerHTML = "";
 for (var i = 0 ; i < item.childNodes.length; i++) {
  var tagName = item.childNodes[i].tagName;
  tagName = _aspxIsExists(tagName) ? tagName.toUpperCase() : "";
  if ((tagName != "UL") && (tagName != "OL"))
   newItem.appendChild(item.childNodes[i].cloneNode(true));
 }
 return newItem;
}
IndentCommand.GetChildList = function(elem) {
 for (var i = 0 ; i < elem.childNodes.length; i++) {
  var tagName = elem.childNodes[i].tagName;
  tagName = _aspxIsExists(tagName) ? tagName.toUpperCase() : ""; 
  if ((tagName == "UL") || (tagName == "OL"))
   return elem.childNodes[i];
 }
 return null;
}
IndentCommand.GetNextListItem = function(listItemNode) {
 var nextListItemNode = listItemNode.nextSibling;
 while (nextListItemNode != null && nextListItemNode.nodeType != 1)
  nextListItemNode = nextListItemNode.nextSibling;
 return nextListItemNode;
}
IndentCommand.GetMainParentList = function(elem) {
 var lastListNode = null;
 while (elem) {
  if (elem.nodeType == 1) {
   var tagName = elem.tagName.toUpperCase();
   if (tagName == "UL" || tagName == "OL")
    lastListNode = elem;
  }
  elem = elem.parentNode;
 }
 return lastListNode;
}
IndentCommand.GetParentList = function(elem) {
 var selectedList = _aspxGetParentByTagName(elem, "OL");
 if (!_aspxIsExists(selectedList))
  selectedList = _aspxGetParentByTagName(elem, "UL");
 return selectedList;
}
var __aspxEmptyBorderTableClassName = "dxEmptyBorderTable";
var __aspxHESizeTypeRegExp = new RegExp("([0-9]*[,.]?[0-9]*)(px|%)");
var _aspxHETableHelper = {
 AppendEmptyBorderClassName: function(elem) {
  if (elem.className.indexOf(__aspxEmptyBorderTableClassName) > -1)
   return;
  elem.className += " " + __aspxEmptyBorderTableClassName;
 },
 IsEmptyBorder: function(table) {
  if (!_aspxIsExists(table))
   return false;
  return table.border == "0" || !_aspxIsExists(table.border) || table.border == "";
 },
 ReplaceTableStyleBorderByAttribute: function(table) {
  var tableStyle = table.style;
  if (tableStyle.borderLeftColor &&
   (tableStyle.borderLeftColor == tableStyle.borderRightColor) &&
   (tableStyle.borderRightColor == tableStyle.borderBottomColor) &&
   (tableStyle.borderBottomColor == tableStyle.borderTopColor)) {
   this.SetTableBorderColor(table, tableStyle.borderBottomColor);
   tableStyle.borderLeftColor = "";
   _aspxRemoveStyleAttribute(tableStyle, "borderLeftColor");
   tableStyle.borderRightColor = "";
   _aspxRemoveStyleAttribute(tableStyle, "borderRightColor");
   tableStyle.borderTopColor = "";
   _aspxRemoveStyleAttribute(tableStyle, "borderTopColor");
   tableStyle.borderBottomColor = "";
   _aspxRemoveStyleAttribute(tableStyle, "borderBottomColor");
  }
 },
 RemoveEmptyBorderClassName: function(elem) {
  elem.className = elem.className.replace(__aspxEmptyBorderTableClassName, "");
 },
 GetTable: function(element) {
  return _aspxGetParentByTagName(element, "TABLE");
 },
 GetTableRow: function(elem) {
  if (elem && elem.nodeType == 1 && elem.tagName.toUpperCase() == "TR")
   return elem;
  var cell = this.GetTableCell(elem);
  if (_aspxIsExists(cell))
   return cell.parentNode;
  return null;
 },
 GetTableCellBySelection: function(startElem, endElem) {
  var cell = _aspxHETableHelper.GetTableCell(startElem);
  if (!_aspxIsExists(cell) && endElem != null) {
   cell = _aspxHETableHelper.GetTableCell(endElem);
   if (__aspxSafari && startElem && startElem.tagName.toUpperCase() == "TR") { 
    var index = cell.cellIndex - 1;
    if (index < 0)
     cell = startElem.cells[startElem.cells.length - 1];
    else
     cell = startElem.cells[index];
   }
  }
  return cell;
 },
 GetTableCell: function(element) {
  if (!element)
   return null;
  if (element.nodeType == "1" &&
   (element.tagName.toUpperCase() == "TD" || element.tagName.toUpperCase() == "TH"))
   return element;
  var cell = _aspxGetParentByTagName(element, "TD");
  if (!_aspxIsExists(cell))
   cell = _aspxGetParentByTagName(element, "TH");
  return cell;
 },
 GetTableProperties: function(table) {
  var tableInfoObject = {
   borderWidth: 0,
   borderColor: null,
   backgroundColor: null,
   width: null,
   height: null,
   cellPadding: 0,
   cellSpacing: 0,
   align: null,
   accessibility: null
  };
  if (table.className.indexOf(__aspxEmptyBorderTableClassName) == -1) {
   if (_aspxIsExists(table.border))
    tableInfoObject.borderWidth = table.border;
   var borderColor = this.GetTableBorderColor(table);
   if (_aspxIsExists(borderColor))
    tableInfoObject.borderColor = borderColor;
  }
  if (table.style.backgroundColor)
   tableInfoObject.backgroundColor = table.style.backgroundColor;
  if (table.style.width)
   tableInfoObject.width = table.style.width;
  if (table.style.height)
   tableInfoObject.height = table.style.height;
  tableInfoObject.cellPadding = table.cellPadding;
  tableInfoObject.cellSpacing = table.cellSpacing;
  if (table.align)
   tableInfoObject.align = table.align;
  var accessibility = { caption: "", summary: "", headers: "" };
  accessibility.headers = this.GetAccessibilityHeadersValue(table);
  accessibility.caption = this.GetAccessibilityCaption(table);
  accessibility.summary = table.summary;
  tableInfoObject.accessibility = accessibility;
  return tableInfoObject;
 },
 SetTableProperties: function(table, properties, htmlEditor) {
  if (properties) {
   if (_aspxIsExists(properties.borderWidth))
    this.SetTableBorderWidth(table, properties.borderWidth, htmlEditor);
   if (_aspxIsExists(properties.borderColor))
    this.SetTableBorderColor(table, properties.borderColor);
   this.SetBackgroundColor(table, properties.backgroundColor);
   table.cellSpacing = properties.cellSpacing;
   table.cellPadding = properties.cellPadding;
   if (properties.width)
    table.style.width = properties.width;
   else if (_aspxIsExists(table.style.width)) {
    _aspxRemoveAttribute(table, "width");
    _aspxRemoveStyleAttribute(table, "width");
   }
   if (properties.height)
    table.style.height = properties.height;
   else if (_aspxIsExists(table.style.height)) {
    _aspxRemoveAttribute(table, "height");
    table.style.height = "";
    _aspxRemoveStyleAttribute(table, "height");
   }
   if (properties.align)
    table.align = properties.align;
   else if (_aspxIsExists(table.align)) {
    table.align = "";
    _aspxRemoveAttribute(table, "align");
   }
   if (properties.accessibility)
    this.SetTableAccessibility(table, properties.accessibility);
  }
 },
 SetTableBorderWidth: function(table, borderWidth, htmlEditor) {
  if (__aspxFirefox && table.style.borderCollapse == "collapse") {
   var tempTableId = ASPxClientSelection.GetMarkerID();
   _aspxChangeAttribute(table, "id", tempTableId);
   table.style.borderCollapse = "separate";
   this.currentHtmlEditor = htmlEditor;
   _aspxSetTimeout("_aspxHETableHelper.SetTableBorderWidthDelay('" + tempTableId + "'," + borderWidth + ")", 100);
  }
  else {
   _aspxSetAttribute(table, "border", borderWidth);
   this.SetEmptyTableBorderClass(table);
  }
 },
 SetTableBorderWidthDelay: function(tableId, borderWidth) {
  var table = _aspxGetElementByIdInDocument(this.currentHtmlEditor.GetDesignViewIFrameDocument(), tableId);
  _aspxSetAttribute(table, "border", borderWidth);
  table.style.borderCollapse = "collapse";
  _aspxRestoreAttribute(table, "id");
  this.SetEmptyTableBorderClass(table);
  this.currentHtmlEditor.commandManager.UpdateLastItemInRestoreHtmlArray();
  this.currentHtmlEditor = null;
 },
 SetEmptyTableBorderClass: function(table) {
  if (this.IsEmptyBorder(table))
   this.AppendEmptyBorderClassName(table);
  else
   this.RemoveEmptyBorderClassName(table);
 },
 GetCellProperties: function(cell) {
  var cellInfo = {
   backgroundColor: null,
   align: null,
   vAlign: null
  };
  if (cell.style.textAlign)
   cellInfo.align = cell.style.textAlign;
  if (cell.style.verticalAlign)
   cellInfo.vAlign = cell.style.verticalAlign;
  if (cell.style.backgroundColor)
   cellInfo.backgroundColor = cell.style.backgroundColor;
  return cellInfo;
 },
 SetCellProperties: function(cell, properties) {
  if (properties.vAlign)
   cell.style.verticalAlign = properties.vAlign.toLowerCase();
  else if (_aspxIsExists(cell.vAlign))
   _aspxRemoveStyleAttribute(cell, "verticalAlign");
  if (properties.align)
   cell.style.textAlign = properties.align.toLowerCase();
  else if (_aspxIsExists(cell.align))
   _aspxRemoveStyleAttribute(cell, "textAlign");
  this.SetBackgroundColor(cell, properties.backgroundColor);
 },
 SetCellPropertiesForAllCell: function(table, properties) {
  for (var i = 0; i < table.rows.length; i++) {
   for (var j = 0; j < table.rows[i].cells.length; j++)
    this.SetCellProperties(this.GetCell(table, i, j), properties);
  }
 },
 SetColumnProperties: function(cell, properties) {
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
  var colSpan = this.GetColSpan(cell);
  for (var i = 0; i < tableModel.length; i++) {
   for (var j = columnIndex; j < columnIndex + colSpan; j++) {
    var curCell = tableModel[i][j];
    if (this.GetColSpan(curCell) <= colSpan) {
     this.SetCellProperties(curCell, properties);
     if (properties.width)
      curCell.style.width = properties.width;
     else if (_aspxIsExists(curCell.style.width)) {
      curCell.style.width = "";
      _aspxRemoveStyleAttribute(curCell, "width");
     }
    }
   }
  }
 },
 GetColumnProperties: function(cell) {
  var columnInfo = {
   backgroundColor: null,
   width: null,
   align: null,
   vAlign: null
  };
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
  var colSpan = this.GetColSpan(cell);
  var curCellInfo = this.GetCellProperties(cell);
  var align = columnInfo.align = curCellInfo.align;
  var vAlign = columnInfo.vAlign = curCellInfo.vAlign;
  var backgroundColor = columnInfo.backgroundColor = curCellInfo.backgroundColor;
  var maxCellWidth = 0;
  var isWidthDefined = true;
  for (var i = 0; i < tableModel.length; i++) {
   for (var j = columnIndex; j < columnIndex + colSpan; j++) {
    var curCell = tableModel[i][j];
    if (this.GetColSpan(curCell) <= colSpan) {
     var curCellInfo = this.GetCellProperties(curCell);
     if (curCell.style.width && _aspxGetClearClientWidth(curCell) > maxCellWidth)
      maxCellWidth = curCell.style.width;
     if (align != curCellInfo.align)
      columnInfo.align = null;
     if (vAlign != curCellInfo.vAlign)
      columnInfo.vAlign = null;
     if (backgroundColor != curCellInfo.backgroundColor)
      columnInfo.backgroundColor = null;
     if (isWidthDefined) {
      var curCellColSpan = this.GetColSpan(curCell);
      if (curCellColSpan != colSpan)
       isWidthDefined = false;
      else if (columnIndex != this.GetColumnIndexByTableModel(tableModel, i, curCell))
       isWidthDefined = false;
     }
    }
   }
  }
  if (isWidthDefined && this.ParseSizeString(maxCellWidth).value > 0)
   columnInfo.width = maxCellWidth;
  return columnInfo;
 },
 GetRowProperties: function(cell) {
  var rowInfo = {
   backgroundColor: null,
   height: null,
   align: null,
   vAlign: null
  };
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var rowSpan = this.GetRowSpan(cell);
  var curCellInfo = this.GetCellProperties(cell);
  var align = rowInfo.align = curCellInfo.align;
  var vAlign = rowInfo.vAlign = curCellInfo.vAlign;
  var backgroundColor = rowInfo.backgroundColor = curCellInfo.backgroundColor;
  var maxCellHeight = 0;
  var isHeightDefined = true;
  for (var i = row.rowIndex; i < row.rowIndex + rowSpan; i++) {
   for (var j = 0; j < tableModel[i].length; j++) {
    var curCell = tableModel[i][j];
    if (this.GetRowSpan(curCell) <= rowSpan) {
     var curCellInfo = this.GetCellProperties(curCell);
     if (curCell.style.height && _aspxGetClearClientHeight(curCell) > maxCellHeight)
      maxCellHeight = curCell.style.height;
     if (align != curCellInfo.align)
      rowInfo.align = null;
     if (vAlign != curCellInfo.vAlign)
      rowInfo.vAlign = null;
     if (backgroundColor != curCellInfo.backgroundColor)
      rowInfo.backgroundColor = null;
     if (isHeightDefined) {
      var curCellRowSpan = this.GetRowSpan(curCell);
      if (curCellRowSpan != rowSpan)
       isHeightDefined = false;
      else if (row.rowIndex != curCell.parentNode.rowIndex)
       isHeightDefined = false;
     }
    }
   }
  }
  if (isHeightDefined && this.ParseSizeString(maxCellHeight).value > 0)
   rowInfo.height = maxCellHeight;
  return rowInfo;
 },
 SetRowProperties: function(cell, properties) {
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
  var rowSpan = this.GetRowSpan(cell);
  var rowIndex = row.rowIndex;
  for (var i = rowIndex; i < rowIndex + rowSpan; i++) {
   for (var j = 0; j < tableModel[i].length; j++) {
    if (this.GetRowSpan(tableModel[i][j]) <= rowSpan) {
     this.SetCellProperties(tableModel[i][j], properties);
     if (properties.height)
      tableModel[i][j].style.height = properties.height;
     else if (_aspxIsExists(tableModel[i][j].style.width)) {
      tableModel[i][j].style.height = "";
      _aspxRemoveStyleAttribute(tableModel[i][j], "height");
     }
    }
   }
  }
 },
 SetTableAccessibility: function(table, properties) {
  if (properties.caption) {
   var caption = table.createCaption();
   caption.innerHTML = properties.caption;
  }
  else
   table.deleteCaption();
  if (properties.summary)
   table.summary = properties.summary;
  else
   _aspxRemoveAttribute(table, "summary");
  var hasColumnHeaders = this.GetHasColumnHeaders(table);
  var headers = properties.headers;
  this.SetRowAndBothHeaders(table, headers);
  this.SetColumnAndBothHeaders(table, headers, hasColumnHeaders);
 },
 SetColumnAndBothHeaders: function(table, headers, hasColumnHeaders) {
  if ((headers == 'column' || headers == 'both') && !this.GetHasColumnHeaders(table)) {
   for (var i = 0; i < table.rows.length; i++) {
    var newCell = _aspxReplaceTagName(table.rows[i].cells[0], 'TH');
    if (newCell != null && !(headers == 'both' && newCell.scope == 'col'))
     newCell.scope = 'row';
   }
  }
  if (hasColumnHeaders && headers != 'column' && headers != 'both') {
   for (var i = 0; i < table.rows.length; i++) {
    var row = table.rows[i];
    if (row.parentNode.nodeName.toUpperCase() == 'TBODY') {
     var newCell = _aspxReplaceTagName(row.cells[0], 'TD');
     if (newCell != null)
      newCell.removeAttribute('scope');
    }
   }
  }
 },
 SetRowAndBothHeaders: function(table, headers) {
  var hasRowHeaders = this.GetHasRowHeaders(table);
  if (!hasRowHeaders && (headers == 'row' || headers == 'both')) {
   var firstRow = table.rows[0];
   for (var i = 0; i < firstRow.childNodes.length; i++) {
    if (firstRow.childNodes[i].nodeType == 1) {
     var th = _aspxReplaceTagName(firstRow.childNodes[i], 'TH');
     if (_aspxIsExists(th))
      th.scope = 'col';
    }
   }
   var tHead = table.tHead;
   if (!_aspxIsExists(tHead))
    tHead = table.createTHead();
   if (tHead.childNodes.length == 0)
    tHead.appendChild(firstRow);
   for (var i = table.tBodies.length - 1; i >= 0; i--) {
    if (_aspxTrim(table.tBodies[i].innerHTML) == "")
     table.removeChild(table.tBodies[i]);
   }
  }
  if (hasRowHeaders && headers != 'row' && headers != 'both') {
   var firstRow = table.rows[0];
   for (var i = 0; i < firstRow.cells.length; i++) {
    var newCell = _aspxReplaceTagName(firstRow.cells[i], "TD");
    if (newCell != null)
     _aspxRemoveAttribute(newCell, "scope");
   }
   if (_aspxIsExists(table.tHead) && table.tHead.childNodes.length > 0) {
    var firstRow = table.tBodies[0].firstChild;
    for (var i = table.tHead.childNodes.length - 1; i >= 0; i--) {
     if (table.tHead.childNodes[i].nodeType == 1)
      firstRow = table.tBodies[0].insertBefore(table.tHead.childNodes[i], firstRow);
    }
    table.removeChild(table.tHead);
   }
  }
 },
 GetAccessibilityHeadersValue: function(table) {
  var hasColumnHeaders = this.GetHasColumnHeaders(table);
  var hasRowHeaders = this.GetHasRowHeaders(table);
  var ret = null;
  if (hasColumnHeaders && hasRowHeaders)
   ret = "both";
  else if (hasColumnHeaders)
   ret = "column";
  else if (hasRowHeaders)
   ret = "row";
  return ret;
 },
 GetAccessibilityCaption: function(table) {
  var caption = _aspxGetChildByTagName(table, "CAPTION", 0);
  if (caption)
   return caption.innerHTML;
  return "";
 },
 GetHasColumnHeaders: function(table) {
  for (var i = 0; i < table.rows.length; i++) {
   if (table.rows[i].cells[0].nodeName.toUpperCase() != 'TH')
    return false;
  }
  return true;
 },
 GetHasRowHeaders: function(table) {
  if (table.rows.length == 0)
   return false;
  for (var i = 0; i < table.rows[0].cells.length; i++) {
   if (table.rows[0].cells[i].nodeName.toUpperCase() != 'TH')
    return false;
  }
  return true;
 },
 IsTableColumnEqual: function(table) {
  if (table.rows.length < 0)
   return false;
  var cellWidth = table.rows[0].cells[0].style.width;
  if (!cellWidth)
   return false;
  for (var i = 0; i < table.rows.length; i++) {
   var curRow = table.rows[i];
   for (var j = 0; j < curRow.cells.length; j++)
    if (cellWidth && cellWidth != this.GetCell(table, i, j).style.width)
    return false;
  }
  return true;
 },
 AdjustColumnWidth: function(table) {
  var cellWidth = 100 / table.rows[0].cells.length + "%";
  for (var i = 0; i < table.rows.length; i++) {
   var curRow = table.rows[i];
   for (var j = 0; j < curRow.cells.length; j++) {
    _aspxRemoveAttribute(this.GetCell(table, i, j), "width");
    this.GetCell(table, i, j).style.width = cellWidth;
   }
  }
 },
 InsertColumn: function(cell, shift, htmlEditor) {
  if (cell.nodeName.toUpperCase() != "TD" && cell.nodeName.toUpperCase() != "TH")
   return "";
  var table = this.GetTable(cell);
  var tableModel = this.CreateTableModel(table);
  var row = cell.parentNode;
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
  var colSpan = this.GetColSpan(cell);
  var nextColumnIndex = -1;
  if (shift > 0)
   nextColumnIndex = columnIndex + colSpan;
  else
   nextColumnIndex = columnIndex;
  var isTableColumnEqual = this.IsTableColumnEqual(table);
  var doc = _aspxGetElementDocument(cell);
  for (var r = 0; r < tableModel.length; r++) {
   var curCell = shift > 0 ? tableModel[r][nextColumnIndex - 1] : tableModel[r][nextColumnIndex];
   var curCellColumnIndex = this.GetColumnIndexByTableModel(tableModel, r, curCell);
   var curCellColSpan = this.GetColSpan(curCell);
   if ((shift > 0 && curCellColumnIndex + curCellColSpan == columnIndex + colSpan) ||
    (shift == 0 && curCellColumnIndex == columnIndex)) {
    var curCellRowSpan = this.GetRowSpan(curCell);
    var newCell = this.CreateNewCellByCell(tableModel[r][columnIndex], true);
    for (var j = r; j < r + curCellRowSpan; j++)
     _aspxArrayInsert(tableModel[j], newCell, nextColumnIndex);
    r = j - 1;
   }
   else
    _aspxArrayInsert(tableModel[r], curCell, nextColumnIndex);
  }
  var rowIndex = row.rowIndex;
  this.GenerateTableFromModel(tableModel, table);
  if (isTableColumnEqual)
   this.AdjustColumnWidth(table);
  if (htmlEditor)
   this.SelectCellCore(tableModel[rowIndex][nextColumnIndex], htmlEditor);
 },
 InsertRow: function(cell, shift, htmlEditor) {
  if (cell.nodeName.toUpperCase() != "TD" && cell.nodeName.toUpperCase() != "TH")
   return "";
  var table = this.GetTable(cell);
  var tableModel = this.CreateTableModel(table);
  var row = cell.parentNode;
  var rowIndex = row.rowIndex;
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, rowIndex, cell);
  var rowSpan = this.GetRowSpan(cell);
  var doc = _aspxGetElementDocument(cell);
  var newRowIndex = -1;
  var rowIndexInModel = -1;
  if (shift > 0) {
   rowIndexInModel = rowIndex + rowSpan - 1;
   newRowIndex = rowIndex + rowSpan + shift - 1;
  }
  else {
   newRowIndex = rowIndex;
   rowIndexInModel = rowIndex;
  }
  var newRowModel = new Array();
  for (var i = 0; i < tableModel[rowIndexInModel].length; i++) {
   var curCell = tableModel[rowIndexInModel][i];
   var curCellRow = curCell.parentNode;
   var curCellRowSpan = this.GetRowSpan(curCell);
   if ((shift > 0 && (curCellRow.rowIndex + curCellRowSpan == rowIndex + rowSpan)) ||
    (shift == 0 && (curCellRow.rowIndex == rowIndex))) {
    var curCellColSpan = this.GetColSpan(curCell);
    var newCell = this.CreateNewCellByCell(curCell);
    for (var j = i; j < i + curCellColSpan; j++)
     newRowModel[j] = newCell;
    i = j - 1;
   }
   else
    newRowModel[i] = tableModel[rowIndexInModel][i];
  }
  _aspxArrayInsert(tableModel, newRowModel, newRowIndex);
  var newRow = null;
  if (_aspxIsExists(_aspxGetParentByTagName(cell, "THEAD")))
   newRow = table.tHead.insertRow(newRowIndex);
  else
   newRow = table.insertRow(newRowIndex);
  _aspxCopyAllAttributes(row, newRow);
  _aspxRemoveAttribute(newRow, "id");
  this.GenerateTableFromModel(tableModel, table);
  if (htmlEditor)
   this.SelectCellCore(tableModel[newRowIndex][columnIndex], htmlEditor);
 },
 RemoveRow: function(cell, htmlEditor) {
  var row = _aspxHETableHelper.GetTableRow(cell);
  if (_aspxIsExists(row)) {
   var table = this.GetTable(cell);
   var tableModel = this.CreateTableModel(table);
   var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
   var rowIndex = row.rowIndex;
   var rowSpan = this.GetRowSpan(tableModel[rowIndex][columnIndex]);
   for (var r = rowSpan + rowIndex - 1; r >= rowIndex; r--) {
    _aspxArrayRemoveAt(tableModel, r);
    if (r < table.rows.length)
     table.deleteRow(r);
   }
   if (table.rows.length > 0) {
    this.GenerateTableFromModel(tableModel, table);
    if (htmlEditor) {
     rowIndex = Math.min(rowIndex, table.rows.length - 1);
     this.SelectCellCore(tableModel[rowIndex][columnIndex], htmlEditor);
    }
   }
   else
    _aspxRemoveElement(table);
   return true;
  }
  return false;
 },
 RemoveColumn: function(cell, htmlEditor) {
  var row = _aspxHETableHelper.GetTableRow(cell);
  if (_aspxIsExists(row)) {
   var table = this.GetTable(cell);
   var tableModel = this.CreateTableModel(table);
   var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
   var rowIndex = row.rowIndex;
   var colSpan = this.GetColSpan(tableModel[rowIndex][columnIndex]);
   for (var r = 0; r < tableModel.length; r++) {
    for (var c = columnIndex + colSpan - 1; c >= columnIndex; c--) {
     _aspxArrayRemoveAt(tableModel[r], c);
    }
   }
   if (tableModel[rowIndex].length > 0) {
    this.GenerateTableFromModel(tableModel, table);
    if (htmlEditor) {
     columnIndex = Math.min(columnIndex, tableModel[rowIndex].length - 1);
     this.SelectCellCore(tableModel[rowIndex][columnIndex], htmlEditor);
    }
   }
   else
    _aspxRemoveElement(table);
   return true;
  }
  return false;
 },
 SplitCellHorizontal: function(cell, htmlEditor) {
  if (!_aspxIsExists(cell))
   return false;
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var rowIndex = row.rowIndex;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
  var colSpan = isNaN(cell.colSpan) ? 1 : cell.colSpan;
  var doc = _aspxGetElementDocument(table);
  var newCellWidth = "";
  var newCell = doc.createElement(cell.nodeName);
  if (!__aspxIE)
   this.AddDefaultContentToCell(newCell);
  if (colSpan > 1) {
   var newColSpan = Math.ceil(colSpan / 2);
   var startIdx = columnIndex + newColSpan;
   var endIdx = columnIndex + colSpan;
   var rowSpan = isNaN(cell.rowSpan) ? 1 : cell.rowSpan;
   for (var r = rowIndex; r < rowIndex + rowSpan; r++) {
    for (var i = startIdx; i < endIdx; i++)
     tableModel[r][i] = newCell;
   }
  }
  else {
   var newTableModel = new Array();
   var newRowHash = {};
   for (var i = 0; i < tableModel.length; i++) {
    var newRow = tableModel[i].slice(0, columnIndex);
    if (tableModel[i].length <= columnIndex) {
     newTableModel.push(newRow);
     continue;
    }
    if (tableModel[i][columnIndex] == cell) {
     newRow.push(cell);
     newRow.push(newCell);
    }
    else {
     newRow.push(tableModel[i][columnIndex]);
     newRow.push(tableModel[i][columnIndex]);
    }
    for (var j = columnIndex + 1; j < tableModel[i].length; j++)
     newRow.push(tableModel[i][j]);
    newTableModel.push(newRow);
   }
   tableModel = newTableModel;
  }
  var cellWidthInfo = _aspxHETableHelper.ParseSizeString(tableModel[rowIndex][columnIndex].style.width);
  if (cellWidthInfo.valueType) {
   var newCellWidth = cellWidthInfo.value / 2;
   tableModel[rowIndex][columnIndex].style.width = newCellWidth + cellWidthInfo.valueType;
   newCell.style.width = newCellWidth + cellWidthInfo.valueType;
  }
  this.GenerateTableFromModel(tableModel, table);
  if (htmlEditor)
   this.SelectCellCore(tableModel[rowIndex][columnIndex], htmlEditor);
 },
 SplitCellVertical: function(cell, htmlEditor) {
  if (!_aspxIsExists(cell))
   return false;
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var rowIndex = row.rowIndex;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, rowIndex, cell);
  var rowSpan = this.GetRowSpan(cell);
  var doc = _aspxGetElementDocument(table);
  if (rowSpan > 1) {
   var newRowSpan = Math.ceil(rowSpan / 2);
   var newCell = doc.createElement(cell.nodeName);
   if (!__aspxIE)
    this.AddDefaultContentToCell(newCell);
   var startRowIndex = rowIndex + newRowSpan;
   var endRowIndex = rowIndex + rowSpan;
   var curColumnIndex = columnIndex;
   while (tableModel[rowIndex][curColumnIndex] == cell) {
    for (var r = startRowIndex; r < endRowIndex; r++) {
     if (tableModel[r][curColumnIndex] == cell)
      tableModel[r][curColumnIndex] = newCell;
    }
    curColumnIndex++;
   }
  }
  else {
   var newRowHash = {};
   var newRowIndex = rowIndex + 1;
   var isThead = _aspxIsExists(_aspxGetParentByTagName(cell, "THEAD"));
   var newRow = null;
   if (isThead)
    newRow = table.tHead.insertRow(newRowIndex);
   else
    newRow = table.insertRow(newRowIndex);
   _aspxCopyAllAttributes(row, newRow);
   _aspxRemoveAttribute(newRow, "id");
   _aspxArrayInsert(tableModel, new Array(), newRowIndex);
   for (var i = 0; i < tableModel[rowIndex].length; i++) {
    if (tableModel[rowIndex][i] == cell) {
     if (!newRowHash[cell]) {
      newRowHash[cell] = doc.createElement(cell.nodeName);
      if (!__aspxIE)
       this.AddDefaultContentToCell(newRowHash[cell]);
     }
     tableModel[newRowIndex][i] = newRowHash[cell];
    }
    else
     tableModel[newRowIndex][i] = tableModel[rowIndex][i];
   }
  }
  this.GenerateTableFromModel(tableModel, table);
  if (htmlEditor)
   this.SelectCellCore(tableModel[rowIndex][columnIndex], htmlEditor);
 },
 MergeCellHorizontal: function(cell, htmlEditor) {
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var rowIndex = row.rowIndex;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, rowIndex, cell);
  var nextCellColumnIndex = this.GetNextCellColumnIndexByTableModel(tableModel, rowIndex, columnIndex);
  var nextCell = tableModel[rowIndex][nextCellColumnIndex];
  var rowSpan = isNaN(cell.rowSpan) ? 1 : cell.rowSpan;
  var newCell = this.MergeCell(cell, nextCell);
  var cellWidthInfo = _aspxHETableHelper.ParseSizeString(tableModel[rowIndex][columnIndex].style.width);
  var mergedCellWidthInfo = _aspxHETableHelper.ParseSizeString(tableModel[rowIndex][nextCellColumnIndex].style.width);
  if (cellWidthInfo.valueType && cellWidthInfo.valueType == mergedCellWidthInfo.valueType)
   newCell.style.width = cellWidthInfo.value + mergedCellWidthInfo.value + cellWidthInfo.valueType;
  for (var i = rowIndex; i < rowIndex + rowSpan; i++) {
   var curColumnIndex = columnIndex;
   while (tableModel[i] &&
     (tableModel[i][curColumnIndex] == cell || tableModel[i][curColumnIndex] == nextCell)) {
    tableModel[i][curColumnIndex] = newCell;
    curColumnIndex++;
   }
  }
  this.GenerateTableFromModel(tableModel, table);
  if (htmlEditor)
   this.SelectCellCore(tableModel[rowIndex][columnIndex], htmlEditor);
 },
 MergeCellVertical: function(cell, htmlEditor) {
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var row = cell.parentNode;
  var rowIndex = row.rowIndex;
  var tableModel = _aspxHETableHelper.CreateTableModel(table);
  var columnIndex = this.GetColumnIndexByTableModel(tableModel, rowIndex, cell);
  var nextCellRowIndex = this.GetNextCellRowIndexByTableModel(tableModel, rowIndex, columnIndex);
  var colSpan = this.GetColSpan(cell);
  var nextCell = tableModel[nextCellRowIndex][columnIndex];
  var newCell = this.MergeCell(cell, nextCell);
  for (var i = columnIndex; i < columnIndex + colSpan; i++) {
   var curRowIndex = rowIndex;
   while (tableModel[curRowIndex] &&
     (tableModel[curRowIndex][i] == cell || tableModel[curRowIndex][i] == nextCell)) {
    tableModel[curRowIndex][i] = newCell;
    curRowIndex++;
   }
  }
  this.GenerateTableFromModel(tableModel, table);
  if (htmlEditor)
   this.SelectCellCore(tableModel[rowIndex][columnIndex], htmlEditor);
 },
 IsMergeCellHorizontalAllow: function(cell, htmlEditor) {
  var isAllow = false;
  var tableModel = _aspxHETableHelper.CreateTableModel(_aspxGetParentByTagName(cell, "TABLE"));
  var row = cell.parentNode;
  var colIndx = this.GetColumnIndexByTableModel(tableModel, row.rowIndex, cell);
  var nextCellColIndx = colIndx + this.GetColSpan(cell);
  var nextCell = tableModel[row.rowIndex][nextCellColIndx];
  if (_aspxIsExists(nextCell)) {
   if (this.GetRowSpan(cell) == this.GetRowSpan(nextCell)) {
    var realNextCellRow = nextCell.parentNode;
    isAllow = realNextCellRow.rowIndex == row.rowIndex;
   }
  }
  return isAllow;
 },
 IsMergeCellVerticalAllow: function(cell, htmlEditor) {
  var isAllow = false;
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var nextCell = this.GetNextCellVertical(cell);
  if (nextCell) {
   var colSpan = isNaN(cell.colSpan) ? 1 : cell.colSpan;
   var nextCellColSpan = isNaN(nextCell.colSpan) ? 1 : nextCell.colSpan;
   isAllow = colSpan == nextCellColSpan;
  }
  return isAllow;
 },
 MergeCell: function(firstCell, secondCell) {
  var doc = _aspxGetElementDocument(firstCell);
  var newCell = doc.createElement(firstCell.nodeName);
  newCell.innerHTML = firstCell.innerHTML;
  var emptyHtmlRegExp = new RegExp(__aspxHEEmptyHtmlRegExpPattern, "ig");
  if (!emptyHtmlRegExp.test(secondCell.innerHTML))
   newCell.innerHTML += "<br/>" + secondCell.innerHTML;
  _aspxCopyAllAttributes(firstCell, newCell);
  return newCell;
 },
 CreateTableModel: function(table) {
  var rows = table.rows;
  var rowCount = 0;
  var model = new Array();
  for (var i = 0; i < rows.length; i++) {
   if (!model[rowCount])
    model[rowCount] = new Array();
   var colCount = 0;
   for (var j = 0; j < rows[i].cells.length; j++) {
    var curCell = rows[i].cells[j];
    while (model[rowCount][colCount])
     colCount++;
    var colSpan = this.GetColSpan(curCell);
    var rowSpan = this.GetRowSpan(curCell);
    for (var rs = 0; rs < rowSpan; rs++) {
     if (!model[rowCount + rs])
      model[rowCount + rs] = new Array();
     for (var cs = 0; cs < colSpan; cs++)
      model[rowCount + rs][colCount + cs] = rows[i].cells[j];
    }
    colCount += colSpan - 1;
   }
   rowCount++;
  }
  return model;
 },
 GenerateTableFromModel: function(model, sourceTable) {
  var rowSpanAttr = __aspxIE ? "_dxrowspan" : "rowSpan";
  for (var i = 0; i < model.length; i++) {
   for (var j = 0; j < model[i].length; j++) {
    if (model[i][j].parentNode)
     model[i][j].parentNode.removeChild(model[i][j]);
    model[i][j].colSpan = model[i][j][rowSpanAttr] = 1;
    model[i][j].rowSpan = 1;
    model[i][j].rowIsNotSpanned = false;
    model[i][j].colIsNotSpanned = false;
   }
  }
  var maxColumnCount = 0;
  for (var i = 0; i < model.length; i++) {
   for (var j = 0; j < model[i].length; j++) {
    if (model[i][j]) {
     var cell = model[i][j];
     if (j > maxColumnCount)
      maxColumnCount = j;
     if (!cell.colIsNotSpanned) {
      if (model[i][j - 1] == cell)
       cell.colSpan++;
      if (model[i][j + 1] != cell)
       cell.colIsNotSpanned = true;
     }
    }
   }
  }
  var sourceRows = new Array();
  for (var i = 0; i <= maxColumnCount; i++) {
   for (var j = 0; j < model.length; j++) {
    if (model[j] && model[j][i] && !model[j][i].rowIsNotSpanned) {
     var cell = model[j][i];
     if (model[j - 1] && model[j - 1][i] == cell)
      cell[rowSpanAttr]++;
     if (!model[j + 1] || model[j + 1][i] != cell)
      cell.rowIsNotSpanned = true;
    }
   }
  }
  var doc = _aspxGetElementDocument(sourceTable);
  for (var i = 0; i < model.length; i++) {
   var rowObj = doc.createElement(sourceTable.rows[i].tagName);
   _aspxCopyAllAttributes(sourceTable.rows[i], rowObj);
   for (var j = 0; j < model[i].length; ) {
    var cell = model[i][j];
    _aspxRemoveAttribute(cell, "rowIsNotSpanned");
    _aspxRemoveAttribute(cell, "colIsNotSpanned");
    if (model[i - 1] && model[i - 1][j] == cell) {
     j += cell.colSpan;
     continue;
    }
    rowObj.appendChild(cell);
    var isEmptyRowSpan = cell.rowSpan == 1;
    if (rowSpanAttr != 'rowSpan' && _aspxIsExists(cell[rowSpanAttr])) {
     if (cell[rowSpanAttr] > 1)
      isEmptyRowSpan = false;
      cell.rowSpan = cell[rowSpanAttr];
      cell.removeAttribute(rowSpanAttr);
     }
    if (cell.colSpan == 1)
     cell.removeAttribute('colspan');
    if (isEmptyRowSpan)
     cell.removeAttribute('rowspan');
    j += cell.colSpan;
   }
   sourceTable.rows[i].parentNode.replaceChild(rowObj, sourceTable.rows[i]);
  }
 },
 AddDefaultContentToCell: function(cell) {
  cell.innerHTML = "&nbsp;";
 },
 CreateNewCellByCell: function(cell, resetWidth) {
  var newCell = _aspxGetElementDocument(cell).createElement(cell.nodeName);
  if (cell.style.cssText !== '') {
   newCell.style.cssText = cell.style.cssText;
   if (resetWidth && _aspxHETableHelper.ParseSizeString(newCell.style.width).valueType == "%")
    newCell.style.width = "";
  }
  if (!__aspxIE)
   this.AddDefaultContentToCell(newCell);
  return newCell;
 },
 ParseSizeString: function(sizeString) {
  var ret = { value: null, valueType: null };
  var res = __aspxHESizeTypeRegExp.exec(sizeString);
  if (res && res.length > 2) {
   ret.value = parseFloat(res[1]);
   ret.valueType = res[2];
  }
  return ret;
 },
 SetBackgroundColor: function(element, color) {
  if (color)
   element.style.backgroundColor = color;
  else {
   element.style.backgroundColor = "";
   _aspxRemoveStyleAttribute(element.style, "backgroundColor");
  }
 },
 SetTableBorderColor: function(table, color) {
  table.setAttribute(__aspxIE ? "borderColor" : "bordercolor", color);
 },
 GetTableBorderColor: function(table, color) {
  return _aspxGetAttribute(table, __aspxIE ? "borderColor" : "bordercolor");
 },
 GetRowIndex: function(cell) {
  var row = cell.parentNode;
  return row.rowIndex;
 },
 GetCell: function(table, rowIndex, colIndex) {
  return table.rows[rowIndex].cells[colIndex];
 },
 GetNextCellVertical: function(cell) {
  var nextCell = null;
  var row = cell.parentNode;
  var table = _aspxGetParentByTagName(cell, "TABLE");
  var rowSpan = this.GetRowSpan(cell);
  if (table.rows.length > row.rowIndex + rowSpan) {
   var curCellIndex = 0;
   var nextRow = table.rows[row.rowIndex + rowSpan];
   var curCumulitativeSpan = 0;
   while ((curCumulitativeSpan < cell.cellIndex + 1) && (nextRow.cells.length > curCellIndex)) {
    curCumulitativeSpan += this.GetColSpan(nextRow.cells[curCellIndex]);
    nextCell = nextRow.cells[curCellIndex];
    curCellIndex += 1;
   }
  }
  return nextCell;
 },
 GetColumnIndexByTableModel: function(model, rowIndex, cell) {
  if (model.length < rowIndex + 1)
   return -1;
  var row = model[rowIndex];
  for (var i = 0; i < row.length; i++) {
   if (row[i] == cell)
    return i;
  }
  return -1;
 },
 GetNextCellColumnIndexByTableModel: function(model, rowIndex, columnIndex) {
  if (model.length < rowIndex + 1)
   return -1;
  var cell = model[rowIndex][columnIndex];
  for (var i = columnIndex; i < model[rowIndex].length; i++) {
   if (model[rowIndex][i] != cell)
    return i;
  }
  return -1;
 },
 GetNextCellRowIndexByTableModel: function(model, rowIndex, columnIndex) {
  if (model.length < rowIndex + 1)
   return -1;
  var cell = model[rowIndex][columnIndex];
  for (var i = rowIndex; i < model.length; i++) {
   if (model[i][columnIndex] != cell)
    return i;
  }
  return -1;
 },
 GetNextRow: function(row) {
  var table = _aspxGetParentByTagName(row, "TABLE");
  var i = 0;
  for (i = 0; i < table.rows.length; i++)
   if (table.rows[i] == row)
   break;
  return i + 1 < table.rows.length ? table.rows[i + 1] : null;
 },
 GetColSpan: function(cell) {
  return isNaN(cell.colSpan) ? 1 : cell.colSpan;
 },
 GetRowSpan: function(cell) {
  return isNaN(cell.rowSpan) ? 1 : cell.rowSpan;
 },
 SelectCell: function(table, rowIndex, colIndex, htmlEditor) {
  var cell = this.GetCell(table, rowIndex, colIndex);
  if (_aspxIsExists(cell))
   this.SelectCellCore(cell, htmlEditor);
 },
 SelectCellCore: function(cell, htmlEditor) {
  var elem = cell;
  if (cell.childNodes.length > 0 && !__aspxIE)
   elem = cell.childNodes[0];
  if (!__aspxIE)
   htmlEditor.SetFocus();
  ASPxClientHtmlEditorSelection.SelectElement(elem, htmlEditor, __aspxOpera);
 },
 DeleteRows: function(table) {
  for (var i = 0; i < table.rows.length; i++) {
   var rIndex = table.rows[i].sectionRowIndex;
   table.deleteRow(rIndex);
  }
 }
}
InsertTableCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  var doc = htmlEditor.GetDesignViewIFrameDocument();
  var tableId = ASPxClientSelection.GetMarkerID();
  var emptyTableHtml = "<table id='" + tableId + "'></table>";
  ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEHTML_COMMAND].Execute(emptyTableHtml, htmlEditor);
  var emptyTable = _aspxGetElementByIdInDocument(doc, tableId);
  emptyTable.id = "";
  _aspxRemoveAttribute(emptyTable, "id");
  InsertTableCommand.SetTableRowAndColumnCount(emptyTable, cmdValue.rows,
              cmdValue.columns, cmdValue.isColumnEqualWidth);
  this.InitializeTable(emptyTable);
  _aspxHETableHelper.SetTableProperties(emptyTable, cmdValue.tableProperties, htmlEditor);
  _aspxHETableHelper.SelectCell(emptyTable, 0, 0, htmlEditor);
  return true;
 },
 InitializeTable: function(table) {
  table.style.borderCollapse = "collapse";
  for (var i = 0; i < table.rows.length; i++) {
   var row = table.rows[i];
   for (var j = 0; j < row.cells.length; j++)
    _aspxHETableHelper.AddDefaultContentToCell(row.cells[j]);
  }
 }
});
InsertTableCommand.SetTableRowAndColumnCount = function(table, rowCount, columnCount, isColumnEqualWidth) {
 _aspxHETableHelper.DeleteRows(table);
 var cellWidth = 100 / columnCount + "%";
 for (var i = 0; i < rowCount; i++) {
  var newRow = table.insertRow(i);
  for (var j = 0; j < columnCount; j++) {
   var cell = newRow.insertCell(j);
   if (isColumnEqualWidth)
    cell.style.width = cellWidth;
  }
 }
};
ChangeTableCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  _aspxHETableHelper.SetTableProperties(cmdValue.tableElement, cmdValue.tableProperties, htmlEditor);
  _aspxHETableHelper.SelectCell(cmdValue.tableElement, 0, 0, htmlEditor);
  return true;
 }
});
ChangeTableCellCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  if (cmdValue.properties.applyForAll)
   _aspxHETableHelper.SetCellPropertiesForAllCell(_aspxGetParentByTagName(cmdValue.cellElement, "TABLE"),
               cmdValue.properties);
  else
   _aspxHETableHelper.SetCellProperties(cmdValue.cellElement, cmdValue.properties);
  return true;
 }
});
ChangeTableColumnCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  _aspxHETableHelper.SetColumnProperties(cmdValue.cell, cmdValue.properties);
  return true;
 }
});
ChangeTableRowCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  _aspxHETableHelper.SetRowProperties(cmdValue.cell, cmdValue.properties);
  return true;
 }
});
DeleteTableCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  var curSelection = ASPxClientHtmlEditorSelection.Create(htmlEditor);
  var table = _aspxHETableHelper.GetTable(curSelection.GetParentElement());
  if (_aspxIsExists(table)) {
   ASPxClientHtmlEditorSelection.SelectElement(table, htmlEditor);
   ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DELETE_COMMAND].Execute(null, htmlEditor);
   if (__aspxOpera)
    _aspxRemoveElement(table);
   htmlEditor.SetFocus();
   return true;
  }
  return false;
 },
 IsLocked: function(editor) {
  return !ChangeTableDialogCommand.IsTableSelected(editor);
 }
});
InsertTableColumnAndRowCommandBase = _aspxCreateClass(Command, {
 IsLocked: function(editor) {
  return !_aspxIsExists(InsertTableColumnAndRowCommandBase.GetTableCell(editor));
 }
});
InsertTableColumnAndRowCommandBase.GetTableCell = function(htmlEditor) {
 if (htmlEditor.NeedGetElementFromSelection("tableCell")) {
  var curSelection = ASPxClientHtmlEditorSelection.Create(htmlEditor);
  var parentElem = curSelection.GetParentElement();
  var endElem = null;
  if (!__aspxIE)
   endElem = curSelection.GetEndContainer();
  htmlEditor.SetSelectedElement("tableCell", _aspxHETableHelper.GetTableCellBySelection(parentElem, endElem));
 }
 return htmlEditor.GetSelectedElement("tableCell");
}
InsertTableColumnCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  var cell = InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor);
  if (_aspxIsExists(cell)) {
   _aspxHETableHelper.InsertColumn(cell, this.GetShift(), htmlEditor);
   htmlEditor.SetFocus();
   return true;
  }
  return false;
 },
 GetShift: function() {
  var ret = 0; 
  if (this.commandID == ASPxClientCommandConsts.INSERTTABLECOLUMNTORIGHT_COMMAND)
   ret = 1;
  return ret;
 }
});
InsertTableRowCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  var cell = InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor);
  if (_aspxIsExists(cell)) {
   _aspxHETableHelper.InsertRow(cell, this.GetShift(), htmlEditor);
   htmlEditor.SetFocus();
   return true;
  }
  return false;
 },
 GetShift: function() {
  var ret = 0; 
  if (this.commandID == ASPxClientCommandConsts.INSERTTABLEROWBELOW_COMMAND)
   ret = 1;
  return ret;
 }
});
DeleteTableRowCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  var cell = InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor);
  return _aspxHETableHelper.RemoveRow(cell, htmlEditor);
 },
 IsLocked: function(editor) {
  if (editor.NeedGetElementFromSelection("tableRow")) {
   var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
   editor.SetSelectedElement("tableRow", _aspxHETableHelper.GetTableRow(curSelection.GetParentElement()));
  }
  return !_aspxIsExists(editor.GetSelectedElement("tableRow"));
 }
});
DeleteTableColumnCommand = _aspxCreateClass(DeleteTableRowCommand, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  var curSelection = ASPxClientHtmlEditorSelection.Create(htmlEditor);
  var selElem = curSelection.GetParentElement();
  var table = _aspxHETableHelper.GetTable(selElem);
  var row = _aspxHETableHelper.GetTableRow(selElem);
  var cell = InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor);
  return _aspxHETableHelper.RemoveColumn(cell, htmlEditor);
 }
});
SplitTableCellHorizontallyCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  _aspxHETableHelper.SplitCellHorizontal(InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor), htmlEditor);
  return true;
 }
});
SplitTableCellVerticallyCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  _aspxHETableHelper.SplitCellVertical(InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor), htmlEditor);
  return true;
 }
});
MergeTableCellRightCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);  
  _aspxHETableHelper.MergeCellHorizontal(InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor), htmlEditor);
  return true;
 },
 IsLocked: function(editor) {
  var cell = InsertTableColumnAndRowCommandBase.GetTableCell(editor);
  if (_aspxIsExists(cell))
   return !_aspxHETableHelper.IsMergeCellHorizontalAllow(cell, editor);
  return true;
 }
});
MergeTableCellDownCommand = _aspxCreateClass(InsertTableColumnAndRowCommandBase, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);
  _aspxHETableHelper.MergeCellVertical(InsertTableColumnAndRowCommandBase.GetTableCell(htmlEditor), htmlEditor);
  return true;
 },
 IsLocked: function(editor) {
  var cell = InsertTableColumnAndRowCommandBase.GetTableCell(editor);
  if (_aspxIsExists(cell))
   return !_aspxHETableHelper.IsMergeCellVerticalAllow(cell, editor);
  return true;
 }
});
FormatBlockCommand = _aspxCreateClass(BrowserCommand, {
 GetCorrectedValue: function(value) {
  return __aspxIE ? "<" + value + ">" : value;
 },
 GetValue: function(editor) {
  value = (__aspxIE) ? this.GetValueIE(editor) : this.GetValueMoz(editor);
  return (value == "font") ? "span" : value;
 },
 GetValueIE : function(editor) {    
  var contentAreaDoc = editor.GetDesignViewIFrameDocument();
  var curSelection = contentAreaDoc.selection;
  if (!curSelection) return "";
  var selRange = curSelection.createRange();
  var parentElement = (selRange.length > 0 ? selRange(0) : selRange.parentElement());
  return this.GetValueByElement(parentElement);
 },
 GetValueMoz: function(editor) {
  var contentWindow = editor.GetDesignViewIFrameWindow(); 
  var curSelection = contentWindow.getSelection();
  if (!curSelection || curSelection.rangeCount != 1) return "";
  var startNode = (curSelection.anchorNode.nodeType != 3
       ? curSelection.anchorNode
       : curSelection.anchorNode.parentNode);
  var endNode = (curSelection.focusNode.nodeType != 3
       ? curSelection.focusNode
       : curSelection.focusNode.parentNode);       
  if (startNode != endNode)
   return "";
  var restoreSelection = ASPxClientHtmlEditorSelection.Create(editor);
  return this.GetValueByElement(restoreSelection.GetParentElement());
 },
 GetValueByElement: function(element) {
  return (element) && (element.nodeType == 1) ? element.tagName.toLowerCase() : "";
 }
});
RemoveFormatCommand = _aspxCreateClass(BrowserCommand, {
 Execute: function(cmdValue, editor) {
  BrowserCommand.prototype.Execute.call(this, cmdValue, editor);
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  var parentElem = curSelection.GetParentElement();
  if (!curSelection.IsTextOnly() && !curSelection.IsControl() && 
   _aspxIsExists(parentElem))
   this.CleanElement(parentElem);
  return true;
 },
 CleanElement: function(element) {
  for (var i =  0; i < element.childNodes.length ; i++)
   this.CleanElement(element.childNodes[i]);
  if (element.nodeType == 1 && element.tagName.toUpperCase() != "BODY") {
   _aspxRemoveAllAttributes(element, ["href", "src", "alt", "target", "id", "title", "value"]);
   _aspxRemoveAllStyles(element);
  }
 }
});
PasteFromWord = _aspxCreateClass(Command, {
 Execute: function(cmdValue, htmlEditor) {
  Command.prototype.Execute.call(this);  
  return ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEHTML_COMMAND].Execute(
   PasteFromWord.ClearWordFormatting(cmdValue.html, cmdValue.stripFontFamily), htmlEditor); 
 }
});
PasteFromWord.ClearWordFormatting = function(html, stripFontFamily) {
 html = PasteFromWord.ClearWordAttributes(html);
 html = html.replace(/<\/?\w+:[^>]*>/gi, '');
 html = html.replace(/<STYLE[^>]*>[\s\S]*?<\/STYLE[^>]*>/gi, '');
 html = html.replace(/<(?:META|LINK)[^>]*>\s*/gi, '');
 html = html.replace(/<\\?\?xml[^>]*>/gi, '');
 html = html.replace(/<o:[pP][^>]*>\s*<\/o:[pP]>/gi, '');
 html = html.replace(/<o:[pP][^>]*>.*?<\/o:[pP]>/gi, '&nbsp;');
 html = html.replace(/<st1:.*?>/gi, '');
 html = html.replace(/<\!--[\s\S]*?-->/g, '');
 html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3") ;
 html =  html.replace(/\s*style="\s*"/gi, '');
 html = html.replace(/style=""/ig, "");
 html = html.replace(/style=''/ig, "");
 html = html.replace(/^\s/i, '');
 html = html.replace(/\s$/i, '');
 html = html.replace(/<p>&nbsp;<\/p>/gi, '<br /><br />');
 html = html.replace(/<font\s*>([^<>]+)<\/font>/gi, '$1');
 html = html.replace(/<span\s*><span\s*>([^<>]+)<\/span><\/span>/ig, '$1');
 html = html.replace(/<span>([^<>]+)<\/span>/gi, '$1');
 if (stripFontFamily) {
  html = html.replace(/\s*face="[^"]*"/gi, '');
  html = html.replace(/\s*face=[^ >]*/gi, '');
  html = html.replace(/\s*FONT-FAMILY:[^;"]*;?/gi, '');
 }
 var replacePwithDIV = new RegExp('(<P)([^>]*>[\\s\\S]*?)(<\/P>)', 'gi');
 html = html.replace(replacePwithDIV, '<div$2<\/div>');
 html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' );
 html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' );
 html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' );
 return html;
}
PasteFromWord.ClearWordAttributes = function(html) {
 html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3") ;
 html = html.replace(/\s*mso-[^:]+:[^;"]+;?/gi, '');
 html = html.replace(/\s*MARGIN: 0cm 0cm 0pt\s*;/gi, '');
 html = html.replace(/\s*MARGIN: 0cm 0cm 0pt\s*"/gi, "\"");
 html = html.replace(/\s*TEXT-INDENT: 0cm\s*;/gi, '');
 html = html.replace(/\s*TEXT-INDENT: 0cm\s*"/gi, "\"");
 html = html.replace(/\s*PAGE-BREAK-BEFORE: [^\s;]+;?"/gi, "\"");
 html = html.replace(/\s*FONT-VARIANT: [^\s;]+;?"/gi, "\"") ;
 html = html.replace(/\s*tab-stops:[^;"]*;?/gi, '') ;
 html = html.replace(/\s*tab-stops:[^"]*/gi, '') ;
 return html;
}
PasteHtmlCommand = _aspxCreateClass(Command, {
 Execute: function(htmlText, htmlEditor, needSelect) {
  Command.prototype.Execute.call(this);
  this.needSelect = _aspxIsExists(needSelect) ? needSelect : true;
  this.htmlText = htmlText;
  this.htmlEditor = htmlEditor;
  if (__aspxIE)
   return this.ExecuteIE();
  if (__aspxOpera)
   return this.ExecuteOpera();
  if (__aspxNetscapeFamily)
   return this.ExecuteNS();
  if (__aspxWebKitFamily)
   return this.ExecuteWebKit();
  return false;
 },
 ExecuteIE: function() {
  var doc = this.htmlEditor.GetDesignViewIFrameDocument();
  if (doc.selection.type.toLowerCase() != "none")
   doc.selection.createRange().execCommand("Delete");
  if (doc.selection.type.toLowerCase() != "none") 
   doc.execCommand("Delete");
  doc.body.setActive();
  var selRange = doc.selection.createRange();
  if (selRange && selRange.length) {
   var elem = selRange.item(0);
   if (elem && elem.tagName.toUpperCase() == "BODY") {
    var formElement = elem.getElementsByTagName("FORM")[0];
    if (formElement)
     _aspxSetInnerHtml(formElement, formElement.innerHTML + this.htmlText);
   }
  }
  else {
   var rngStart = selRange.duplicate();
   rngStart.collapse(true);
   selRange.pasteHTML(this.htmlText);
   rngStart.setEndPoint("StartToEnd", selRange);
   rngStart.select();
  }
  return true;
 },
 ExecuteNS: function() {
  return this.ExecuteOpera();
 },
 ExecuteOpera: function() {
  var doc = this.htmlEditor.GetDesignViewIFrameDocument();
  var tmpNode = doc.createElement("SPAN");
  _aspxSetInnerHtml(tmpNode, this.htmlText);
  this.InsertNodeAtSelection(tmpNode);
  var range = doc.createRange();
  range.selectNodeContents(tmpNode);
  var documentFragment = range.extractContents();
  range.selectNode(tmpNode);
  range.deleteContents();
  this.InsertNodeAtSelection(documentFragment);
  if (__aspxOpera)
   this.htmlEditor.GetDesignViewIFrameDocument().body.focus();
  return true;
 },
 ExecuteWebKit: function() {
  var doc = this.htmlEditor.GetDesignViewIFrameDocument();
  doc.execCommand("InsertHTML", false, this.htmlText);
  this.htmlEditor.Focus();
  return true;
 },
 InsertNodeAtSelection : function(insertNode) {
  if (__aspxOpera)
   ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DELETE_COMMAND].Execute(null, this.htmlEditor);
  var selection = this.htmlEditor.GetDesignViewIFrameWindow().getSelection();  
  var range = selection.getRangeAt(0);
  selection.removeAllRanges();
  range.deleteContents();
  var container = range.startContainer;
  var startPosition = range.startOffset;
   range = this.htmlEditor.GetDesignViewIFrameDocument().createRange();
  if ((container.nodeType == 3) && (insertNode.nodeType == 3)) {
   container.insertData(startPosition, insertNode.nodeValue);
   range.setEnd(container, startPosition + insertNode.length);
   range.setStart(container, startPosition);
  }
  else {
   var afterNode;
   var isContainerEmpty = false;
   if (container.nodeType == 3) {
    var textNode = container;
    container = textNode.parentNode;
    var nodeText = textNode.nodeValue;
    var textBefore = nodeText.substr(0, startPosition);
    var textAfter = nodeText.substr(startPosition);
     var beforeNode = this.htmlEditor.GetDesignViewIFrameDocument().createTextNode(textBefore);
     var afterNode = this.htmlEditor.GetDesignViewIFrameDocument().createTextNode(textAfter);
    container.insertBefore(afterNode, textNode);
    container.insertBefore(insertNode, afterNode);
    try {
     container.insertBefore(beforeNode, insertNode);
    }
    catch (exc) { }
    container.removeChild(textNode);
   }
   else {
    if (container.childNodes.length > 0) {
     afterNode = container.childNodes[startPosition];
     container.insertBefore(insertNode, afterNode);
    }
    else {
     if (container.tagName != "BODY")
      container = container.parentNode;
     isContainerEmpty = true;
     container.appendChild(insertNode);
    }
   }
   try {
    if (isContainerEmpty) {
     range.selectNode(container.childNodes[container.childNodes.length - 1]);
     range.collapse(false);
    }
    else {
     range.setStart(insertNode, 0);
     if (!_aspxIsExists(afterNode)) 
       afterNode = __aspxNetscapeFamily ? this.htmlEditor.GetDesignViewIFrameDocument().body : insertNode;
      range.setEnd(_aspxIsExists(afterNode) ? afterNode : this.htmlEditor.GetDesignViewIFrameDocument().body, 0);
    }
   }
   catch (exc) { }
  }
  try {
   selection.addRange(range);
  }
  catch (exc) { }
 }
});
CopyPastCommand  = _aspxCreateClass(BrowserCommand, {
 Execute: function(cmdValue, editor) {
  var isSuccessfully = true;
  Command.prototype.Execute.call(this);
  if (__aspxIE)
   isSuccessfully = this.ExecuteIE(editor);
  else {
   var message = "Not supported in this browser";
   if (_aspxIsExists(ASPxCommandMessageConsts[this.commandID]))
    message = ASPxCommandMessageConsts[this.commandID];
   alert(message);
   return false;
  }
  return isSuccessfully;
 },
 ExecuteIE: function(editor) {
  var isSuccessfully = false;
  var isEnabled = !__aspxOpera;
  if (isEnabled) {
   try {
    editor.GetDesignViewIFrameDocument().queryCommandEnabled(this.commandID); 
   }
   catch (e) { 
    isEnabled = false;
   }
  }
  if (isEnabled)
   isSuccessfully = editor.GetDesignViewIFrameDocument().execCommand(this.commandID, false, null);
  return isSuccessfully;
 },
 IsHtmlChangeable: function() {
  return this.GetCommandID() != ASPxClientCommandConsts.COPY_COMMAND;
 }
});
SelectAllBrowserCommand  = _aspxCreateClass(BrowserCommand, {
 IsHtmlChangeable: function() {
  return false;
 }
});
TextTypeCommand = _aspxCreateClass(Command, {
 IsDefaultAction: function(editor) {
  return true;
 },
 IsImmediateExecution: function() {
  return true;
 }
});
KbCopyCommand = _aspxCreateClass(TextTypeCommand, {
 IsHtmlChangeable: function() {
  return false;
 } 
});
KbCutCommand = _aspxCreateClass(TextTypeCommand, {
});
KbPasteCommand = _aspxCreateClass(TextTypeCommand, {
});
LineBreakTypeCommand = _aspxCreateClass(TextTypeCommand, {
});
NewParagraphTypeCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  return editor.GetDesignViewIFrameDocument().execCommand("InsertParagraph", false, null);
 }
});
DeleteCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
    var isSuccessfully = true;
  var designViewIFrameDocument = editor.GetDesignViewIFrameDocument();
    isSuccessfully = designViewIFrameDocument.execCommand(this.commandID, false, null);
    if (__aspxOpera) { 
   designViewIFrameDocument.contentEditable = true;
   designViewIFrameDocument.body.focus();
  }
  return isSuccessfully;
 }
});
DeleteWithoutSelectionCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  return true;
 },
 IsImmediateExecution: function() {
  return true;
 }
});
UndoCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  var ret = editor.Undo();
  editor.SetFocus();  
  return ret;
 },
 IsReversable: function() {
  return false;
 },
 IsLocked: function(editor) {
  return !editor.IsUndoAvailable();
 }
});
RedoCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  var ret = editor.Redo();
  editor.SetFocus();
  return ret;
 },
 IsReversable: function() {
  return false;
 },
 IsLocked: function(editor) {
  return !editor.IsRedoAvailable();
 }
});
CheckSpellingCommand  = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  return editor.CheckSpelling();
 },
 IsLocked: function(editor) {
  return aspxIsEmptyHtml(editor.GetHtmlInternal());
 }
});
CheckSpellingCoreCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  editor.SetHtmlInternal(cmdValue);
  return true;
 }
});
PrintCommand  = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  return editor.Print();
 },
 IsLocked: function(editor) {
  return aspxIsEmptyHtml(editor.GetHtmlInternal());
 },
 IsReversable: function() {
  return false;
 }
});
function aspxIsEmptyHtml(html){
 var html = _aspxTrim(html);
 return html == "" || html == "&nbsp;" || html == "<P>&nbsp;</P>";
}
InsertImageCommand = _aspxCreateClass(BrowserCommand, {
 Execute: function(cmdValue, editor) {
  var newImageElement = this.InsertImage(cmdValue.src, editor);
  ChangeImageCommand.SetImageProperties(newImageElement, "", cmdValue.width,
           cmdValue.height, cmdValue.align, cmdValue.alt,
           cmdValue.useFloat);
  return true;
 },
 InsertImage: function(source, editor) {
  var markerID = ASPxClientSelection.GetMarkerID();
  var htmlText = "<img src='" + source + "' id='" + markerID + "' />";
  ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEHTML_COMMAND].Execute(htmlText, editor);
  var imageElement = _aspxGetElementByIdInDocument(editor.GetDesignViewIFrameDocument(), markerID);
  _aspxRemoveAttribute(imageElement, "id");
  return imageElement;
 }
});
ChangeImageCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  ChangeImageCommand.SetImageProperties(cmdValue.imageElement, cmdValue.src, cmdValue.width, 
             cmdValue.height, cmdValue.align, cmdValue.alt,
             cmdValue.useFloat);
  return true;
 }
});
ChangeImageCommand.GetImageProperties = function(imageElement) {
 var imageInfoObject = {
  isCustomSize: false,
  src: imageElement.src,
  width: imageElement.width,
  height: imageElement.height,
  align: "",
  alt: "",
  useFloat: false
 };
 imageInfoObject.isCustomSize = ChangeImageCommand.IsExistImageAttribute(imageElement, "width") ||
           ChangeImageCommand.IsExistImageAttribute(imageElement, "height");
 var parentNode = imageElement.parentNode;
 if (parentNode.childNodes.length == 1 && parentNode.tagName != "BODY") {
  imageInfoObject.align = parentNode.style.textAlign;
  if (!imageInfoObject.align)
   imageInfoObject.align = parentNode.align;
 }
 if (!imageInfoObject.align) {
  if (_aspxIsExistsAttribute(imageElement, "align"))
   imageInfoObject.align = _aspxGetAttribute(imageElement, "align");
  else {
   if (__aspxIE && _aspxIsExists(imageElement.style.styleFloat)) {
    imageInfoObject.align = imageElement.style.styleFloat;
    imageInfoObject.useFloat = true;
   }
   if (!__aspxIE && _aspxIsExists(imageElement.style.cssFloat)) {
    imageInfoObject.align = imageElement.style.cssFloat;
    imageInfoObject.useFloat = true;
   }
  }
 }
 imageInfoObject.alt = _aspxGetAttribute(imageElement, "alt");
 return imageInfoObject;
};
ChangeImageCommand.IsExistImageAttribute = function(image, attrName) {
 var styleAttr = _aspxGetAttribute(image.style, attrName);
 return ((styleAttr != "") && (styleAttr != null)) ||
     (!__aspxNetscapeFamily && (image.outerHTML.toLowerCase().indexOf(attrName + "=") > -1));
};
Command.RemoveFloat = function(imageElement) {
 _aspxRemoveStyleAttribute(imageElement, "styleFloat");
 if (_aspxIsExists(imageElement.style.cssFloat)) 
  imageElement.style.cssFloat = "";
};
ChangeImageCommand.SetImageProperties = function(imageElement, src, width, height, align, alt, useFloat) {
 if (src && src != "")
  _aspxSetAttribute(imageElement, "src", src);
 if (width && width != "")
  _aspxSetAttribute(imageElement.style, "width", width);
 else {
  _aspxRemoveAttribute(imageElement, "width");
  _aspxRemoveAttribute(imageElement.style, "width");
 }
 if (height && height != "")
  _aspxSetAttribute(imageElement.style, "height", height);
 else {
  _aspxRemoveAttribute(imageElement, "height");
  _aspxRemoveAttribute(imageElement.style, "height");
 }
 if (alt && alt != "")
  _aspxSetAttribute(imageElement, "alt", alt);
 if (align) {
  var documentObj = _aspxGetElementDocument(imageElement); 
  var sourceId = imageElement.id;
  imageElement.id = __aspxHEMarkID;
  var parentNode = imageElement.parentNode;
  var wrapElem = null;
  if (parentNode.childNodes.length == 1 && parentNode.tagName != "BODY" && parentNode.tagName != "TD")
   wrapElem = parentNode;
  _aspxRemoveAttribute(imageElement, "align");
  Command.RemoveFloat(imageElement);
  if (align.toLowerCase() == "left" || align.toLowerCase() == "right") {
   if (wrapElem != null)
    _aspxRemoveOuterTags(wrapElem);
   imageElement = _aspxGetElementByIdInDocument(documentObj, __aspxHEMarkID);
   if (useFloat) {
    if (__aspxIE)
     imageElement.style.styleFloat = align;
    else
     imageElement.style.cssFloat = align;
   }
   else
    _aspxSetAttribute(imageElement, "align", align);
  }
  else { 
   if (wrapElem == null)
    wrapElem = _aspxWrapElementInNewElement(imageElement, "DIV");
   wrapElem.style.textAlign = "center";
   imageElement = _aspxGetElementByIdInDocument(documentObj, __aspxHEMarkID);
  }
  sourceId != "" ? imageElement.id = sourceId : _aspxRemoveAttribute(imageElement, "id");
 }
};
InsertLinkCommand = _aspxCreateClass(HtmlProcessingCommand, {
 Execute: function(cmdValue, editor) {
  this.ValidateCommandValue(cmdValue);
  var curSelection = ASPxClientHtmlEditorSelection.Create(editor);
  var selContainerElement = curSelection.GetParentElement();
  var link = _aspxGetParentByTagName(selContainerElement, "A");
  if (_aspxIsExists(link)) { 
   InsertLinkCommand.prototype.SetLinkProperties(link, cmdValue.url, 
               InsertLinkCommand.PrepareLinkText(cmdValue.text), 
               cmdValue.target, cmdValue.title);
  }  
  else if (curSelection.GetText()!= "" || curSelection.GetParentElement().tagName == "IMG" ||
    curSelection.GetParentElement().tagName == "TABLE") { 
   ASPxHtmlEditorCommandList[ASPxClientCommandConsts.UNLINK_COMMAND].Execute(null, editor);   
   var selInfo = editor.GetEditorSelectionInfo();
   var lastLinkID = 'dx_temp_' + (new Date()).valueOf();
   for (var i = 0; i < selInfo.allElements.length; i++) {
    var curElem = selInfo.allElements[i];
    var parentLink = _aspxGetParentByTagName(curElem, "A");
    var curLink = null;
    if (_aspxIsExists(parentLink)) {
     if (parentLink.href != cmdValue.url)
      InsertLinkCommand.prototype.SetLinkProperties(parentLink, cmdValue.url, "",
                  cmdValue.target, cmdValue.title);
     curLink = parentLink;
    }
    else {
     var elemInnerHtml = curElem.innerHTML;
     var newLinkElement = editor.GetDesignViewIFrameDocument().createElement('A');
     _aspxSetInnerHtml(newLinkElement, elemInnerHtml);
     curElem.innerHTML = '';
     if (__aspxWebKitFamily) newLinkElement.href = "#";
     curElem.appendChild(newLinkElement);
     InsertLinkCommand.prototype.SetLinkProperties(newLinkElement, cmdValue.url, InsertLinkCommand.PrepareLinkText(cmdValue.text),
                 cmdValue.target, cmdValue.title);
     curLink = newLinkElement;
    }
    if (i == selInfo.allElements.length - 1)
     _aspxChangeAttribute(curLink, "id", lastLinkID);
   }   
   editor.DeleteNewAddedFontElements(selInfo);
   var lastLinkElement = _aspxGetElementByIdInDocument(editor.GetDesignViewIFrameDocument(), lastLinkID);
   _aspxRestoreAttribute(lastLinkElement, "id");
   curSelection.SelectElement(lastLinkElement, false);
   if (__aspxOpera)
    editor.GetDesignViewIFrameDocument().body.focus();
  }
  else { 
   var htmlText = "<a href=\"" + cmdValue.url + "\"";
   if (cmdValue.title)
    htmlText = this.AddAttributeStringToHtml(htmlText, "title", cmdValue.title);
   if (cmdValue.target)
    htmlText = this.AddAttributeStringToHtml(htmlText, "target", cmdValue.target);
   htmlText += ">" + InsertLinkCommand.PrepareLinkText(cmdValue.text) + "</a>";
   return ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEHTML_COMMAND].Execute(htmlText, editor);
  }  
  return true;
 },
 ValidateCommandValue: function(cmdValue) {
  cmdValue.url = this.ReplaceDoubleQuotesWithSingleQuotes(cmdValue.url);
  cmdValue.title = this.ReplaceDoubleQuotesWithSingleQuotes(cmdValue.title);
 },
 ReplaceDoubleQuotesWithSingleQuotes: function(str) {
  return str ? str.replace(new RegExp("\"", "g"), "'") : str;
 },
 AddAttributeStringToHtml: function(html, attrName, attrValue) {
  return html + " " + attrName + "=\"" + attrValue + "\"";
 }
});
InsertLinkCommand.prototype.SetLinkProperties = function(linkElement, url, text, target, title) {
 _aspxSetOrRemoveAttribute(linkElement, "href", url);
 _aspxSetOrRemoveAttribute(linkElement, "target", target);
 _aspxSetOrRemoveAttribute(linkElement, "title", title);
 if (text != "")
  linkElement.innerHTML = text;
}
InsertLinkCommand.PrepareLinkText = function(text) {
 return text.replace("<", "&lt;").replace(">", "&gt;");
}
DialogCommand = _aspxCreateClass(Command, {
 Execute: function(cmdValue, editor) {
  var dialog = ASPxHtmlEditorDialogList[this.commandID];
  if (dialog != null)
   dialog.Execute(editor);
  else
   alert('Dialog is not found');
  return true;
 },
 IsHtmlChangeable: function() {
  return false;
 },
 GetState: function(editor) {
  return false;
 },
 IsLocked: function(editor) {
  return false;
 }
});
PasteFromWordDialogCommand = _aspxCreateClass(DialogCommand, {
 IsLocked: function(editor) {
  if (__aspxWebKitFamily) return false;
  try {
   return !editor.GetDesignViewIFrameDocument().queryCommandEnabled(ASPxClientCommandConsts.PASTE_COMMAND);
  }
  catch(e) {}
  return true;
 }
});
ChangeImageDialogCommand = _aspxCreateClass(DialogCommand, {
 IsLocked: function(editor) {
  return !_aspxIsExists(InsertImageDialog.prototype.GetSelectedImage(editor));
 }
});
ChangeLinkDialogCommand = _aspxCreateClass(DialogCommand, {
 IsLocked: function(editor) {
  return !InsertLinkDialog.prototype.IsLinkSelected(editor);
 }
});
TableCellPropertiesDialogCommand = _aspxCreateClass(DialogCommand, {
 IsLocked: function(editor) {
  return !TableCellPropertiesDialogCommand.IsTableCellSelected(editor);
 }
});
TableCellPropertiesDialogCommand.IsTableCellSelected = function(editor) {
 return _aspxIsExists(InsertTableColumnAndRowCommandBase.GetTableCell(editor));
}
ChangeTableDialogCommand = _aspxCreateClass(DialogCommand, {
 IsLocked: function(editor) {
  return !ChangeTableDialogCommand.IsTableSelected(editor);
 }
});
ChangeTableDialogCommand.IsTableSelected = function(htmlEditor) {
 var curSelection = ASPxClientHtmlEditorSelection.Create(htmlEditor);
 return _aspxIsExists(_aspxHETableHelper.GetTable(curSelection.GetParentElement()));
};
var ASPxHtmlEditorCommandList = {};
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.BOLD_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.BOLD_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.ITALIC_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.ITALIC_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.UNDERLINE_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.UNDERLINE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.STRIKETHROUGH_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.STRIKETHROUGH_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.JUSTIFYCENTER_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.JUSTIFYCENTER_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.JUSTIFYLEFT_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.JUSTIFYLEFT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.JUSTIFYRIGHT_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.JUSTIFYRIGHT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.JUSTIFYFULL_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.JUSTIFYFULL_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.SUPERSCRIPT_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.SUPERSCRIPT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.SUBSCRIPT_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.SUBSCRIPT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INDENT_COMMAND] = new IndentCommand(ASPxClientCommandConsts.INDENT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.OUTDENT_COMMAND] = new IndentCommand(ASPxClientCommandConsts.OUTDENT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTORDEREDLIST_COMMAND] = new InsertListCommand(ASPxClientCommandConsts.INSERTORDEREDLIST_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTUNORDEREDLIST_COMMAND] = new InsertListCommand(ASPxClientCommandConsts.INSERTUNORDEREDLIST_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.SELECT_ALL] = new SelectAllBrowserCommand(ASPxClientCommandConsts.SELECT_ALL);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTE_COMMAND] = new CopyPastCommand(ASPxClientCommandConsts.PASTE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEFROMWORD_COMMAND] = new PasteFromWord(ASPxClientCommandConsts.PASTEFROMWORD_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CUT_COMMAND] = new CopyPastCommand(ASPxClientCommandConsts.CUT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.COPY_COMMAND] = new CopyPastCommand(ASPxClientCommandConsts.COPY_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.KBPASTE_COMMAND] = new KbPasteCommand(ASPxClientCommandConsts.KBPASTE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.KBCUT_COMMAND] = new KbCutCommand(ASPxClientCommandConsts.KBCUT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.KBCOPY_COMMAND] = new KbCopyCommand(ASPxClientCommandConsts.KBCOPY_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.FONTSIZE_COMMAND] = new FontSizeBrowserCommand(ASPxClientCommandConsts.FONTSIZE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.FONTNAME_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.FONTNAME_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.FONTCOLOR_COMMAND] = new FontColorBrowserCommand(ASPxClientCommandConsts.FONTCOLOR_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.BACKCOLOR_COMMAND] = new BgColorBrowserCommand(ASPxClientCommandConsts.BACKCOLOR_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.APPLYCSS_COMMAND] = new ApplyCssCommand(ASPxClientCommandConsts.APPLYCSS_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.FORMATBLOCK_COMMAND] = new FormatBlockCommand(ASPxClientCommandConsts.FORMATBLOCK_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.REMOVEFORMAT_COMMAND] = new RemoveFormatCommand(ASPxClientCommandConsts.REMOVEFORMAT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.UNDO_COMMAND] = new UndoCommand(ASPxClientCommandConsts.UNDO_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.REDO_COMMAND] = new RedoCommand(ASPxClientCommandConsts.REDO_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.LINEBREAKETYPE_COMMAND] = new LineBreakTypeCommand(ASPxClientCommandConsts.LINEBREAKETYPE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.NEWPARAGRAPHTYPE_COMMAND] = new NewParagraphTypeCommand(ASPxClientCommandConsts.NEWPARAGRAPHTYPE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.TEXTTYPE_COMMAND] = new TextTypeCommand(ASPxClientCommandConsts.TextType_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.RESIZEOBJECT_COMMAND] = new TextTypeCommand(ASPxClientCommandConsts.RESIZEOBJECT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DRAGDROPOBJECT_COMMAND] = new TextTypeCommand(ASPxClientCommandConsts.DRAGDROPOBJECT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DROPOBJECTFROMEXTERNAL_COMMAND] = new TextTypeCommand(ASPxClientCommandConsts.DROPOBJECTFROMEXTERNAL_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DELETE_COMMAND] = new DeleteCommand(ASPxClientCommandConsts.DELETE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.KBDELETE_COMMAND] = new DeleteWithoutSelectionCommand(ASPxClientCommandConsts.KBDELETE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEHTML_COMMAND] = new PasteHtmlCommand(ASPxClientCommandConsts.PASTEHTML_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTLINK_COMMAND] = new InsertLinkCommand(ASPxClientCommandConsts.INSERTLINK_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.UNLINK_COMMAND] = new BrowserCommand(ASPxClientCommandConsts.UNLINK_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGEIMAGE_COMMAND] = new ChangeImageCommand(ASPxClientCommandConsts.CHANGEIMAGE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTIMAGE_COMMAND] = new InsertImageCommand(ASPxClientCommandConsts.INSERTIMAGE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHECKSPELLING_COMMAND] = new CheckSpellingCommand(ASPxClientCommandConsts.CHECKSPELLING_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CheckSpellingCore_COMMAND] = new CheckSpellingCoreCommand(ASPxClientCommandConsts.CHECKSPELLING_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PRINT_COMMAND] = new PrintCommand(ASPxClientCommandConsts.PRINT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTTABLE_COMMAND] = new InsertTableCommand(ASPxClientCommandConsts.INSERTTABLE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGETABLE_COMMAND] = new ChangeTableCommand(ASPxClientCommandConsts.CHANGETABLE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGETABLECELL_COMMAND] = new ChangeTableCellCommand(ASPxClientCommandConsts.CHANGETABLECELL_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGETABLECOLUMN_COMMAND] = new ChangeTableColumnCommand(ASPxClientCommandConsts.CHANGETABLECOLUMN_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGETABLEROW_COMMAND] = new ChangeTableRowCommand(ASPxClientCommandConsts.CHANGETABLEROW_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DELETETABLE_COMMAND] = new DeleteTableCommand(ASPxClientCommandConsts.DELETETABLE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DELETETABLEROW_COMMAND] = new DeleteTableRowCommand(ASPxClientCommandConsts.DELETETABLEROW_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.DELETETABLECOLUMN_COMMAND] = new DeleteTableColumnCommand(ASPxClientCommandConsts.DELETETABLECOLUMN_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTTABLECOLUMNTOLEFT_COMMAND] = new InsertTableColumnCommand(ASPxClientCommandConsts.INSERTTABLECOLUMNTOLEFT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTTABLECOLUMNTORIGHT_COMMAND] = new InsertTableColumnCommand(ASPxClientCommandConsts.INSERTTABLECOLUMNTORIGHT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTTABLEROWBELOW_COMMAND] = new InsertTableRowCommand(ASPxClientCommandConsts.INSERTTABLEROWBELOW_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTTABLEROWABOVE_COMMAND] = new InsertTableRowCommand(ASPxClientCommandConsts.INSERTTABLEROWABOVE_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.PASTEFROMWORDDIALOG_COMMAND] = new PasteFromWordDialogCommand(ASPxClientCommandConsts.PASTEFROMWORDDIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTIMAGE_DIALOG_COMMAND] = new DialogCommand(ASPxClientCommandConsts.INSERTIMAGE_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGEIMAGE_DIALOG_COMMAND] = new ChangeImageDialogCommand(ASPxClientCommandConsts.CHANGEIMAGE_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.CHANGELINK_DIALOG_COMMAND] = new ChangeLinkDialogCommand(ASPxClientCommandConsts.CHANGELINK_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTLINK_DIALOG_COMMAND] = new DialogCommand(ASPxClientCommandConsts.INSERTLINK_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.TABLEPROPERTIES_DIALOG_COMMAND] = new ChangeTableDialogCommand(ASPxClientCommandConsts.TABLEPROPERTIES_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.INSERTTABLE_DIALOG_COMMAND] = new DialogCommand(ASPxClientCommandConsts.INSERTTABLE_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.TABLECELLPROPERTIES_DIALOG_COMMAND] = new TableCellPropertiesDialogCommand(ASPxClientCommandConsts.TABLECELLPROPERTIES_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.TABLECOLUMNPROPERTIES_DIALOG_COMMAND] = new TableCellPropertiesDialogCommand(ASPxClientCommandConsts.TABLECOLUMNPROPERTIES_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.TABLEROWPROPERTIES_DIALOG_COMMAND] = new TableCellPropertiesDialogCommand(ASPxClientCommandConsts.TABLEROWPROPERTIES_DIALOG_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.SPLITTABLECELLHORIZONTALLY_COMMAND] = new SplitTableCellHorizontallyCommand(ASPxClientCommandConsts.SPLITTABLECELLHORIZONTALLY_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.SPLITTABLECELLVERTICALLY_COMMAND] = new SplitTableCellVerticallyCommand(ASPxClientCommandConsts.SPLITTABLECELLVERTICALLY_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.MERGETABLECELLRIGHT_COMMAND] = new MergeTableCellRightCommand(ASPxClientCommandConsts.MERGETABLECELLRIGHT_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.MERGETABLECELLDOWN_COMMAND] = new MergeTableCellDownCommand(ASPxClientCommandConsts.MERGETABLECELLDOWN_COMMAND);
ASPxHtmlEditorCommandList[ASPxClientCommandConsts.Start_COMMAND] = new Command(ASPxClientCommandConsts.TEXTTYPE_COMMAND);
var __aspxEmptySelection = "empty";
CommandManager = _aspxCreateClass(null, {
 constructor: function(htmlEditor) {
  this.htmlEditor = htmlEditor;
  this.commandIdArray = new Array();
  this.currentCmdIDIndex = -1;
  this.lastRestoreSelection = null;
  this.restoreHtmlArray = new Array();
  this.undoSelectionArray = new Array();
  this.redoSelectionArray = new Array();
  this.ExecuteCommand(ASPxClientCommandConsts.Start_COMMAND, "null", true);
 },
 ExecuteCommand: function(cmdID, cmdValue, addToUndoStack) {
  var isSuccessfully = false;
  if (!ASPxHtmlEditorCommandList[cmdID].IsHtmlChangeable() || !addToUndoStack)
   isSuccessfully = ASPxHtmlEditorCommandList[cmdID].Execute(cmdValue, this.htmlEditor);
  else {
   this.OnCommandExecuting(cmdID);
   isSuccessfully = ASPxHtmlEditorCommandList[cmdID].Execute(cmdValue, this.htmlEditor);
   var needAddToStack = isSuccessfully && ASPxHtmlEditorCommandList[cmdID].IsReversable();
   if (needAddToStack) {
    this.ClearActionsToRedo();
    this.currentCmdIDIndex = this.commandIdArray.length;
    _aspxArrayPush(this.commandIdArray, cmdID);
   }
   this.OnCommandExecuted(needAddToStack);
  }
  return isSuccessfully;
 },
 Undo: function(depth) {
  depth = Math.min(depth, this.commandIdArray.length);
  var actionCount = this.commandIdArray.length;
  depth = Math.min(depth, this.commandIdArray.length);
  while ((depth > 0) && (this.currentCmdIDIndex > 0) && (this.currentCmdIDIndex < actionCount)) {
   this.htmlEditor.SetHtmlInternal(this.GetRestoreText(this.currentCmdIDIndex - 1));
   this.GetUndoSelection(this.currentCmdIDIndex - 1).Restore();
   this.currentCmdIDIndex--;
   depth--;
  }
  return true;
 },
 Redo: function(depth) {
  depth = Math.min(depth, this.commandIdArray.length);
  var actionIndex = this.currentCmdIDIndex + 1;
  while (depth > 0 && this.commandIdArray.length >= actionIndex) {
   this.htmlEditor.SetHtmlInternal(this.GetRestoreText(actionIndex));
   this.GetRedoSelection(actionIndex).Restore();
   this.currentCmdIDIndex = actionIndex;
   actionIndex++;
   depth--;
  }
  return true;
 },
 OnCommandExecuting: function(cmdID) {
  if (this.IsUndoRedoCommand(cmdID) &&
   _aspxIsExists(this.commandIdArray[this.currentCmdIDIndex + 1]))
   return;
  if (_aspxIsExists(this.commandIdArray[this.currentCmdIDIndex])) {
   var prevActionUndoSelection = this.htmlEditor.SaveLastSelection();
   if (this.IsLastCommandImmediateExecute()) {
    this.AddNewItemToArray(this.restoreHtmlArray, this.currentCmdIDIndex, this.lastHTML);
    this.UpdateOrAddNewItemToArray(this.undoSelectionArray, this.currentCmdIDIndex, prevActionUndoSelection);
    this.AddNewItemToArray(this.redoSelectionArray, this.currentCmdIDIndex,
      _aspxCloneObject(this.lastRestoreSelection));
   }
   else
    this.undoSelectionArray[this.currentCmdIDIndex] = prevActionUndoSelection;
  }
 },
 OnCommandExecuted: function(needAddToStack) {
  var lastCmdID = this.GetLastCommandID();
  if (needAddToStack && !ASPxHtmlEditorCommandList[lastCmdID].IsImmediateExecution()) {
   this.AddNewItemToArray(this.restoreHtmlArray, this.currentCmdIDIndex, this.GetEditorHtml());
   this.AddNewItemToArray(this.undoSelectionArray, this.currentCmdIDIndex, __aspxEmptySelection);
   this.AddNewItemToArray(this.redoSelectionArray, this.currentCmdIDIndex, this.htmlEditor.SaveLastSelection());
  }
 },
 ClearActionsToRedo: function() {
  if (this.IsRedoAvailable()) {
   this.lastRestoreSelection = null;
   var startIndex = this.currentCmdIDIndex + 1;
   var length = this.commandIdArray.length - this.currentCmdIDIndex;
   this.commandIdArray.splice(startIndex, length);
   this.restoreHtmlArray.splice(startIndex, length);
   this.undoSelectionArray.splice(startIndex, length);
   this.redoSelectionArray.splice(startIndex, length);
  }
 },
 ClearUndoHistory: function() {
  this.lastRestoreSelection = null;
  this.currentCmdIDIndex = -1;
  this.commandIdArray.length = 0;
  this.commandIdArray.length = 0;
  this.restoreHtmlArray.length = 0;
  this.undoSelectionArray.length = 0;
  this.redoSelectionArray.length = 0;
  this.ExecuteCommand(ASPxClientCommandConsts.Start_COMMAND, "null", true);
 },
 CleanEmptyRestoreHtml: function() {
  if (this.GetEditorHtml() == this.lastHTML) {
   _aspxArrayRemoveAt(this.commandIdArray, this.currentCmdIDIndex);
   this.currentCmdIDIndex = this.commandIdArray.length - 1;
  }
 },
 GetEditorHtml: function() {
  return this.htmlEditor.GetHtmlInternal();
 },
 GetRestoreText: function(index) {
  return this.restoreHtmlArray[index];
 },
 GetRedoSelection: function(index) {
  return this.redoSelectionArray[index];
 },
 GetUndoSelection: function(index) {
  return this.undoSelectionArray[index];
 },
 IsRedoAvailable: function() {
  return (this.commandIdArray.length - 1 > this.currentCmdIDIndex);
 },
 IsUndoAvailable: function() {
  return this.currentCmdIDIndex > 0;
 },
 UpdateLastRestoreSelectionAndHTML: function() {
  if (this.lastRestoreSelection == null)
   this.lastRestoreSelection = ASPxClientHtmlEditorSelection.Create(this.htmlEditor);
  this.lastRestoreSelection.Save();
  this.UpdateLastRestoreHtml();
 },
 UpdateLastRestoreHtml: function() {
  this.lastHTML = this.GetEditorHtml();
 },
 UpdateLastItemInRestoreHtmlArray: function() {
  this.restoreHtmlArray[this.restoreHtmlArray.length - 1] = this.GetEditorHtml();
 },
 IsLastCommandImmediateExecute: function() {
  var lastCmdID = this.GetLastCommandID();
  var isImmediateExecution = ASPxHtmlEditorCommandList[lastCmdID].IsImmediateExecution();
  return (lastCmdID != null) && isImmediateExecution &&
    (this.currentCmdIDIndex == this.commandIdArray.length - 1);
 },
 IsDeleting: function() {
  var lastCmdID = this.GetLastCommandID();
  return (lastCmdID != null) && (lastCmdID == ASPxClientCommandConsts.KBDELETE_COMMAND) &&
    (this.currentCmdIDIndex == this.commandIdArray.length - 1);
 },
 IsUndoRedoCommand: function(cmdID) {
  return (cmdID == ASPxClientCommandConsts.REDO_COMMAND) ||
    (cmdID == ASPxClientCommandConsts.UNDO_COMMAND);
 },
 GetLastCommandID: function() {
  var curAction = this.commandIdArray[this.currentCmdIDIndex];
  return _aspxIsExists(curAction) ? curAction : null;
 },
 AddNewItemToArray: function(array, index, value) {
  if (!_aspxIsExists(array[index]))
   _aspxArrayPush(array, value);
 },
 UpdateOrAddNewItemToArray: function(array, index, value) {
  if (!_aspxIsExists(array[index]))
   _aspxArrayPush(array, value);
  else if (array[index] == __aspxEmptySelection)
   array[index] = value;
 }
});
var ASPxShortcuts = [
 [ASPxClientCommandConsts.BOLD_COMMAND, "CTRL+B"],
 [ASPxClientCommandConsts.ITALIC_COMMAND, "CTRL+I"],
 [ASPxClientCommandConsts.UNDERLINE_COMMAND, "CTRL+U"],
 [ASPxClientCommandConsts.JUSTIFYLEFT_COMMAND, "CTRL+L"],
 [ASPxClientCommandConsts.JUSTIFYCENTER_COMMAND, "CTRL+E"],
 [ASPxClientCommandConsts.JUSTIFYRIGHT_COMMAND, "CTRL+R"],
 [ASPxClientCommandConsts.JUSTIFYFULL_COMMAND, "CTRL+J"],
 [ASPxClientCommandConsts.NEWPARAGRAPHTYPE_COMMAND, "CTRL+ENTER"],
 [ASPxClientCommandConsts.LINEBREAKETYPE_COMMAND, "SHIFT+ENTER"],
 [ASPxClientCommandConsts.ENTER_COMMAND, "ENTER"],
 [ASPxClientCommandConsts.UNDO_COMMAND, "CTRL+Z"],
 [ASPxClientCommandConsts.REDO_COMMAND, "CTRL+Y"],
 [ASPxClientCommandConsts.INSERTLINK_DIALOG_COMMAND, "CTRL+K"], 
 [ASPxClientCommandConsts.INSERTIMAGE_DIALOG_COMMAND, "CTRL+G"], 
 [ASPxClientCommandConsts.UNLINK_COMMAND, "CTRL+SHIFT+K"], 
 [ASPxClientCommandConsts.KBPASTE_COMMAND, "CTRL+V"],
 [ASPxClientCommandConsts.KBPASTE_COMMAND, "SHIFT+INSERT"],
 [ASPxClientCommandConsts.KBCUT_COMMAND, "CTRL+X"],
 [ASPxClientCommandConsts.KBCUT_COMMAND, "SHIFT+DELETE"],
 [ASPxClientCommandConsts.KBCOPY_COMMAND, "CTRL+C"],
 [ASPxClientCommandConsts.KBCOPY_COMMAND, "CTRL+INSERT"],
 [ASPxClientCommandConsts.PRINT_COMMAND, "CTRL+P"],
 [ASPxClientCommandConsts.SELECT_ALL, "CTRL+A"]
];
KeyboardManager = _aspxCreateClass(null, {
 constructor: function() {
  this.shortcutCommands = new Array();
 },
 AddShortcut: function(shortcutString, commandID) {
   var shortcutCode = _aspxParseShortcutString(shortcutString);
   this.shortcutCommands[shortcutCode] = commandID;
 }
});
KeyboardManager.prototype.IsSystemKey = function(keyCode) {
 return keyCode == 0 ||
  keyCode >= ASPxKey.F1 && keyCode <= ASPxKey.F12 ||
  keyCode >= ASPxKey.Backspace && keyCode <= ASPxKey.Esc ||
  keyCode >= ASPxKey.Space && keyCode <= ASPxKey.Delete ||
  keyCode == ASPxKey.ContextMenu;
}
KeyboardManager.prototype.IsDeleteOrBackSpaceKey = function(keyCode) {
 return keyCode == ASPxKey.Delete || keyCode == ASPxKey.Backspace;
}
KeyboardManager.prototype.IsBackSpaceKey = function(keyCode) {
 return keyCode == ASPxKey.Backspace;
}
KeyboardManager.prototype.IsCursorMovingKey = function(keyCode) {
 return keyCode >= ASPxKey.PageUp && keyCode <= ASPxKey.Down;
}
KeyboardManager.prototype.GetShortcutCommand = function(evt) { 
 var shortcutCode = _aspxGetShortcutCode(evt.keyCode, evt.ctrlKey, evt.shiftKey, evt.altKey);
 return this.shortcutCommands[shortcutCode];
}
