UNPKG

@syncfusion/ej2-documenteditor

Version:

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

1,115 lines (1,114 loc) 124 kB
import { Widget, BodyWidget, TableRowWidget, TableWidget, LineWidget, ElementBox, TextElementBox, ListTextElementBox, ImageElementBox, ParagraphWidget, TableCellWidget, FieldElementBox, BlockContainer, BookmarkElementBox, CommentCharacterElementBox, ContentControl } from '../index'; import { HelperMethods } from '../index'; import { Point } from '../index'; import { isNullOrUndefined } from '@syncfusion/ej2-base'; import { EditRangeEndElementBox } from '../viewer/page'; /* eslint-disable */ /** * @private */ var TextPosition = /** @class */ (function () { function TextPosition(owner) { /** * @private */ this.location = new Point(0, 0); /** * @private */ this.isUpdateLocation = true; this.owner = owner; this.documentHelper = this.owner.documentHelper; } Object.defineProperty(TextPosition.prototype, "paragraph", { /** * @private */ get: function () { return this.currentWidget.paragraph; }, enumerable: true, configurable: true }); Object.defineProperty(TextPosition.prototype, "isAtParagraphStart", { /** * @private */ get: function () { return this.currentWidget.paragraph && this.currentWidget === this.currentWidget.paragraph.firstChild && this.offset === this.owner.selectionModule.getStartOffset(this.paragraph); }, enumerable: true, configurable: true }); Object.defineProperty(TextPosition.prototype, "isAtParagraphEnd", { /** * @private */ get: function () { return this.owner.selectionModule.isParagraphLastLine(this.currentWidget) && this.offset === this.owner.selectionModule.getLineLength(this.currentWidget); }, enumerable: true, configurable: true }); Object.defineProperty(TextPosition.prototype, "isCurrentParaBidi", { /** * @private */ get: function () { if (!isNullOrUndefined(this.currentWidget.paragraph)) { return this.currentWidget.paragraph.paragraphFormat.bidi; } return false; }, enumerable: true, configurable: true }); Object.defineProperty(TextPosition.prototype, "selection", { /** * @private */ get: function () { return this.owner.selectionModule; }, enumerable: true, configurable: true }); Object.defineProperty(TextPosition.prototype, "hierarchicalPosition", { /** * Gets the hierarchical position of logical text position in the document * * @returns {string} */ get: function () { return this.getHierarchicalIndexInternal(); }, enumerable: true, configurable: true }); Object.defineProperty(TextPosition.prototype, "viewer", { get: function () { return this.owner.viewer; }, enumerable: true, configurable: true }); /** * Return clone of current text position * * @private */ TextPosition.prototype.clone = function () { var textPosition = new TextPosition(this.owner); textPosition.currentWidget = this.currentWidget; textPosition.offset = this.offset; textPosition.location = this.location; return textPosition; }; /** * @private */ TextPosition.prototype.containsRtlText = function (widget) { for (var i = 0; i < widget.children.length; i++) { if (widget.children[i].isRightToLeft) { return true; } } return false; }; /** * Set text position for paragraph and inline * * @private */ TextPosition.prototype.setPositionForSelection = function (line, element, index, physicalLocation) { //Set the start end position var isParagraphEnd = false; if (isNullOrUndefined(element)) { this.currentWidget = line; } else { this.currentWidget = element.line; if (element.nextNode instanceof FieldElementBox && index > element.length) { isParagraphEnd = this.selection.isLastRenderedInline(element, element.length); } } this.location = physicalLocation; if (isParagraphEnd) { this.offset = this.selection.getParagraphLength(this.currentWidget.paragraph) + 1; } else { this.offset = this.currentWidget.getOffset(element, index); } }; /** * Set text position * * @private */ TextPosition.prototype.setPositionFromLine = function (line, offset, location) { this.currentWidget = line; this.offset = offset; if (location instanceof Point) { this.location.copy(location); } }; /** * Set text position * * @private */ TextPosition.prototype.setPosition = function (line, positionAtStart) { this.currentWidget = line; this.offset = positionAtStart ? this.selection.getStartOffset(line.paragraph) : line.paragraph.lastChild.getEndOffset() + 1; this.updatePhysicalPosition(true); }; /** * Set position for text position * * @private */ TextPosition.prototype.setPositionInternal = function (textPosition) { this.currentWidget = textPosition.currentWidget; this.offset = textPosition.offset; this.location = textPosition.location; }; /** * Set position for current index * * @private */ TextPosition.prototype.setPositionForCurrentIndex = function (hierarchicalIndex) { var index = { index: hierarchicalIndex }; var paragraph = this.getParagraphWidget(index); //ref hierarchicalIndex this.offset = parseFloat(index.index); this.setPositionParagraph(paragraph, this.offset); }; /** * Get Page * */ TextPosition.prototype.getPage = function (position) { var page; var index = position.index.indexOf(';'); var newValue = '0'; if (index >= 0) { newValue = position.index.substring(0, index); position.index = position.index.substring(index).replace(';', ''); } index = parseInt(newValue, 10); page = this.documentHelper.pages[index]; return page; }; /** * @private */ TextPosition.prototype.getParagraphWidget = function (position) { if (isNullOrUndefined(position.index)) { return undefined; } var page = this.getPage(position); var child = this.getLineWidget(undefined, position, page); return child; }; /** * @private */ TextPosition.prototype.getLineWidget = function (widget, position, page) { if (isNullOrUndefined(position.index)) { return undefined; } var index = position.index.indexOf(';'); var value = '0'; if (index >= 0) { value = position.index.substring(0, index); position.index = position.index.substring(index).replace(';', ''); } if (value === 'H' || value === 'F') { if (value === 'H') { widget = page.headerWidget; } else { widget = page.footerWidget; } } else if (value === 'FN' || value === 'EN') { var index1 = position.index.indexOf(';'); var value1 = position.index.substring(0, index1); position.index = position.index.substring(index1).replace(';', ''); if (value === 'FN') { widget = page.footnoteWidget.bodyWidgets[value1]; } else { widget = page.endnoteWidget.bodyWidgets[value1]; } } else if (!isNullOrUndefined(page)) { if (parseInt(value, 10) < page.bodyWidgets.length) { widget = page.bodyWidgets[parseInt(value, 10)]; } else { widget = page.bodyWidgets[0]; } } index = parseInt(value, 10); if (widget instanceof BlockContainer) { index = position.index.indexOf(';'); value = '0'; value = position.index.substring(0, index); position.index = position.index.substring(index).replace(';', ''); index = parseInt(value, 10); } if (widget instanceof TableRowWidget && index >= widget.childWidgets.length) { position.index = '0;0'; index = widget.childWidgets.length - 1; } if (index >= 0 && index < widget.childWidgets.length) { var child = widget.childWidgets[index]; if (child instanceof LineWidget) { if (position.index.indexOf(';') > 0) { position.index = '0'; } return child; } if (child instanceof Widget) { if (position.index.indexOf(';') > 0) { return this.getLineWidget(child, position); } else { //If table is shifted to previous text position then return the first paragraph within table. if (child instanceof TableWidget) { return this.getLineWidget(this.documentHelper.getFirstParagraphInFirstCell(child), position); } else if (child instanceof TableRowWidget && position.index.indexOf(';') === -1) { return this.documentHelper.getFirstParagraphInFirstCell(child.ownerTable).childWidgets[0]; } return undefined; } } } else if (widget.nextRenderedWidget instanceof Widget) { position.index = '0'; if (widget.nextRenderedWidget instanceof TableWidget) { return this.documentHelper.getFirstParagraphInFirstCell(widget.nextRenderedWidget).firstChild; } return this.getLineWidget(widget.nextRenderedWidget, position); } return undefined; }; /** * Update physical location of paragraph * * @private */ TextPosition.prototype.updatePhysicalPosition = function (moveNextLine) { if (this.currentWidget && this.owner.isLayoutEnabled && this.isUpdateLocation) { this.location = this.selection.getPhysicalPositionInternal(this.currentWidget, this.offset, moveNextLine); } }; /** * Return true if text position are in same paragraph and offset * * @private */ TextPosition.prototype.isAtSamePosition = function (textPosition) { return this.currentWidget === textPosition.currentWidget && this.offset === textPosition.offset; }; /** * Return true if text position is in same paragraph index * @private */ TextPosition.prototype.isInSameParagraphIndex = function (textPosition) { if (isNullOrUndefined(textPosition)) { throw new Error('textPosition is undefined.'); } return this.paragraph.index === textPosition.paragraph.index; }; /** * Return true if text position is in same paragraph * * @private */ TextPosition.prototype.isInSameParagraph = function (textPosition) { if (isNullOrUndefined(textPosition)) { throw new Error('textPosition is undefined.'); } return this.paragraph === textPosition.paragraph; }; /** * Return true if start and end is in same list * * @private */ TextPosition.prototype.isInSameListParagraph = function (textPosition) { if (isNullOrUndefined(textPosition)) { throw new Error('textPosition is undefined.'); } return this.paragraph.paragraphFormat.listFormat.listId === textPosition.paragraph.paragraphFormat.listFormat.listId; }; /** * Return true is current text position exist before given text position * * @private */ TextPosition.prototype.isExistBefore = function (textPosition) { if (isNullOrUndefined(textPosition)) { throw new Error('textPosition is undefined.'); } if (this.currentWidget === textPosition.currentWidget) { return this.offset < textPosition.offset; } var currentParagraph = this.currentWidget.paragraph; var paragraph = textPosition.currentWidget.paragraph; if (currentParagraph === paragraph) { return currentParagraph.childWidgets.indexOf(this.currentWidget) < paragraph.childWidgets.indexOf(textPosition.currentWidget); } if (currentParagraph.containerWidget === paragraph.containerWidget) { if (currentParagraph.isInsideTable) { return currentParagraph.associatedCell.childWidgets.indexOf(currentParagraph) < paragraph.associatedCell.childWidgets.indexOf(paragraph); //handle after header footer implementation // } else if ((this.currentParagraph).owner instanceof WHeaderFooter) { // return ((this.currentParagraph).owner as WHeaderFooter).blocks.indexOf((this.currentParagraph)) < // ((textPosition.currentParagraph).owner as WHeaderFooter).blocks.indexOf((textPosition.currentParagraph)); } else { return (currentParagraph.containerWidget.childWidgets.indexOf(currentParagraph)) < (paragraph.containerWidget.childWidgets.indexOf(paragraph)); } } return this.owner.selectionModule.isExistBefore(currentParagraph, paragraph); }; /** * Return true is current text position exist after given text position * * @private */ TextPosition.prototype.isExistAfter = function (textPosition) { if (isNullOrUndefined(textPosition)) { throw new Error('textPosition is undefined.'); } if (this.currentWidget === textPosition.currentWidget) { return this.offset > textPosition.offset; } if (this.currentWidget.paragraph === textPosition.currentWidget.paragraph) { return this.currentWidget.paragraph.childWidgets.indexOf(this.currentWidget) > textPosition.currentWidget.paragraph.childWidgets.indexOf(textPosition.currentWidget); } var startParagraph = this.currentWidget.paragraph; var endParagraph = textPosition.currentWidget.paragraph; if (!isNullOrUndefined(startParagraph) && !isNullOrUndefined(endParagraph)) { if (startParagraph.containerWidget instanceof BodyWidget && endParagraph.containerWidget instanceof BodyWidget && startParagraph.containerWidget === endParagraph.containerWidget) { if (startParagraph.isInsideTable && endParagraph.isInsideTable) { return startParagraph.associatedCell.childWidgets.indexOf(startParagraph) > endParagraph.associatedCell.childWidgets.indexOf(endParagraph); // } else if ((this.currentParagraph).owner instanceof WHeaderFooter) { // return ((this.currentParagraph).owner as WHeaderFooter).blocks.indexOf((this.currentParagraph)) > // ((textPosition.currentParagraph).owner as WHeaderFooter).blocks.indexOf((textPosition.currentParagraph)); } else { return (startParagraph.containerWidget.childWidgets.indexOf(startParagraph) > (endParagraph.containerWidget.childWidgets.indexOf(endParagraph))); } } return this.owner.selectionModule.isExistAfter(startParagraph, endParagraph); } return false; }; /** * Return hierarchical index of current text position * * @private */ TextPosition.prototype.getHierarchicalIndexInternal = function () { return this.getHierarchicalIndex(this.currentWidget, this.offset.toString()); }; /** * @private */ TextPosition.prototype.getHierarchicalIndex = function (line, hierarchicalIndex) { var node = line; if (node) { return node.getHierarchicalIndex(hierarchicalIndex); } return hierarchicalIndex; }; /** * @private */ TextPosition.prototype.setPositionParagraph = function (line, offsetInLine, isRetrieveBookmark) { this.currentWidget = line; this.offset = offsetInLine; if (!isRetrieveBookmark) { this.updatePhysicalPosition(true); } }; /** * @private */ TextPosition.prototype.setPositionForLineWidget = function (lineWidget, offset) { var lineLength = this.selection.getLineLength(lineWidget); var lineIndex = lineWidget.paragraph.childWidgets.indexOf(lineWidget); if (lineWidget.isLastLine()) { if (!isNullOrUndefined(lineWidget.paragraph.bodyWidget.footNoteReference)) { lineLength = lineLength + lineWidget.paragraph.bodyWidget.footNoteReference.text.length; } else { lineLength = lineLength + 1; } } if (offset > lineLength) { var nextLineWidget = void 0; if (lineIndex >= lineWidget.paragraph.childWidgets.length - 1) { var nextBlock = this.selection.getNextRenderedBlock(lineWidget.paragraph); if (nextBlock && nextBlock.index === lineWidget.paragraph.index) { nextLineWidget = nextBlock.firstChild; } } else { nextLineWidget = lineWidget.paragraph.childWidgets[lineIndex + 1]; } this.setPositionForLineWidget(nextLineWidget, offset - lineLength); return; } else if (offset < 0) { var prevLine = lineWidget.paragraph.childWidgets[lineIndex - 1]; var currentOffSet = this.selection.getLineLength(prevLine) + offset; this.setPositionForLineWidget(prevLine, currentOffSet); return; } else { this.currentWidget = lineWidget; this.offset = offset; } this.updatePhysicalPosition(true); }; /** * move to next text position * * @private */ TextPosition.prototype.moveNextPosition = function (isNavigate) { if (isNullOrUndefined(isNavigate)) { isNavigate = true; } var inline = this.selection.getNextStartInline(this.currentWidget, this.offset); if (inline instanceof FieldElementBox && inline.fieldType === 0 && !isNullOrUndefined(inline.fieldEnd)) { if (isNavigate) { this.moveNextPositionInternal(inline); this.moveNextPosition(); return; } else { var line = inline.fieldEnd.line; var fieldEnd = inline.fieldEnd; var fieldEndOffset = line.getOffset(fieldEnd, 1); var fieldEndIndex = this.getHierarchicalIndex(line, fieldEndOffset.toString()); if (TextPosition.isForwardSelection(this.selection.end.getHierarchicalIndexInternal(), fieldEndIndex)) { //If field end is after selection end, extend selection end to field end. this.selection.end.moveToInline(inline.fieldEnd, 1); return; } this.moveToInline(inline.fieldEnd, 1); } } var nextOffset = this.selection.getNextValidOffset(this.currentWidget, this.offset); var lineIndex = this.paragraph.childWidgets.indexOf(this.currentWidget); var index = 0; if (nextOffset > this.offset) { this.offset = nextOffset; var info = this.currentWidget.getInline(this.offset, index); inline = info.element; index = info.index; if (!isNullOrUndefined(inline) && index === inline.length && (inline.nextNode instanceof FieldElementBox || inline.nextNode instanceof BookmarkElementBox)) { var nextValidInline = this.documentHelper.getNextValidElement(inline.nextNode); //Moves to field end mark or Bookmark end. if (nextValidInline instanceof FieldElementBox && nextValidInline.fieldType === 1 || nextValidInline instanceof BookmarkElementBox && nextValidInline.bookmarkType === 1) { inline = nextValidInline; this.currentWidget = inline.line; this.offset = this.currentWidget.getOffset(inline, this.documentHelper.isFormFillProtectedMode ? 0 : 1); } } } else if (lineIndex + 1 < this.paragraph.childWidgets.length) { var nextLineWidget = this.paragraph.childWidgets[lineIndex + 1]; while (nextLineWidget && nextLineWidget.height === 0) { if (isNullOrUndefined(nextLineWidget.nextLine)) { var block = this.selection.getNextParagraphBlock(nextLineWidget.paragraph); if (!isNullOrUndefined(block)) { this.currentWidget = nextLineWidget; this.updateOffsetToNextParagraph(index, false); return; } } nextLineWidget = nextLineWidget.nextLine; } if (nextLineWidget) { this.currentWidget = nextLineWidget; this.offset = this.selection.getStartLineOffset(this.currentWidget); } var inlineObj = this.currentWidget.getInline(this.offset, index); inline = inlineObj.element; index = inlineObj.index; if (inline instanceof FieldElementBox && inline.fieldType === 0) { this.offset++; } } else { this.updateOffsetToNextParagraph(index, false, isNavigate); } //Gets physical position in current page. this.updatePhysicalPosition(true); }; /** * Move text position to previous paragraph inside table * * @private */ TextPosition.prototype.moveToPreviousParagraphInTable = function (selection) { var previousParagraph; var currentPara = this.currentWidget.paragraph; if (currentPara.isInsideTable) { previousParagraph = selection.getPreviousSelectionCell(currentPara.associatedCell); } else { previousParagraph = selection.getPreviousParagraphBlock(currentPara); } if (isNullOrUndefined(previousParagraph)) { return; } this.currentWidget = previousParagraph.childWidgets[previousParagraph.childWidgets.length - 1]; this.offset = this.currentWidget.getEndOffset() + 1; }; TextPosition.prototype.nextValidVisibleBlock = function (visibleBlock, isStart) { var currentValidVisibleBlock = visibleBlock; while (visibleBlock && ((visibleBlock.characterFormat.hidden && visibleBlock.height === 0) || (!visibleBlock.isEmpty() && !visibleBlock.characterFormat.hidden && visibleBlock.height === 0 && visibleBlock.firstChild.children[0].characterFormat.hidden))) { visibleBlock = isStart ? this.selection.getNextParagraphBlock(visibleBlock) : this.selection.getPreviousParagraphBlock(visibleBlock); } if (isNullOrUndefined(visibleBlock)) { return currentValidVisibleBlock; } return visibleBlock; }; TextPosition.prototype.setPositionForValidLine = function (cell, isNext, positionAtStart) { var visibleBlock; if (!isNext) { visibleBlock = this.selection.getLastParagraph(cell); visibleBlock = this.nextValidVisibleBlock(visibleBlock, false); this.setPosition(this.getValidVisibleLine(visibleBlock.childWidgets[visibleBlock.childWidgets.length - 1], isNext), positionAtStart); } else { visibleBlock = this.selection.getFirstParagraph(cell); visibleBlock = this.nextValidVisibleBlock(visibleBlock, true); this.setPosition(this.getValidVisibleLine(visibleBlock.childWidgets[0], isNext), positionAtStart); } }; TextPosition.prototype.updateOffsetToNextParagraph = function (indexInInline, isHighlight, isNavigate) { //Moves to owner and get next paragraph. var inline; var positionAtStart = false; var nextParagraph = undefined; var lineIndex = this.paragraph.childWidgets.indexOf(this.currentWidget); if (!isHighlight) { nextParagraph = this.selection.getNextParagraphBlock(this.paragraph); nextParagraph = this.nextValidVisibleBlock(nextParagraph, true); } else if (lineIndex + 1 < this.paragraph.childWidgets.length) { var nextLineWidget = this.paragraph.childWidgets[lineIndex + 1]; if (nextLineWidget) { this.currentWidget = nextLineWidget; this.offset = 1; } } else { nextParagraph = this.selection.getNextSelectionBlock(this.paragraph); if (!isNullOrUndefined(nextParagraph)) { if (nextParagraph.containerWidget instanceof TableCellWidget) { if (this.selection.start.paragraph.isInsideTable) { var containerCell = this.selection.getContainerCellOf(this.selection.start.paragraph.associatedCell, nextParagraph.associatedCell); positionAtStart = !containerCell.ownerTable.contains(nextParagraph.associatedCell); } else { positionAtStart = true; } } } } if (!isNullOrUndefined(nextParagraph) && nextParagraph.childWidgets.length > 0) { if (!positionAtStart) { this.currentWidget = this.getValidVisibleLine(nextParagraph.firstChild, true); this.offset = isHighlight ? 1 : this.selection.getStartLineOffset(this.currentWidget, isNavigate); } else { this.currentWidget = this.getValidVisibleLine(nextParagraph.lastChild, false); this.offset = this.selection.getLineLength(this.currentWidget) + 1; } } var inlineObj = this.currentWidget.getInline(this.offset, indexInInline); inline = inlineObj.element; indexInInline = inlineObj.index; if (inline instanceof FieldElementBox && inline.fieldType === 0) { this.offset++; } }; TextPosition.prototype.getValidVisibleLine = function (visibleLine, isNext) { var currentVisibleLine = visibleLine; if (isNext) { while (visibleLine && visibleLine.height === 0) { visibleLine = visibleLine.nextLine; } } else { while (visibleLine && visibleLine.height === 0) { visibleLine = visibleLine.previousLine; } } if (visibleLine) { return visibleLine; } return currentVisibleLine; }; TextPosition.prototype.updateOffsetToPrevPosition = function (index, isHighlight) { var inlineInfo; var inline; var lineIndex = this.paragraph.childWidgets.indexOf(this.currentWidget); var prevOffset = this.selection.getPreviousValidOffset(this.currentWidget, this.offset); var isMoveToVisibleBlock = true; if (this.offset > prevOffset) { this.offset = prevOffset; isMoveToVisibleBlock = false; } else if (lineIndex > 0) { var prevLineWidget = this.paragraph.childWidgets[lineIndex - 1]; while (prevLineWidget && prevLineWidget.height === 0) { if (isNullOrUndefined(prevLineWidget.previousLine)) { var block = this.selection.getPreviousParagraphBlock(prevLineWidget.paragraph); if (!isNullOrUndefined(block)) { this.currentWidget = prevLineWidget; isMoveToVisibleBlock = true; break; } } prevLineWidget = prevLineWidget.previousLine; } if (prevLineWidget) { isMoveToVisibleBlock = false; this.currentWidget = prevLineWidget; var endOffset = this.currentWidget.getEndOffset(); this.offset = endOffset > 0 ? endOffset - 1 : endOffset; var length_1 = 0; var visibleElement = this.selection.getElementInfo(this.currentWidget, this.offset).element; while (!isNullOrUndefined(visibleElement) && visibleElement.characterFormat.hidden) { length_1 += visibleElement.length; visibleElement = visibleElement.previousElement; } this.offset -= length_1; } } if (isMoveToVisibleBlock) { //Moves to owner and get previous paragraph. var previousParagraph = undefined; var positionAtStart = false; if (!isHighlight) { previousParagraph = this.selection.getPreviousParagraphBlock(this.paragraph); previousParagraph = this.nextValidVisibleBlock(previousParagraph, false); } else { previousParagraph = this.selection.getPreviousSelectionBlock(this.paragraph); if (!isNullOrUndefined(previousParagraph)) { if (previousParagraph.containerWidget instanceof TableCellWidget) { if (this.selection.start.paragraph.isInsideTable) { var containerCell = this.selection.getContainerCellOf(this.selection.start.paragraph.associatedCell, previousParagraph.associatedCell); positionAtStart = !containerCell.ownerTable.contains(previousParagraph.associatedCell); } else { positionAtStart = true; } } } } if (!isNullOrUndefined(previousParagraph)) { if (!positionAtStart) { this.currentWidget = this.getValidVisibleLine(previousParagraph.lastChild, false); // line end with page break and updating offset before page break. this.offset = (this.currentWidget.isEndsWithPageBreak || this.currentWidget.isEndsWithColumnBreak) ? this.currentWidget.getEndOffset() - 1 : this.currentWidget.getEndOffset(); } else { this.currentWidget = this.getValidVisibleLine(previousParagraph.firstChild, true); this.offset = this.selection.getStartLineOffset(this.currentWidget); } } } index = 0; inlineInfo = this.currentWidget.getInline(this.offset, index); inline = inlineInfo.element; index = inlineInfo.index; if (inline instanceof EditRangeEndElementBox) { for (var i = this.currentWidget.children.length - 1; i >= 0; i--) { inline = this.currentWidget.children[i]; if (inline instanceof EditRangeEndElementBox) { this.offset--; } else { break; } } } if (inline instanceof FieldElementBox && inline.fieldType === 0) { this.offset++; } if (inline instanceof FieldElementBox) { //Checks if field character is part of rendered field, otherwise moves to previous rendered content. var previousInline = this.selection.getPreviousValidElement(inline); if (!isNullOrUndefined(previousInline)) { inline = previousInline; this.currentWidget = inline.line; this.offset = this.currentWidget.getOffset(inline, inline.length); if (inline instanceof FieldElementBox && inline.fieldType === 0) { this.offset--; } } } //Gets physical position in current page. this.updatePhysicalPosition(true); }; /** * Moves the text position to start of the next paragraph. */ TextPosition.prototype.moveToNextParagraphStartInternal = function () { var paragraph = this.currentWidget.paragraph; if (!isNullOrUndefined(this.selection.getNextParagraphBlock(paragraph))) { this.currentWidget = this.selection.getNextParagraphBlock(paragraph).firstChild; this.offset = this.selection.getStartOffset(paragraph); this.updatePhysicalPosition(true); } }; /** * Move to previous position * * @private */ TextPosition.prototype.movePreviousPosition = function () { var index = 0; var inlineInfo = this.currentWidget.getInline(this.offset, index); var inline = inlineInfo.element; index = inlineInfo.index; var lineIndex = this.paragraph.childWidgets.indexOf(this.currentWidget); if (inline instanceof FieldElementBox && inline.fieldType === 1 && !isNullOrUndefined(inline.fieldBegin) || inline instanceof BookmarkElementBox) { this.movePreviousPositionInternal(inline); } this.updateOffsetToPrevPosition(index, false); }; /** * Move to next position * * @private */ TextPosition.prototype.moveNextPositionInternal = function (fieldBegin) { var inline; if (isNullOrUndefined(fieldBegin.fieldSeparator)) { inline = fieldBegin.fieldEnd; } else { inline = fieldBegin.fieldSeparator; this.currentWidget = inline.line; if (this.currentWidget === fieldBegin.fieldEnd.line && !this.selection.hasValidInline(this.paragraph, inline, fieldBegin.fieldEnd)) { inline = fieldBegin.fieldEnd; } } this.currentWidget = inline.line; this.offset = this.currentWidget.getOffset(inline, 1); }; /** * Move text position backward * * @private */ TextPosition.prototype.moveBackward = function () { var indexInInline = 0; var inlineObj = this.currentWidget.getInline(this.offset, indexInInline); var inline = inlineObj.element; indexInInline = inlineObj.index; if (!this.owner.selectionModule.isEmpty && !isNullOrUndefined(inline)) { var nextInline = this.selection.getNextRenderedElementBox(inline, indexInInline); if (nextInline instanceof FieldElementBox && nextInline.fieldType === 0) { var hierarchicalIndex = this.owner.selectionModule.start.getHierarchicalIndexInternal(); var fieldEndOffset = nextInline.fieldEnd.line.getOffset(nextInline.fieldEnd, 1); var fieldEndIndex = this.getHierarchicalIndex(nextInline.fieldEnd.line, fieldEndOffset.toString()); if (!TextPosition.isForwardSelection(fieldEndIndex, hierarchicalIndex)) { //If field end is after selection start, move selection start to field end. this.owner.selectionModule.start.setPositionParagraph(nextInline.fieldEnd.line, fieldEndOffset); return; } } } if (inline instanceof FieldElementBox && inline.fieldType === 1 && !isNullOrUndefined(inline.fieldBegin)) { var hierarchicalIndex = this.owner.selectionModule.start.getHierarchicalIndexInternal(); var fieldEndOffset = inline.line.getOffset(inline, 1); var fieldEndIndex = this.getHierarchicalIndex(inline.line, fieldEndOffset.toString()); if (!TextPosition.isForwardSelection(hierarchicalIndex, fieldEndIndex)) { //If field end is after selection start, extend selection end to field begin. var fieldBeginOffset = inline.fieldBegin.line.getOffset(inline.fieldBegin, 0); this.currentWidget = inline.fieldBegin.line; this.offset = fieldBeginOffset; //Updates physical position in current page. this.updatePhysicalPosition(true); return; } this.movePreviousPositionInternal(inline); } this.updateOffsetToPrevPosition(indexInInline, true); }; /** * Move text position forward * * @private */ TextPosition.prototype.moveForward = function () { var indexInInline = 0; var inlineObj = this.currentWidget.getInline(this.offset, indexInInline); var inline = inlineObj.element; indexInInline = inlineObj.index; if (!isNullOrUndefined(inline)) { if (!this.owner.selectionModule.isEmpty && indexInInline === inline.length && inline instanceof FieldElementBox && inline.fieldType === 1) { var hierarchicalIndex = this.owner.selectionModule.start.getHierarchicalIndexInternal(); var fieldBeginOffset = inline.fieldBegin.line.getOffset(inline.fieldBegin, 0); var fieldBeginIndex = this.getHierarchicalIndex(inline.fieldBegin.line, fieldBeginOffset.toString()); if (!TextPosition.isForwardSelection(hierarchicalIndex, fieldBeginIndex)) { //If field begin is before selection start, move selection start to field begin. this.owner.selectionModule.start.setPositionParagraph(inline.fieldBegin.line, fieldBeginOffset); return; } } inline = this.selection.getNextRenderedElementBox(inline, indexInInline); } if (inline instanceof FieldElementBox && !isNullOrUndefined(inline.fieldEnd)) { var selectionStartParagraph = this.owner.selectionModule.start.paragraph; var selectionStartIndex = 0; var selectionStartInlineObj = selectionStartParagraph.getInline(this.owner.selectionModule.start.offset, selectionStartIndex); var selectionStartInline = selectionStartInlineObj.element; selectionStartIndex = selectionStartInlineObj.index; var nextRenderInline = this.selection.getNextRenderedElementBox(selectionStartInline, selectionStartIndex); if (nextRenderInline === inline) { this.moveNextPositionInternal(inline); } else { //If selection start is before field begin, extend selection end to field end. inline = inline.fieldEnd; this.currentWidget = inline.line; this.offset = this.currentWidget.getOffset(inline, 1); //Updates physical position in current page. this.updatePhysicalPosition(true); return; } } else if ((inline instanceof FieldElementBox) && (inline.fieldType === 0 || inline.fieldType === 1)) { this.currentWidget = inline.line; this.offset = this.currentWidget.getOffset(inline, 1); } indexInInline = 0; var nextOffset = this.selection.getNextValidOffset(this.currentWidget, this.offset); var length = this.selection.getLineLength(this.currentWidget); var isParagraphEnd = this.selection.isParagraphLastLine(this.currentWidget); if (this.offset < nextOffset) { this.offset = nextOffset; var inlineObj_1 = this.currentWidget.getInline(this.offset, indexInInline); inline = inlineObj_1.element; indexInInline = inlineObj_1.index; if (!isNullOrUndefined(inline) && indexInInline === inline.length && inline.nextNode instanceof FieldElementBox) { var nextValidInline = this.documentHelper.getNextValidElement(inline.nextNode); //Moves to field end mark. if (nextValidInline instanceof FieldElementBox && nextValidInline.fieldType === 1) { inline = nextValidInline; this.offset = this.currentWidget.getOffset(inline, 1); } } } else if (this.offset === nextOffset && inline instanceof FieldElementBox && inline.fieldType === 1 && inline.previousNode instanceof ImageElementBox) { this.offset = nextOffset; } else if (this.offset === nextOffset && this.offset < length + 1 && isParagraphEnd) { this.offset = length + 1; } else { this.updateOffsetToNextParagraph(indexInInline, true); } //Gets physical position in current page. this.updatePhysicalPosition(true); }; /** * Move to given inline * * @private */ TextPosition.prototype.moveToInline = function (inline, index) { this.currentWidget = inline.line; this.offset = this.currentWidget.getOffset(inline, index); //Updates physical position in current page. this.updatePhysicalPosition(true); }; /** * Return true is start element exist before end element * * @private */ TextPosition.isForwardSelection = function (start, end) { if (start === end) { return true; } start = start.replace(/S;/g, ''); end = end.replace(/S;/g, ''); start = start.replace(/C;/g, ''); end = end.replace(/C;/g, ''); start = start.replace(/H;/g, ''); end = end.replace(/H;/g, ''); start = start.replace(/F;/g, ''); end = end.replace(/F;/g, ''); start = start.replace(/FN;/g, ''); end = end.replace(/FN;/g, ''); start = start.replace(/EN;/g, ''); end = end.replace(/EN;/g, ''); var selectionStart = start.split(';'); var selectionEnd = end.split(';'); var length = selectionStart.length; if (length > selectionEnd.length) { length = selectionEnd.length - 1; } for (var i = 0; i < length; i++) { var startOffset = parseFloat(selectionStart[i]); var endOffset = parseFloat(selectionEnd[i]); if (startOffset !== endOffset) { return startOffset < endOffset; } } return false; }; /** * Move to previous position offset * * @param fieldEnd * @private */ TextPosition.prototype.movePreviousPositionInternal = function (fieldEnd) { var inline; if (fieldEnd instanceof FieldElementBox && isNullOrUndefined(fieldEnd.fieldSeparator)) { inline = this.selection.getPreviousValidElement(fieldEnd.fieldBegin); } else { inline = this.selection.getPreviousValidElement(fieldEnd); } this.currentWidget = inline.line; var index = inline instanceof FieldElementBox || inline instanceof BookmarkElementBox ? 0 : inline.length; this.offset = this.currentWidget.getOffset(inline, index); }; /** * Moves the text position to start of the word. * * @param type * @private */ TextPosition.prototype.moveToWordStartInternal = function (type) { var endOffset = this.currentWidget.getEndOffset(); var currentPara = this.currentWidget.paragraph; var selection = this.selection; if (type === 2 && (this.offset === endOffset || this.offset === endOffset + 1)) { return; } if (this.offset === endOffset + 1) { this.offset = endOffset; } else if (this.offset === selection.getStartOffset(currentPara) && this.currentWidget === currentPara.childWidgets[0]) { var previousParagraph = selection.getPreviousParagraphBlock(currentPara); if (isNullOrUndefined(previousParagraph)) { return; } this.currentWidget = previousParagraph.childWidgets[previousParagraph.childWidgets.length - 1]; this.offset = this.currentWidget.getEndOffset(); } else { if (this.offset === selection.getStartLineOffset(this.currentWidget)) { var lineIndex = currentPara.childWidgets.indexOf(this.currentWidget); if (lineIndex - 1 >= 0) { this.currentWidget = currentPara.childWidgets[lineIndex - 1]; this.offset = this.currentWidget.getEndOffset(); } } var isStarted = false; var endSelection = false; var indexInInline = 0; var inlineObj = this.currentWidget.getInline(this.offset, indexInInline); var inline = inlineObj.element; indexInInline = inlineObj.index; this.getPreviousWordOffset(inline, selection, indexInInline, type, (inline instanceof FieldElementBox && inline.fieldType === 1), isStarted, endSelection, this); } if (type === 1) { this.calculateOffset(); } this.updatePhysicalPosition(true); }; TextPosition.prototype.getNextWordOffset = function (inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace) { if (inline instanceof TextElementBox) { this.getNextWordOffsetSpan(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } else if (inline instanceof ImageElementBox) { this.getNextWordOffsetImage(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } else if (inline instanceof FieldElementBox && inline.fieldType === 0) { this.getNextWordOffsetFieldBegin(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } else if ((inline instanceof FieldElementBox && inline.fieldType === 2) || (inline instanceof BookmarkElementBox && inline.bookmarkType === 0)) { this.getNextWordOffsetFieldSeparator(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } else if ((inline instanceof FieldElementBox && inline.fieldType === 1) || (inline instanceof BookmarkElementBox && inline.bookmarkType === 1)) { this.getNextWordOffsetFieldEnd(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } else if (inline instanceof CommentCharacterElementBox) { this.getNextWordOffsetComment(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } else if (inline instanceof ContentControl) { this.getNextWordOffsetContentControl(inline, indexInInline, type, isInField, endSelection, endPosition, excludeSpace); } }; TextPosition.prototype.getNextWordOffsetFieldBegin = function (fieldBegin, indexInInline, type, isInField, endSelection, endPosition, excludeSpace) { var startOffset = fieldBegin.line.getOffset(fieldBegin, 0); var endOffset = startOffset + fieldBegin.length; if (isNullOrUndefined(fieldBegin.fieldSeparator)) { this.getNextWordOffsetFieldEnd(fieldBegin.fieldEnd, 0, type, isInField, endSelection, endPosition, excludeSpace); } else if (type === 0) { this.getNextWordOffsetFieldSeparator(fieldBegin.fieldSeparator, 0, type, isInField, endSelection, endPosition, excludeSpace); } else if (!isNullOrUndefined(fieldBegin.fieldEnd)) { var inline = fieldBegin.fieldSeparator; if (inline.line.paragraph === fieldBegin.fieldEnd.line.paragraph && !this.selection.hasValidInline(inline.line.paragraph, inline, fieldBegin.fieldEnd)) { inline = fieldBegin.fieldEnd; } this.getNextWordOffset(inline, 0, type, !(endPosition.paragraph === fieldBegin.line.paragraph && endPosition.offset === startOffset), endSelection, endPosition, excludeSpace); if (endSelection && !isNullOrUndefined(fieldBegin.fieldSeparator) && (endPosition.paragraph === fieldBegin.line.paragraph) && (endPosition.offset === fieldBegin.fieldSeparator.line.getOffset(fieldBegin.fieldSeparator, fieldBegin.fieldSeparator.length))) { endPosition.setPositionParagraph(fieldBegin.line, startOffset); return; } if (!endSelection) { endPosition.setPositionParagraph(fieldBegin.fieldEnd.line, fieldBegin.fieldEnd.line.getOffset(fieldBegin.fieldEnd, fieldBegin.fieldEnd.length)); } } }; TextPosition.prototype.getNextWordOffsetImage = function (image, indexInInline, type, isInField, endSelection, endPosition, excludeSpace) { if (isInField) { endPosition.setPositionParagraph(image.line, image.line.getOffset(image, indexInInline)); endSelection = false; return; } if (indexInInline === 0) { var startOffset = image.line.getOffset(image, 0); endSelection = true; if (endPosition.offset === startOffset) {