@syncfusion/ej2-documenteditor
Version:
Feature-rich document editor control with built-in support for context menu, options pane and dialogs.
856 lines • 243 kB
JavaScript
import { WParagraphFormat } from '../format/paragraph-format';
import { WSectionFormat } from '../format/section-format';
import { WCharacterFormat } from '../format/character-format';
import { WListFormat } from '../format/list-format';
import { HistoryInfo } from '../index';
import { ModifiedLevel, RowHistoryFormat, TableHistoryInfo } from './history-helper';
import { BlockWidget, ParagraphWidget, BodyWidget, TableCellWidget, FieldElementBox, TableWidget, TableRowWidget, BookmarkElementBox, HeaderFooterWidget, CheckBoxFormField, TextFrame, TextElementBox, FootnoteElementBox, ImageElementBox, ListTextElementBox } from '../viewer/page';
import { Dictionary } from '../../base/dictionary';
import { abstractListsProperty, listIdProperty, listsProperty, nsidProperty } from '../../index';
import { TextPosition, ImageSizeInfo } from '../index';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { ElementBox, CommentCharacterElementBox } from '../viewer/page';
import { WTableFormat, WRowFormat, WCellFormat, WParagraphStyle } from '../format/index';
import { HelperMethods } from '../editor/editor-helper';
import { CONTROL_CHARACTERS } from '../../base/types';
// Code for Comparing the offset calculated using old approach and optimized approach
// /**
// * @private
// */
// export class MyError extends Error {
// constructor(message: string) {
// super(message);
// }
// }
// export function throwCustomError(condition: boolean, message: string) {
// if (condition) {
// throw new MyError(message);
// }
// }
/**
* @private
*/
var BaseHistoryInfo = /** @class */ (function () {
function BaseHistoryInfo(node) {
this.cellOperation = [];
this.splittedRevisions = [];
this.isRemovedNodes = false;
this.modifiedFormatOperation = [];
this.revisionOperation = [];
/**
* @private
*/
this.markerData = [];
this.ownerIn = node;
this.documentHelper = node.documentHelper;
this.modifiedPropertiesIn = [];
this.modifiedNodeLength = [];
this.removedNodesIn = [];
this.insertedNodes = [];
}
Object.defineProperty(BaseHistoryInfo.prototype, "owner", {
//Properties
//gets owner control
get: function () {
return this.ownerIn;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "editorHistory", {
get: function () {
return this.owner.editorHistoryModule;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "action", {
get: function () {
return this.actionIn;
},
set: function (value) {
this.actionIn = value;
if (this.owner.enableCollaborativeEditing && !this.editorHistory.isUndoing && this.cellOperation.length === 0) {
if (value === 'DeleteColumn' || value === 'DeleteCells' || value === 'ClearCells' || value === 'MergeCells') {
if (!(this.owner.selectionModule.isTableSelected(true) || this.owner.selectionModule.isRowSelect()) || value === 'ClearCells' || value === 'MergeCells') {
this.insertedText = CONTROL_CHARACTERS.Cell;
this.deleteColumnOperation(this.action);
}
}
else if (value === 'Accept Change' || value === 'Reject Change') {
this.createAcceptRejectOperation(this.action);
}
else if (value === 'SectionBreak') {
this.insertedText = CONTROL_CHARACTERS.Section_Break;
this.type = 'NewPage';
}
else if (value === 'SectionBreakContinuous') {
this.insertedText = CONTROL_CHARACTERS.Section_Break;
this.type = 'Continuous';
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "modifiedProperties", {
get: function () {
return this.modifiedPropertiesIn;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "removedNodes", {
/* eslint-enable */
get: function () {
return this.removedNodesIn;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "selectionStart", {
//gets or sets selection start
get: function () {
return this.selectionStartIn;
},
set: function (value) {
this.selectionStartIn = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "selectionEnd", {
get: function () {
return this.selectionEndIn;
},
set: function (value) {
this.selectionEndIn = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "insertPosition", {
get: function () {
return this.insertPositionIn;
},
set: function (value) {
this.insertPositionIn = value;
if (this.owner.enableCollaborativeEditing && !this.owner.editorModule.isRemoteAction && value !== '' && !isNullOrUndefined(value) && value.indexOf('C') === -1) {
//TODO: Insert position not needed in all the cases. Need to optimize it.
this.insertIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(value);
// Code for Comparing the offset calculated using old approach and optimized approach
// this.owner.selection.isNewApproach = true;
// this.newInsertIndex = this.owner.selection.getAbsolutePositionFromRelativePosition(value);
// this.owner.selection.isNewApproach = false;
// throwCustomError(this.newInsertIndex !== this.insertIndex, "New InsertIndex " + this.newInsertIndex + " and old insertIndex " + this.insertIndex + " doesnot match");
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "endPosition", {
get: function () {
return this.endPositionIn;
},
set: function (value) {
this.endPositionIn = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseHistoryInfo.prototype, "viewer", {
get: function () {
return this.ownerIn.viewer;
},
enumerable: true,
configurable: true
});
BaseHistoryInfo.prototype.updateSelection = function () {
this.updateCollaborativeSelection(this.owner.selectionModule.start.clone(), this.owner.selectionModule.end.clone());
var blockInfo = this.owner.selectionModule.getParagraphInfo(this.owner.selectionModule.start);
this.selectionStart = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString());
blockInfo = this.owner.selectionModule.getParagraphInfo(this.owner.selectionModule.end);
this.selectionEnd = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString());
};
BaseHistoryInfo.prototype.updateCollaborativeSelection = function (start, end) {
if (this.owner.enableCollaborativeEditing && !this.owner.editorModule.isRemoteAction) {
//TODO: Need to consider formard and backward selection
if (this.action === 'RemoveEditRange') {
var startEdit = this.owner.selectionModule.getEditRangeStartElement();
var position = this.owner.selectionModule.getPosition(startEdit);
start = position.startPosition;
end = position.endPosition;
}
else {
this.updateTableSelection(start, end);
}
this.startIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(start);
// Code for Comparing the offset calculated using old approach and optimized approach
// this.owner.selection.isNewApproach = true;
// this.newStartIndex = this.owner.selection.getAbsolutePositionFromRelativePosition(start);
// this.owner.selection.isNewApproach = false;
this.owner.selectionModule.isEndOffset = true;
this.endIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(end);
// Code for Comparing the offset calculated using old approach and optimized approach
// this.owner.selection.isNewApproach = true;
// this.newEndIndex = this.owner.selection.getAbsolutePositionFromRelativePosition(end);
// this.owner.selection.isNewApproach = false;
this.owner.selectionModule.isEndOffset = false;
var isForward = this.owner.selectionModule.isForward;
if (isForward) {
this.startIndex -= this.owner.selectionModule.getTableRelativeValue(start, end);
}
else {
this.endIndex -= this.owner.selectionModule.getTableRelativeValue(end, start);
}
// if (this.action === 'BackSpace' || this.action === 'Delete') {
var isParagraphStart = isForward ? (start.paragraph.equals(end.paragraph)
&& start.isAtParagraphStart) : (start.paragraph.equals(end.paragraph) && end.isAtParagraphStart);
if ((isParagraphStart || !start.paragraph.equals(end.paragraph))) {
if (isForward) {
this.endIndex += this.paraInclude(end);
}
else {
this.startIndex += this.paraInclude(start);
}
}
// }
if (!this.owner.enableTrackChanges) {
this.splitOperationForDelete(start, end);
}
// Code for Comparing the offset calculated using old approach and optimized approach
// throwCustomError(this.newStartIndex !== this.startIndex, "New StartIndex " + this.newStartIndex + " and old StartIndex " + this.startIndex + " doesnot match");
// throwCustomError(this.newEndIndex !== this.endIndex, "New EndIndex " + this.newEndIndex + " and old EndIndex " + this.endIndex + " doesnot match");
}
};
BaseHistoryInfo.prototype.paraInclude = function (position) {
var paragrapthInfo = this.owner.selectionModule.getParagraphInfo(position);
if (position.paragraph.getTotalLength() < paragrapthInfo.offset) {
if (!(position.paragraph.isInsideTable
&& position.paragraph.equals(position.paragraph.associatedCell.lastChild))) {
return 1;
}
}
return 0;
};
/**
* This method will set position when the multple cell selected.
*
* @param {TextPosition} startPosition - Specifies the start position.
* @param {TextPosition} endPosition - Specifies the end position.
* @private
* @returns {void}
*/
BaseHistoryInfo.prototype.updateTableSelection = function (startPosition, endPosition) {
var start = startPosition;
var end = endPosition;
if (!this.owner.selectionModule.isForward) {
start = endPosition;
end = startPosition;
}
if (start.paragraph.isInsideTable) {
var firstPara = this.owner.selectionModule.getFirstParagraph(start.paragraph.associatedCell);
if (end.paragraph.isInsideTable) {
if (!start.paragraph.associatedCell.equals(end.paragraph.associatedCell)) {
var lastPara = this.owner.selectionModule.getLastParagraph(end.paragraph.associatedCell);
start.setPosition(firstPara.firstChild, true);
end.setPositionParagraph(lastPara.lastChild, lastPara.lastChild.getEndOffset() + 1);
}
}
else {
start.setPosition(firstPara.firstChild, true);
}
}
else if (end.paragraph.isInsideTable) {
var lastPara = this.owner.selectionModule.getLastParagraph(end.paragraph.associatedCell);
end.setPositionParagraph(lastPara.lastChild, lastPara.lastChild.getEndOffset() + 1);
}
};
/**
* start is para and end is in row.
*
* @param {TextPosition} startPosition - Specifies the start position.
* @param {TextPosition} endPosition - Specifies the end position.
* @private
* @returns {void}
*/
BaseHistoryInfo.prototype.splitOperationForDelete = function (startPosition, endPosition) {
// when start is para and end is row. we are building the operation like:
// fisrt delete the end table from table start to selection end.
// second need to paste the content from the start para and need to paste it in the next row.
// third delete the start paragraph to before wiget of end table.
var start = startPosition;
var end = endPosition;
if (!this.owner.selectionModule.isForward) {
start = endPosition;
end = startPosition;
}
if (!start.paragraph.isInsideTable && end.paragraph.isInsideTable && (this.action === 'BackSpace' || this.action === 'Delete')) {
var lastParagraph = this.owner.selectionModule.getLastBlockInLastCell(end.paragraph.associatedCell.ownerTable);
if (!lastParagraph.associatedCell.equals(end.paragraph.associatedCell)) {
var PasteLength = this.startIndex;
var endLineWidget = start.currentWidget;
var endOffset = start.offset;
start.setPosition(start.paragraph.firstChild, true);
this.startIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(start);
var startIndex = this.startIndex;
var table = this.owner.documentHelper.layout.getParentTable(end.paragraph.associatedCell.ownerTable);
var paragraphInfo = { 'paragraph': null, 'offset': 0 };
var tableStart = this.owner.selectionModule.getPositionInfoForHeaderFooter(paragraphInfo, { position: 0, done: false }, table).position;
// Table start will get the offset for table. So adding plus one to row offset.
this.startIndex = tableStart + 1;
this.cellOperation.push(this.getDeleteOperation(this.action));
// This will add the paste content in first and first cell so adding plus 3.
this.startIndex = tableStart + 3;
if (endOffset !== 0) {
this.pasteContent = this.owner.sfdtExportModule.write((this.owner.documentEditorSettings.optimizeSfdt ? 1 : 0), start.currentWidget, start.offset, endLineWidget, endOffset, false, true);
this.cellOperation.push(this.getPasteOpertion(this.pasteContent, PasteLength - startIndex));
}
this.endIndex = tableStart;
this.startIndex = startIndex;
this.cellOperation.push(this.getDeleteOperation(this.action));
}
}
if (this.action === 'PasteColumn' || this.action === 'PasteOverwrite' || this.action === 'PasteRow') {
//when inserting new colomn in paste. first deleting the table and inserting the whole table.
var table = startPosition.paragraph.associatedCell.ownerTable;
var paragraphInfo = { 'paragraph': null, 'offset': 0 };
this.startIndex = this.owner.selectionModule.getPositionInfoForHeaderFooter(paragraphInfo, { position: 0, done: false }, table).position;
this.endIndex = this.startIndex + this.owner.selectionModule.getBlockLength(undefined, table, 0, { done: false }, true, undefined, undefined);
}
};
BaseHistoryInfo.prototype.setBookmarkInfo = function (bookmark) {
this.removedNodes.push({ 'bookmark': bookmark, 'startIndex': bookmark.indexInOwner, 'endIndex': bookmark.reference.indexInOwner });
};
BaseHistoryInfo.prototype.setContentControlInfo = function (contentControl) {
this.removedNodes.push({ 'contentcontrol': contentControl, 'startIndex': contentControl.indexInOwner, 'endIndex': contentControl.reference.indexInOwner });
};
BaseHistoryInfo.prototype.setFormFieldInfo = function (field, value) {
this.removedNodes.push({ 'formField': field, 'value': value });
};
BaseHistoryInfo.prototype.setEditRangeInfo = function (editStart) {
this.removedNodes.push({ 'editStart': editStart, 'startIndex': editStart.indexInOwner, 'endIndex': editStart.editRangeEnd.indexInOwner });
};
BaseHistoryInfo.prototype.revertFormTextFormat = function () {
/* eslint-disable @typescript-eslint/no-explicit-any */
var fieldInfo = this.removedNodes[0];
var text = fieldInfo.value;
/* eslint-enable @typescript-eslint/no-explicit-any */
var formField = fieldInfo.formField;
if (this.editorHistory.isUndoing) {
this.owner.editorModule.applyTextFormatInternal(formField, text);
this.editorHistory.recordChanges(this);
}
else {
text = HelperMethods.formatText(formField.formFieldData.format, text);
this.owner.editorModule.applyTextFormatInternal(formField, text);
this.editorHistory.undoStack.push(this);
}
};
BaseHistoryInfo.prototype.revertFormField = function () {
/* eslint-disable @typescript-eslint/no-explicit-any */
var fieldInfo = this.removedNodes[0];
/* eslint-enable @typescript-eslint/no-explicit-any */
var field = fieldInfo.formField;
if (field.formFieldData instanceof CheckBoxFormField) {
this.owner.editorModule.toggleCheckBoxFormField(field, true, fieldInfo.value);
}
else {
this.owner.editorModule.updateFormField(field, fieldInfo.value);
}
};
BaseHistoryInfo.prototype.revertContentControl = function () {
var contentControlInfo = this.removedNodes[0];
var contentcontrol = contentControlInfo.contentcontrol;
if (this.editorHistory.isUndoing) {
var markerData = this.owner.editorModule.getMarkerData(contentcontrol);
this.documentHelper.contentControlCollection.push(contentcontrol);
this.markerData.push(markerData);
contentcontrol.line.children.splice(contentControlInfo.startIndex, 0, contentcontrol);
//const previousNode: ElementBox = contentControl.previousNode;
this.markerData.push(markerData);
contentcontrol.reference.line.children.splice(contentControlInfo.endIndex, 0, contentcontrol.reference);
this.editorHistory.recordChanges(this);
this.viewer.updateScrollBars();
this.owner.editorModule.fireContentChange();
}
else {
this.owner.editorModule.removeContentControlInternal();
this.editorHistory.undoStack.push(this);
}
};
BaseHistoryInfo.prototype.revertBookmark = function () {
var bookmarkInfo = this.removedNodes[0];
var bookmark = bookmarkInfo.bookmark;
if (this.editorHistory.isUndoing) {
var markerData = this.owner.editorModule.getMarkerData(bookmark);
this.documentHelper.bookmarks.add(bookmark.name, bookmark);
this.markerData.push(markerData);
bookmark.line.children.splice(bookmarkInfo.startIndex, 0, bookmark);
var previousNode = bookmark.previousNode;
if (previousNode instanceof FieldElementBox && !isNullOrUndefined(previousNode.formFieldData)) {
previousNode.formFieldData.name = bookmark.name;
}
this.markerData.push(markerData);
bookmark.reference.line.children.splice(bookmarkInfo.endIndex, 0, bookmark.reference);
this.editorHistory.recordChanges(this);
if (this.owner.documentEditorSettings.showBookmarks === true) {
this.viewer.updateScrollBars();
}
this.owner.editorModule.fireContentChange();
}
else {
this.owner.editorModule.deleteBookmarkInternal(bookmark);
this.editorHistory.undoStack.push(this);
}
};
BaseHistoryInfo.prototype.revertComment = function () {
var editPosition = this.insertPosition;
var comment = this.removedNodes[0];
var insert = false;
if (this.action === 'ResolveComment') {
this.editorHistory.currentBaseHistoryInfo = this;
this.owner.editorModule.resolveOrReopenComment(comment, !comment.isResolved);
return;
}
if (this.action === 'EditComment') {
var modifiedCommentObject = this.modifiedProperties[0];
this.editorHistory.currentBaseHistoryInfo = this;
var commentView = this.owner.commentReviewPane.commentPane.comments.get(comment);
commentView.commentText.innerText = modifiedCommentObject.text;
modifiedCommentObject.text = comment.text;
comment.text = commentView.commentText.innerText;
this.owner.editorHistoryModule.updateHistory();
this.owner.fireContentChange();
return;
}
if (this.action === 'InsertCommentWidget') {
insert = (this.editorHistory.isRedoing);
}
else if (this.action === 'DeleteCommentWidget') {
insert = (this.editorHistory.isUndoing);
}
if (insert) {
if (comment) {
this.insertedElement = comment.clone();
if (comment.isReply) {
this.owner.editorModule.addReplyComment(comment, this.insertPosition);
}
else {
this.owner.editorModule.addCommentWidget(comment, false, true, true);
}
}
}
else {
var commentElement = this.owner.editorModule.getCommentElementBox(editPosition);
this.owner.editorModule.deleteCommentWidget(commentElement);
}
};
BaseHistoryInfo.prototype.revertEditRangeRegion = function () {
var editRangeInfo = this.removedNodes[0];
var editStart = editRangeInfo.editStart;
if (this.editorHistory.isUndoing) {
var user = editStart.user === '' ? editStart.group : editStart.user;
this.owner.editorModule.updateRangeCollection(editStart, user);
this.markerData.push(this.owner.editorModule.getMarkerData(editStart));
this.markerData.push(this.owner.editorModule.getMarkerData(editStart.editRangeEnd));
editStart.line.children.splice(editRangeInfo.startIndex, 0, editStart);
editStart.editRangeEnd.line.children.splice(editRangeInfo.endIndex, 0, editStart.editRangeEnd);
this.editorHistory.recordChanges(this);
}
else {
this.owner.editorModule.removeUserRestrictionsInternal(editStart);
this.editorHistory.undoStack.push(this);
}
this.owner.editorModule.fireContentChange();
};
/* eslint-disable */
BaseHistoryInfo.prototype.revert = function () {
if (this.action === 'FormTextFormat') {
this.revertFormTextFormat();
return;
}
if (this.action === 'UpdateFormField') {
this.revertFormField();
return;
}
if (this.action === 'DeleteBookmark') {
this.revertBookmark();
return;
}
if (this.action === 'RemoveContentControl') {
this.revertContentControl();
return;
}
if (this.action === 'RemoveEditRange') {
this.revertEditRangeRegion();
return;
}
if (this.action === 'InsertCommentWidget' || this.action === 'DeleteCommentWidget' || this.action === 'ResolveComment' || this.action === 'EditComment') {
this.revertComment();
return;
}
if (this.action === 'ListFormat' && this.owner.editorModule.listNumberFormat !== '') {
var abstractList = this.documentHelper.lists[0].abstractList.levels[this.owner.editorModule.listLevelNumber];
var currentListLevelPattern = abstractList.listLevelPattern;
var currentNUmberFormat = abstractList.numberFormat;
abstractList.listLevelPattern = this.owner.editorModule.listLevelPattern;
abstractList.numberFormat = this.owner.editorModule.listNumberFormat;
this.owner.editorModule.listLevelPattern = currentListLevelPattern;
this.owner.editorModule.listNumberFormat = currentNUmberFormat;
}
this.owner.isShiftingEnabled = true;
var selectionStartTextPosition = undefined;
var selectionEndTextPosition = undefined;
var start = this.selectionStart;
var end = this.selectionEnd;
this.collabStart = this.selectionStart;
this.collabEnd = this.selectionEnd;
var isForwardSelection = TextPosition.isForwardSelection(start, end);
if (this.modifiedProperties.length > 0 || this.action === 'Selection'
|| this.action === 'ClearCharacterFormat' || this.action === 'ClearParagraphFormat') {
selectionStartTextPosition = !isNullOrUndefined(start) ? this.owner.selectionModule.getTextPosBasedOnLogicalIndex(start) : undefined;
selectionEndTextPosition = !isNullOrUndefined(end) ? this.owner.selectionModule.getTextPosBasedOnLogicalIndex(end) : undefined;
if (this.owner.enableCollaborativeEditing) {
this.updateCollaborativeSelection(selectionStartTextPosition, selectionEndTextPosition);
}
this.revertModifiedProperties(selectionStartTextPosition, selectionEndTextPosition);
}
else {
if (this.owner.enableCollaborativeEditing) {
if (!isNullOrUndefined(this.insertPosition)) {
this.insertIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(this.insertPosition);
}
if (!isNullOrUndefined(this.endPosition)) {
var startPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.insertPosition);
var endPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.endPosition);
this.updateCollaborativeSelection(startPosition, endPosition);
}
}
var sel = this.owner.selectionModule;
var deletedNodes = this.removedNodes;
if (this.removedNodes.length > 0) {
if (this.action === 'InsertTable' && this.editorHistory.isRedoing) {
for (var i = 0; i < this.removedNodes.length; i++) {
this.insertedNodes.push(this.removedNodes[parseInt(i.toString(), 10)]);
}
}
this.isRemovedNodes = true;
}
else {
this.isRemovedNodes = false;
}
this.removedNodesIn = [];
if (isNullOrUndefined(this.endPosition)) {
this.endPosition = this.insertPosition;
}
var isForward = TextPosition.isForwardSelection(this.insertPosition, this.endPosition);
var insertTextPosition = sel.getTextPosBasedOnLogicalIndex(isForward ? this.insertPosition : this.endPosition);
var endTextPosition = sel.getTextPosBasedOnLogicalIndex(isForward ? this.endPosition : this.insertPosition);
// Set the endRevisionLogicalIndex based on undo stack value when the selection contains a table with the above paragraph (undoing).
if (this.action === 'RemoveRowTrack' && this.editorHistory.isUndoing) {
this.owner.selectionModule.select(this.selectionEnd, this.selectionEnd);
var isLastChild = (this.owner.selectionModule.start.paragraph === this.owner.editor.getLastParaForBodywidgetCollection(this.owner.selectionModule.start.paragraph));
if (this.owner.selectionModule.start.paragraph.isInsideTable || isLastChild && this.owner.selectionModule.end.paragraph.isEmpty() && deletedNodes.length > 0 && deletedNodes[0] instanceof TableWidget) {
this.endRevisionLogicalIndex = this.selectionEnd;
}
}
if (this.editorHistory.isUndoing) {
if (this.lastElementRevision && isNullOrUndefined(this.isAcceptOrReject) && deletedNodes.length > 0 && deletedNodes[0] instanceof ParagraphWidget && deletedNodes[0].isEmpty()) {
this.endRevisionLogicalIndex = this.selectionEnd;
}
else if (this.action === 'Delete' && this.editorHistory.currentHistoryInfo
&& this.editorHistory.currentHistoryInfo.action === 'RemoveHyperlink'
&& this.lastElementRevision instanceof FieldElementBox) {
// Bug 873011: Updated the selection for delete operation on "RemoveHyperlink" undo case.
this.endRevisionLogicalIndex = this.selectionEnd;
}
else if (this.lastElementRevision && isNullOrUndefined(this.endRevisionLogicalIndex)) {
this.updateEndRevisionInfo();
}
else if (this.action === 'RemoveRowTrack') {
this.endRevisionLogicalIndex = this.selectionEnd;
}
}
if (this.action === 'ClearRevisions') {
// Bug 873011: Handled the separate undo revision for field begin and field end for "ClearRevisions" action on hyperlink undo.
var fieldBegin = sel.getHyperlinkField();
if (this.isHyperlinkField && !isNullOrUndefined(fieldBegin)) {
var offset = fieldBegin.fieldSeparator.line.getOffset(fieldBegin.fieldSeparator, 1);
endTextPosition.setPositionParagraph(fieldBegin.fieldSeparator.line, offset);
this.undoRevisionForElements(insertTextPosition, endTextPosition, deletedNodes[deletedNodes.length - 1]);
var fieldEnd = fieldBegin.fieldEnd;
insertTextPosition.setPositionParagraph(fieldEnd.line, fieldEnd.line.getOffset(fieldEnd, 0));
endTextPosition.setPositionParagraph(fieldEnd.line, fieldEnd.line.getOffset(fieldEnd, 1));
this.undoRevisionForElements(insertTextPosition, endTextPosition, deletedNodes[deletedNodes.length - 1]);
}
else {
this.owner.selectionModule.select(this.selectionEnd, this.selectionEnd);
this.undoRevisionForElements(insertTextPosition, endTextPosition, deletedNodes[deletedNodes.length - 1]);
}
this.removedNodes.push(deletedNodes[deletedNodes.length - 1]);
deletedNodes = [];
}
if (this.action === 'Uppercase') {
sel.selectPosition(insertTextPosition, endTextPosition);
this.editorHistory.currentBaseHistoryInfo = this;
var editModule = this.owner.editorModule;
editModule.changeSelectedTextCase(sel, insertTextPosition, endTextPosition, this.action.toString(), deletedNodes);
editModule.reLayout(sel);
return;
}
if (this.action === 'Lowercase') {
sel.selectPosition(insertTextPosition, endTextPosition);
this.editorHistory.currentBaseHistoryInfo = this;
var editModule = this.owner.editorModule;
editModule.changeSelectedTextCase(sel, insertTextPosition, endTextPosition, this.action.toString(), deletedNodes);
editModule.reLayout(sel);
return;
}
if (this.action === 'CapitalizeEachWord') {
sel.selectPosition(insertTextPosition, endTextPosition);
this.editorHistory.currentBaseHistoryInfo = this;
var editModule = this.owner.editorModule;
editModule.changeSelectedTextCase(sel, insertTextPosition, endTextPosition, this.action.toString(), deletedNodes);
editModule.reLayout(sel);
return;
}
if (this.action === 'SentenceCase') {
sel.selectPosition(insertTextPosition, endTextPosition);
this.editorHistory.currentBaseHistoryInfo = this;
var editModule = this.owner.editorModule;
editModule.changeSelectedTextCase(sel, insertTextPosition, endTextPosition, this.action.toString(), deletedNodes);
editModule.reLayout(sel);
return;
}
if (this.action === 'ToggleCase') {
sel.selectPosition(insertTextPosition, endTextPosition);
this.editorHistory.currentBaseHistoryInfo = this;
var editModule = this.owner.editorModule;
editModule.changeSelectedTextCase(sel, insertTextPosition, endTextPosition, this.action.toString(), deletedNodes);
editModule.reLayout(sel);
return;
}
if (insertTextPosition.isAtSamePosition(endTextPosition)) {
sel.selectContent(insertTextPosition, true);
}
else {
sel.selectPosition(insertTextPosition, endTextPosition);
}
if (this.action === 'InsertHyperlink' && this.editorHistory.isRedoing) {
var fieldBegin = this.owner.selectionModule.getHyperlinkField();
if (!isNullOrUndefined(fieldBegin)) {
var offset = (fieldBegin.line).getOffset(fieldBegin, 0);
insertTextPosition.setPositionParagraph(fieldBegin.line, offset);
this.owner.selectionModule.start.setPositionInternal(insertTextPosition);
offset = fieldBegin.fieldEnd.line.getOffset(fieldBegin.fieldEnd, 1);
endTextPosition.setPositionParagraph(fieldBegin.fieldEnd.line, offset);
}
}
this.editorHistory.currentBaseHistoryInfo = this;
this.selectionStart = this.insertPosition;
this.insertPosition = undefined;
this.selectionEnd = this.endPosition;
this.endPosition = undefined;
// Use this property to skip deletion if already selected content deleted case.
var isRemoveContent = false;
var isDeletecell = false;
if (this.action === 'DeleteCells' || this.action === 'RemoveRowTrack') {
isDeletecell = true;
}
if (this.endRevisionLogicalIndex && deletedNodes.length > 0) {
var currentPosition = sel.getTextPosBasedOnLogicalIndex(this.endRevisionLogicalIndex);
if (this.editorHistory.isUndoing || (this.editorHistory.isRedoing && insertTextPosition.isAtSamePosition(endTextPosition))) {
sel.selectPosition(insertTextPosition, currentPosition);
}
this.collabEnd = this.endRevisionLogicalIndex;
if (this.owner.enableCollaborativeEditing) {
this.endIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(currentPosition);
this.endIndex += this.paraInclude(currentPosition);
}
if (this.editorHistory.isUndoing || (this.editorHistory.isRedoing && !this.owner.selectionModule.isEmpty && deletedNodes.length > 0)) {
this.owner.editorModule.deleteSelectedContents(sel, true, isDeletecell);
isRemoveContent = true;
}
}
if (!insertTextPosition.isAtSamePosition(endTextPosition) && !isRemoveContent) {
isRemoveContent = this.action === 'BackSpace' || this.action === 'Delete' || this.action === 'ClearCells'
|| this.action === 'DeleteCells';
var skipDelete = (deletedNodes.length > 0 && this.action === 'ParaMarkTrack') || this.action === 'ClearRevisions' || this.action === 'AcceptTOC';
if (!(isRemoveContent) && this.action !== 'MergeCells' && this.action !== 'InsertRowAbove'
&& this.action !== 'InsertRowBelow' && this.action !== 'InsertColumnLeft'
&& this.action !== 'InsertColumnRight' && this.action !== 'Borders'
&& this.action !== 'DeleteTable' && this.action !== 'DeleteColumn' && this.action !== 'DeleteRow') {
sel.end.setPositionInternal(endTextPosition);
if (!this.owner.selectionModule.isEmpty && !skipDelete) {
if (this.editorHistory.isRedoing && this.action !== 'Accept Change' && this.action !== 'ParaMarkTrack' &&
this.action !== 'ParaMarkReject' && this.action !== 'RemoveRowTrack') {
this.owner.editorModule.removeSelectedContents(sel);
}
else {
// Bug 873011: Handled the separate deletion for field begin and field end for "Accept Change" action on hyperlink redo.
var fieldBegin = sel.getHyperlinkField();
if (this.isHyperlinkField && !isNullOrUndefined(fieldBegin)
&& this.editorHistory.isRedoing && this.action === 'Accept Change') {
var fieldEnd = fieldBegin.fieldEnd;
sel.start.setPositionParagraph(fieldBegin.line, (fieldBegin.line).getOffset(fieldBegin, 0));
sel.end.setPositionParagraph(fieldBegin.fieldSeparator.line, (fieldBegin.fieldSeparator.line).getOffset(fieldBegin.fieldSeparator, 1));
this.owner.editorModule.deleteSelectedContents(sel, true);
if (this.editorHistory && this.editorHistory.currentBaseHistoryInfo) {
this.editorHistory.currentBaseHistoryInfo.removedNodes.reverse();
}
sel.start.setPositionParagraph(fieldEnd.line, (fieldEnd.line).getOffset(fieldEnd, 0));
sel.end.setPositionParagraph(fieldEnd.line, (fieldEnd.line).getOffset(fieldEnd, 1));
this.owner.editorModule.deleteSelectedContents(sel, true);
if (this.editorHistory && this.editorHistory.currentBaseHistoryInfo) {
this.editorHistory.currentBaseHistoryInfo.removedNodes.reverse();
}
}
else {
this.owner.editorModule.deleteSelectedContents(sel, true);
}
}
if (!isNullOrUndefined(this.editorHistory.currentHistoryInfo) &&
this.editorHistory.currentHistoryInfo.action === 'PageBreak' && this.documentHelper.blockToShift) {
this.documentHelper.layout.shiftLayoutedItems(false);
}
}
}
}
else if (this.action === 'SectionBreakContinuous' && insertTextPosition && this.editorHistory.isUndoing) {
if (insertTextPosition.offset === 0 && !isNullOrUndefined(insertTextPosition.paragraph.previousRenderedWidget) && insertTextPosition.paragraph.previousRenderedWidget instanceof ParagraphWidget && insertTextPosition.paragraph.previousRenderedWidget.isEndsWithPageBreak && insertTextPosition.paragraph.containerWidget instanceof BodyWidget && insertTextPosition.currentWidget === insertTextPosition.currentWidget.paragraph.firstChild && insertTextPosition.paragraph.containerWidget.sectionFormat.breakCode === 'NoBreak') {
var section = insertTextPosition.paragraph.previousRenderedWidget.containerWidget;
this.owner.editorModule.combineSectionInternal(this.owner.selectionModule, section, insertTextPosition.paragraph.containerWidget);
this.owner.editorModule.layoutWholeDocument();
}
}
else {
isRemoveContent = false;
if (!insertTextPosition.isAtSamePosition(endTextPosition)) {
isRemoveContent = this.action === 'BackSpace' || this.action === 'Delete' || this.action === 'ClearCells'
|| this.action === 'DeleteCells';
}
}
var isRedoAction = (this.editorHistory.isRedoing && !isRemoveContent);
isRemoveContent = this.lastElementRevision ? false : isRemoveContent;
this.revertModifiedNodes(deletedNodes, isRedoAction, isForwardSelection ? start : end, start === end, isForwardSelection ? end : start);
// Use this property to delete table or cell based on history action.
if (isRemoveContent) {
this.removeContent(insertTextPosition, endTextPosition, isDeletecell);
}
//this.owner.editorModule.reLayout(this.documentHelper.selection);
}
var isSelectionChanged = false;
var updateSelection = false;
if (!isNullOrUndefined(this.editorHistory.currentHistoryInfo) && (this.editorHistory.currentHistoryInfo.action === 'Reject All' || this.editorHistory.currentHistoryInfo.action === 'Accept All' || this.editorHistory.currentHistoryInfo.action === 'Paste')) {
updateSelection = true;
}
if (this.action !== 'TrackingPageBreak' && ((this.editorHistory.isUndoing || this.endRevisionLogicalIndex || this.action === 'RemoveRowTrack' || updateSelection) && isNullOrUndefined(this.editorHistory.currentHistoryInfo) || updateSelection) ||
((this.action === 'InsertRowAbove' || this.action === 'Borders' || this.action === 'InsertRowBelow' || this.action === 'InsertColumnLeft' || this.action === 'InsertColumnRight' || this.action === 'Accept Change' || this.action === 'PasteColumn' || this.action === 'PasteRow' || this.action === 'PasteOverwrite' || this.action === 'PasteNested') && (this.editorHistory.isRedoing
|| this.editorHistory.currentHistoryInfo.action === 'Paste'))) {
if (this.action === 'RemoveRowTrack' && this.editorHistory.isRedoing) {
selectionStartTextPosition = !isNullOrUndefined(this.selectionStart) ? this.owner.selectionModule.getTextPosBasedOnLogicalIndex(this.selectionStart) : undefined;
selectionEndTextPosition = !isNullOrUndefined(this.selectionEnd) ? this.owner.selectionModule.getTextPosBasedOnLogicalIndex(this.selectionEnd) : undefined;
}
else {
selectionStartTextPosition = !isNullOrUndefined(start) ? this.owner.selectionModule.getTextPosBasedOnLogicalIndex(start) : undefined;
selectionEndTextPosition = !isNullOrUndefined(end) ? this.owner.selectionModule.getTextPosBasedOnLogicalIndex(end) : undefined;
}
if (this.action !== 'ModifyStyle') {
this.owner.selectionModule.selectRange(selectionStartTextPosition, selectionEndTextPosition);
}
this.documentHelper.updateFocus();
isSelectionChanged = true;
}
this.owner.trackChangesPane.isTrackingPageBreak = false;
var index = this.insertIndex;
// Updates insert position of history info instance.
this.insertPosition = start;
this.endPosition = end;
if (this.action === 'InsertHyperlink') {
this.insertIndex = index;
}
if (!isNullOrUndefined(this.editorHistory.currentHistoryInfo) &&
(this.editorHistory.currentHistoryInfo.action === 'Accept All'
|| this.editorHistory.currentHistoryInfo.action === 'Reject All' || this.editorHistory.currentHistoryInfo.action === 'RemoveComment')) {
if (this.owner.documentHelper.blockToShift) {
this.owner.documentHelper.layout.shiftLayoutedItems(false);
}
}
this.owner.editorModule.reLayout(this.owner.selectionModule, this.owner.selectionModule.isEmpty);
if (this.editorHistory.isUndoing && this.action === 'SectionBreak') {
this.owner.editorModule.isSkipOperationsBuild = this.owner.enableCollaborativeEditing;
this.owner.editorModule.layoutWholeDocument();
this.owner.editorModule.isSkipOperationsBuild = false;
}
if (isSelectionChanged) {
this.documentHelper.scrollToPosition(this.owner.selectionModule.start, this.owner.selectionModule.end);
}
this.highlightListText();
};
BaseHistoryInfo.prototype.highlightListText = function () {
if (!isNullOrUndefined(this.editorHistory.currentHistoryInfo)) {
if (this.action === 'ListCharacterFormat' || (this.editorHistory.currentHistoryInfo.action === 'ListSelect' && this.action === 'ListFormat')) {
var selectionStartTextPosition = this.owner.selectionModule.getTextPosBasedOnLogicalIndex(this.selectionStart);
var widget = selectionStartTextPosition.currentWidget;
this.documentHelper.selection.highlightListText(widget);
}
}
};
BaseHistoryInfo.prototype.removeContent = function (insertTextPosition, endTextPosition, isDeletecell) {
//If the base parent of the insert text position and end text position is null
//then the paragraphs already removed.
//Example scenario: In table editing that is delete cells operation
// we will backed up the entire table ad it will be replaced on undo operation.
//At that time if the positions are in table
//which is already replaced in undo (revert modified nodes method) then the base parent of the paragraph will be null.
//So again, selecting the content and deleting is unnecessary
// and it will cause improper position updates and null reference exceptions.
if ((!isNullOrUndefined(insertTextPosition.paragraph.containerWidget) &&
insertTextPosition.paragraph.containerWidget instanceof BodyWidget &&
(!isNullOrUndefined(endTextPosition.paragraph.containerWidget)
&& endTextPosition.paragraph.containerWidget instanceof BodyWidget))
|| (!isNullOrUndefined(insertTextPosition.paragraph.containerWidget)
&& !isNullOrUndefined(endTextPosition.paragraph.containerWidget)
&& insertTextPosition.paragraph.containerWidget instanceof TableCellWidget
&& endTextPosition.paragraph.containerWidget instanceof TableCellWidget
&& !isNullOrUndefined(insertTextPosition.paragraph.bodyWidget)) ||
(!isNullOrUndefined(insertTextPosition.paragraph.containerWidget)
&& !isNullOrUndefined(endTextPosition.paragraph.containerWidget)
&& insertTextPosition.paragraph.containerWidget instanceof TextFrame
&& endTextPosition.paragraph.containerWidget instanceof TextFrame)) {
//Removes if any empty paragraph is added while delete.
this.owner.selectionModule.selectRange(insertTextPosition, endTextPosition);
this.documentHelper.updateFocus();
var isDelete = false;
if (this.action === 'BackSpace' || this.action === 'Uppercase' || this.action === 'RemoveRowTrack') {
isDelete = true;
}
this.owner.editorModule.deleteSelectedContents(this.owner.selectionModule, isDelete, isDeletecell);
}
};
BaseHistoryInfo.prototype.updateEndRevisionInfo = function () {
this.lastElementRevision = this.checkAdjacentNodeForMarkedRevision(this.lastElementRevision);
var currentRevision = this.retrieveEndPosition(this.lastElementRevision);
var blockInfo = this.owner.selectionModule.getParagraphInfo(currentRevision);
var isLastChild = (blockInfo.paragraph == this.owner.editor.getLastParaForBodywidgetCollection(blockInfo.paragraph));
if (blockInfo.paragraph.isInsideTable && blockInfo.paragraph == this.owner.selection.getLastParagraph(blockInfo.paragraph.associatedCell)) {
isLastChild = true;
}
if (blockInfo.paragraph.getLength() == blockInfo.offset && !isLastChild) {
blockInfo.offset++;
}
this.endRevisionLogicalIndex = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString());
this.lastElementRevision.isMarkedForRevision = false;
};
BaseHistoryInfo.prototype.retrieveEndPosition = function (elementBox) {
var endPosition = new TextPosition(this.owner);
var offset = elementBox.line.getOffset(elementBox, 0) + elementBox.length;
endPosition.setPositionFromLine(elementBox.line, offset);
return endPosition;
};
/**
* Method to retrieve exact spitted node which is marked as last available element.
*
* @param {ElementBox} elementBox - Specifies the element box
* @returns {ElementBox} - Returns ele