Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
private selectEditorPoint(container: Node, offset: number): boolean {
if (!this.contains(container)) {
return false;
}
let range = this.core.document.createRange();
if (container.nodeType == NodeType.Text && offset <= container.nodeValue.length) {
range.setStart(container, offset);
} else if (offset == NodeBoundary.Begin) {
range.setStartBefore(container);
} else {
range.setStartAfter(container);
}
range.collapse(true /* toStart */);
return updateSelection(this.core, range);
}
function insertCursorMarkerToEditorPoint(
editor: Editor,
editorPoint: EditorPoint,
cursorMaker: Element
): void {
if (editor.contains(editorPoint.containerNode)) {
let containerNode = editorPoint.containerNode;
let offset = editorPoint.offset;
let parentNode = containerNode.parentNode;
if (editorPoint.offset == NodeBoundary.Begin) {
// For boundary_begin, insert the marker before the node
parentNode.insertBefore(cursorMaker, containerNode);
} else if (
containerNode.nodeType == NodeType.Element ||
(containerNode.nodeType == NodeType.Text &&
editorPoint.offset == containerNode.nodeValue.length)
) {
// otherwise, insert after
parentNode.insertBefore(cursorMaker, containerNode.nextSibling);
} else {
// This is for insertion in-between a text node
let insertionRange = editor.getDocument().createRange();
insertionRange.setStart(containerNode, offset);
insertionRange.collapse(true /* toStart */);
insertionRange.insertNode(cursorMaker);
}
function selectEditorPoint(core: EditorCore, container: Node, offset: number): boolean {
if (!container || !contains(core.contentDiv, container)) {
return false;
}
let range = core.document.createRange();
if (container.nodeType == NodeType.Text && offset <= container.nodeValue.length) {
range.setStart(container, offset);
} else if (offset == NodeBoundary.Begin) {
range.setStartBefore(container);
} else {
range.setStartAfter(container);
}
range.collapse(true /* toStart */);
return updateSelection(core, range);
}
) {
let editorSelection = new EditorSelection(
this.core.contentDiv,
selectionRange,
this.core.inlineElementFactory
);
let blockElement = editorSelection.startBlockElement;
if (!blockElement) {
// Only reason we don't get the selection block is that we have an empty content div
// which can happen when users removes everything (i.e. select all and DEL, or backspace from very end to begin)
// The fix is to add a DIV wrapping, apply default format and move cursor over
let nodes = fromHtml('<div><br></div>', this.core.document);
let element = this.core.contentDiv.appendChild(nodes[0]) as HTMLElement;
applyFormat(element, this.core.defaultFormat);
// element points to a wrapping node we added "<div><br></div>". We should move the selection left to <br>
this.selectEditorPoint(element.firstChild, NodeBoundary.Begin);
} else if (
blockElement.getStartNode().parentNode == blockElement.getEndNode().parentNode
) {
// Only fix the balanced start-end block where start and end node is under same parent
// The focus node could be pointing to the content div, normalize it to have it point to a child first
let focusOffset = selectionRange.startOffset;
let editorPoint = normalizeEditorPoint(focusNode, focusOffset);
let element = wrapAll(blockElement.getContentNodes()) as HTMLElement;
if (getTagOfNode(blockElement.getStartNode()) == 'BR') {
// if the block is just BR, apply default format
// Otherwise, leave it as it is as we don't want to change the style for existing data
applyFormat(element, this.core.defaultFormat);
}
// Last restore the selection using the normalized editor point
this.selectEditorPoint(editorPoint.containerNode, editorPoint.offset);
}
export function getInlineElementBeforePoint(
rootNode: Node,
position: EditorPoint,
inlineElementFactory: InlineElementFactory
) {
let inlineElement: InlineElement;
let containerNode = position.containerNode;
let offset = position.offset;
if (containerNode) {
let isPartial = false;
if (offset == NodeBoundary.Begin) {
// The point is at the begin of container element
containerNode = getPreviousLeafSibling(rootNode, containerNode);
} else if (
containerNode.nodeType == NodeType.Text &&
offset < containerNode.nodeValue.length
) {
// Run across a text node
isPartial = true;
}
if (containerNode && shouldSkipNode(containerNode)) {
containerNode = getPreviousLeafSibling(rootNode, containerNode);
}
inlineElement = containerNode
? getInlineElementAtNode(rootNode, containerNode, inlineElementFactory)
export default function normalizeEditorPoint(container: Node, offset: number): EditorPoint {
let adjustedContainer = container;
let adjustedOffset = offset;
if (adjustedContainer.nodeType == NodeType.Element && adjustedContainer.hasChildNodes()) {
if (offset < adjustedContainer.childNodes.length) {
// offset points to a child node that exists
adjustedContainer = container.childNodes[offset];
adjustedOffset = NodeBoundary.Begin;
} else {
// offset points to end of container
adjustedContainer = container.childNodes[offset - 1];
adjustedOffset =
adjustedContainer.nodeType == NodeType.Text
? adjustedContainer.nodeValue.length
: NodeBoundary.End;
}
}
// Even we have an adjusted container, it does not mean it is a leaf
// Still need to do the check, and adjust a bit further to last or first child
// depending on what offset says
if (adjustedContainer.hasChildNodes()) {
if (adjustedOffset == 0) {
while (adjustedContainer.firstChild) {
// This is often the case the cursor runs in middle of two nodes.
// i.e. <p>{cursor}<br></p>, or <p><img>{cursor}text</p>.
// range.getBoundingClientRect mostly return a client rect of all 0
// Skip this if we're in middle of a text node
let editorPoint = normalizeEditorPoint(range.startContainer, range.startOffset);
if (
editorPoint.containerNode.nodeType != NodeType.Text ||
editorPoint.containerNode.nodeValue.length == editorPoint.offset
) {
let nearbyRange = core.document.createRange();
nearbyRange.selectNode(editorPoint.containerNode);
rect = getRectFromClientRect(nearbyRange.getBoundingClientRect());
if (rect) {
// Fix the position to boundary of the nearby range
rect.left = rect.right =
editorPoint.offset == NodeBoundary.Begin ? rect.left : rect.right;
}
}
}
// 4) fallback range.getClientRects()
if (!rect) {
// This is often the case Safari when cursor runs in middle of text node
// range.getBoundingClientRect() returns a all 0 client rect.
// range.getClientRects() returns a good client rect
let clientRects = range.getClientRects();
if (clientRects && clientRects.length == 1) {
rect = getRectFromClientRect(clientRects[0]);
}
}
// 5) lastly fallback range.startContainer.getBoundingClientRect()