UNPKG

@syncfusion/ej2-documenteditor

Version:

Feature-rich document editor control with built-in support for context menu, options pane and dialogs.

849 lines 245 kB
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, ListTextElementBox, ErrorTextElementBox } 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.isRemovedNodes = false; this.modifiedFormatOperation = []; this.revisionOperation = []; /** * @private */ this.isClearCell = false; /** * @private */ this.markerData = []; /** * @private */ this.listInfo = undefined; /** * @private */ this.pastedComments = []; 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 === '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.isAtParagraphEnd) : (start.paragraph.equals(end.paragraph) && end.isAtParagraphStart || end.isAtParagraphEnd); 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.setContentControlCheckBox = function (contentControl, value) { this.removedNodes.push({ 'contentControlCheckBox': contentControl, 'value': value }); }; 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.markerData.push(markerData); contentcontrol.line.children.splice(contentControlInfo.startIndex, 0, contentcontrol); this.documentHelper.owner.editorModule.insertContentControlInCollection(contentcontrol); //const previousNode: ElementBox = contentControl.previousNode; this.markerData.push(markerData); contentcontrol.reference.line.children.splice(contentControlInfo.endIndex, 0, contentcontrol.reference); this.owner.editorModule.updatePropertiesToBlock(contentcontrol, true); this.owner.selectionModule.updateContentControlHighlightSelection(); 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; // When perform undo, redo for drag and drop operation, bookmark reference changed so we couldn't insert or delete proper bookmark. so updated the bookmark based on name. if (!isNullOrUndefined(bookmark) && (bookmark.line.indexInOwner === -1 || bookmark.line.paragraph.indexInOwner === -1) && !isNullOrUndefined(this.owner.documentHelper) && this.owner.documentHelper.bookmarks.length > 0 && !isNullOrUndefined(bookmark.line.paragraph.containerWidget)) { bookmark = this.owner.documentHelper.bookmarks.get(bookmark.name); this.removedNodes[0].bookmark = bookmark; } if (this.editorHistory.isUndoing) { if (isNullOrUndefined(bookmark.line.paragraph.containerWidget) && !isNullOrUndefined(this.owner.selection)) { var startPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.selectionStart); var endPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.selectionEnd); bookmark.line = startPosition.currentWidget; bookmark.reference.line = endPosition.currentWidget; } 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); // Skip recording the changes if the currentHistoryInfo action is InsertBookmark. Because, the changes will be recorded in the update complex history. // Need to skip recording changes if the currentHistoryInfo action is Grouping. Because in grouping the history already recorded while updating complex history. if (!this.editorHistory.currentHistoryInfo || (this.editorHistory.currentHistoryInfo && this.editorHistory.currentHistoryInfo.action !== 'InsertBookmark' && this.editorHistory.currentHistoryInfo.action !== 'Grouping')) { this.editorHistory.recordChanges(this); } if (this.owner.documentEditorSettings.showBookmarks === true) { this.viewer.updateScrollBars(); } this.owner.editorModule.fireContentChange(); } else { this.owner.editorModule.deleteBookmarkInternal(bookmark); // Skip recording the changes if the currentHistoryInfo action is InsertBookmark. Because, the changes will be recorded in the update complex history. // Need to skip recording changes if the currentHistoryInfo action is Grouping. Because in grouping the history already recorded while updating complex history. if (!this.editorHistory.currentHistoryInfo || (this.editorHistory.currentHistoryInfo && this.editorHistory.currentHistoryInfo.action !== 'InsertBookmark' && this.editorHistory.currentHistoryInfo.action !== 'Grouping')) { 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(); }; BaseHistoryInfo.prototype.revertContentControlProperties = function () { var start = this.selectionStart; var end = this.selectionEnd; if (!isNullOrUndefined(this.selectionStart) && !isNullOrUndefined(this.selectionEnd)) { var selectionStartTextPosition = this.owner.selectionModule.getTextPosBasedOnLogicalIndex(start); var selectionEndTextPosition = this.owner.selectionModule.getTextPosBasedOnLogicalIndex(end); this.owner.selectionModule.selectRange(selectionStartTextPosition, selectionEndTextPosition); var contentcontrol = this.owner.selection.currentContentControl; if (contentcontrol) { if (contentcontrol.contentControlProperties.type === 'CheckBox' && this.modifiedProperties.length === 0) { var contentControlInfo = this.removedNodes[0]; this.owner.editorModule.toggleContentControlCheckBox(contentcontrol, !contentControlInfo.value); contentControlInfo.value = !contentControlInfo.value; } else { var contenControlObject = this.modifiedProperties.pop(); this.editorHistory.currentBaseHistoryInfo = this; var content = this.owner.editorModule.getContentControlPropObject(contentcontrol.contentControlProperties); this.owner.editorModule.assignContentControl(contentcontrol.contentControlProperties, contenControlObject); this.modifiedProperties.push(content); this.format = JSON.stringify(contenControlObject); } } } if (this.editorHistory.isUndoing) { this.editorHistory.recordChanges(this); } else { this.editorHistory.undoStack.push(this); } this.owner.editorModule.fireContentChange(); }; BaseHistoryInfo.prototype.revertIgnoreOnce = function () { if (this.owner.spellChecker) { var startPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.selectionStart); this.documentHelper.selection.selectPosition(startPosition, startPosition); var currentContextInfo = this.owner.spellChecker.findCurretText(); if (currentContextInfo && currentContextInfo.element instanceof ErrorTextElementBox) { this.owner.spellChecker.handleIgnoreOnceInternal(currentContextInfo.element, this.editorHistory.isUndoing); } else { var startInlineObj = startPosition.currentWidget.getInline(startPosition.offset, 0, false, true); if (startInlineObj && startInlineObj.element instanceof TextElementBox) { var exactText = this.owner.spellChecker.manageSpecialCharacters(startInlineObj.element.text, undefined, true); var textIndex = startInlineObj.element.ignoreOnceItems.indexOf(exactText); if (this.editorHistory.isUndoing) { if (textIndex !== -1) { startInlineObj.element.ignoreOnceItems.splice(textIndex, 1); } } else { if (textIndex === -1) { startInlineObj.element.ignoreOnceItems.push(exactText); } } } } this.documentHelper.owner.editorModule.reLayout(this.documentHelper.selection); } if (this.editorHistory.isUndoing) { this.editorHistory.recordChanges(this); } else { this.editorHistory.undoStack.push(this); } }; /* 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 === 'UpdateContentControl') { this.revertContentControlProperties(); return; } if (this.action === 'IgnoreOnce') { this.revertIgnoreOnce(); return; } if (this.editorHistory && this.editorHistory.currentHistoryInfo && (this.editorHistory.currentHistoryInfo.action === 'Accept All' || this.editorHistory.currentHistoryInfo.action === 'Reject All')) { this.owner.selectionModule.isModifyingSelectionInternally = true; } if (this.action === 'ListFormat' && !isNullOrUndefined(this.listInfo) && this.listInfo.listNumberFormat !== '' && this.listInfo.listId !== -1) { var abstractList = this.documentHelper.getListById(this.listInfo.listId).abstractList.levels[this.listInfo.listLevelNumber]; var currentListLevelPattern = abstractList.listLevelPattern; var currentNUmberFormat = abstractList.numberFormat; abstractList.listLevelPattern = this.listInfo.listLevelPattern; abstractList.numberFormat = this.listInfo.listNumberFormat; this.listInfo.listLevelPattern = currentListLevelPattern; this.listInfo.listNumberFormat = currentNUmberFormat; if (!isNullOrUndefined(this.listInfo.listCharacterFormat) && abstractList.characterFormat.hasValue('fontFamily')) { var currentListCharacterFormat = abstractList.characterFormat.fontFamily; abstractList.characterFormat.fontFamily = this.listInfo.listCharacterFormat; abstractList.characterFormat.fontFamilyAscii = this.listInfo.listCharacterFormat; abstractList.characterFormat.fontFamilyBidi = this.listInfo.listCharacterFormat; abstractList.characterFormat.fontFamilyFarEast = this.listInfo.listCharacterFormat; abstractList.characterFormat.fontFamilyNonFarEast = this.listInfo.listCharacterFormat; this.listInfo.listCharacterFormat = currentListCharacterFormat; } } this.owner.editorModule.isSkipGrouping = true; 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 && this.owner.enableCollaborativeEditing) { 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); 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]); } var id = deletedNodes[deletedNodes.length - 1]; if (this.removedNodes.indexOf(id) === -1) { this.removedNodes.push(id); } deletedNodes = []; } var caseActions = ['Uppercase', 'Lowercase', 'CapitalizeEachWord', 'SentenceCase', 'ToggleCase']; if (caseActions.indexOf(this.action) !== -1) { 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; if (this.endRevisionLogicalIndex && deletedNodes.length > 0) { var currentPosition = sel.getTextPosBasedOnLogicalIndex(this.endRevisionLogicalIndex); if ((this.editorHistory.isUndoing && !this.editorHistory.currentBaseHistoryInfo.isRevisionEndInAnotherCell) || (this.editorHistory.isRedoing && insertTextPosition.isAtSamePosition(endTextPosition))) { sel.selectPosition(insertTextPosition, currentPosition); this.owner.editor.isSelectionBasedonEndRevision = true; } 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 && !insertTextPosition.isAtSamePosition(endTextPosition))) { this.owner.editor.isDeleteTrackedContent = true; this.owner.editorModule.deleteSelectedContents(sel, true); this.owner.editor.isDeleteTrackedContent = false; this.owner.editor.isSelectionBasedonEndRevision = false; isRemoveContent = true; } } if (!insertTextPosition.isAtSamePosition(endTextPosition) && !isRemoveContent) { isRemoveContent = this.action === 'BackSpace' || this.action === 'Delete' || this.action === 'ClearCells' || this.action === 'DeleteCells' || this.action === 'PasteOverwrite' || this.action === "PasteRow" || this.action === 'PasteNested'; 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 && this.action !== 'ClearRevisions') { if (this.editorHistory.isRedoing && this.action !== 'Accept Change' && 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.documentHelper.layout.layoutWholeDocument(); } } else { isRemoveContent = false; if (!insertTextPosition.isAtSamePosition(endTextPosition)) { isRemoveContent = this.action === 'BackSpace' || this.action === 'Delete' || this.action === 'ClearCells' || this.action === 'DeleteCells'; } } if (this.action === 'Paste' && this.pastedComments.length > 0) { if (this.editorHistory.isUndoing) { for (var i = 0; i < this.pastedComments.length; i++) { var comment = this.pastedComments[i]; this.owner.editorModule.deleteCommentWidget(comment); } } else if (this.editorHistory.isRedoing) { for (var j = 0; j < this.pastedComments.length; j++) { var comment = this.pastedComments[j]; this.owner.editorModule.addCommentWidget(comment, false, this.owner.showComments, false); if (comment.replyComments.length > 0) { for (var k = 0; k < comment.replyComments.length; k++) { this.owner.commentReviewPane.addReply(comment.replyComments[k], false, false); } } } } } var isRedoAction = (this.editorHistory.isRedoing && !isRemoveContent); isRemoveContent = this.endRevisionLogicalIndex ? 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); } //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.editorHistory.isRedoing && this.endRevisionLogicalIndex && (this.action === "BackSpace" || this.action === "Delete"))) { this.owner.selectionModule.selectRange(selectionStartTextPosition, selectionEndTextPosition); } else if (this.editorHistory.isRedoing && this.endRevisionLogicalIndex && this.action === "BackSpace" && selectionStartTextPosition && selectionEndTextPosition && selectionStartTextPosition.isAtSamePosition(selectionEndTextPosition)) { this.owner.selectionModule.sel