Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
// 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
formatNode = fromHtml(
Browser.isEdge ? '<div><span><br></span></div>' : '<div><br></div>',
this.editor.getDocument()
)[0] as HTMLElement;
this.editor.insertNode(formatNode, {
position: ContentPosition.End,
updateCursor: false,
replaceSelection: false,
insertOnNewLine: false,
});
// element points to a wrapping node we added "<div><br></div>". We should move the selection left to <br>
result = new Position(formatNode.firstChild, PositionType.Begin);
}
if (formatNode) {
applyFormat(formatNode, this.editor.getDefaultFormat(), this.editor.isDarkMode());
}
return result;
}
? editor.collapseNodes(
startBlock.getStartNode(),
endBlock.getEndNode(),
true /*canSplitParent*/
)
: [];
if (nodes.length == 0) {
// Selection is collapsed and blockElement is null, we need to create an empty div.
// In case of IE and Edge, we insert ZWS to put cursor in the div, otherwise insert BR node.
nodes = fromHtml(
`<div>${Browser.isIEOrEdge ? ZERO_WIDTH_SPACE : '<br>'}</div>`,
editor.getDocument()
);
editor.insertNode(nodes[0]);
editor.select(nodes[0], PositionType.Begin);
} else if (nodes.length == 1) {
let tag = getTagOfNode(nodes[0]);
if (tag == 'BR') {
nodes = [wrap(nodes[0])];
} else if (tag == 'LI' || tag == 'TD') {
nodes = [].slice.call(nodes[0].childNodes) as Node[];
}
} else {
while (
nodes[0] &&
editor.contains(nodes[0].parentNode) &&
nodes.some(node => UNWRAPPABLE_NODES.indexOf(getTagOfNode(node)) >= 0)
) {
nodes = [splitBalancedNodeRange(nodes)];
}
}
if (!core.api.hasFocus(core) || !core.api.getSelectionRange(core, false /*tryGetFromCache*/)) {
// Focus (document.activeElement indicates) and selection are mostly in sync, but could be out of sync in some extreme cases.
// i.e. if you programmatically change window selection to point to a non-focusable DOM element (i.e. tabindex=-1 etc.).
// On Chrome/Firefox, it does not change document.activeElement. On Edge/IE, it change document.activeElement to be body
// Although on Chrome/Firefox, document.activeElement points to editor, you cannot really type which we don't want (no cursor).
// So here we always do a live selection pull on DOM and make it point in Editor. The pitfall is, the cursor could be reset
// to very begin to of editor since we don't really have last saved selection (created on blur which does not fire in this case).
// It should be better than the case you cannot type
if (
!core.cachedSelectionRange ||
!core.api.selectRange(core, core.cachedSelectionRange, true /*skipSameRange*/)
) {
let node = getFirstLeafNode(core.contentDiv) || core.contentDiv;
core.api.selectRange(
core,
createRange(node, PositionType.Begin),
true /*skipSameRange*/
);
}
}
// remember to clear cachedSelectionRange
core.cachedSelectionRange = null;
// This is more a fallback to ensure editor gets focus if it didn't manage to move focus to editor
if (!core.api.hasFocus(core)) {
core.contentDiv.focus();
}
};
editor.addUndoSnapshot(() => {
element.parentNode.insertBefore(div, element);
// Select the new line when we are in table. This is the same behavior with Word
if (getTagOfNode(element) == 'TABLE') {
editor.select(new Position(div, PositionType.Begin).normalize());
}
});
event.rawEvent.preventDefault();
export default function applyTextStyle(
container: Node,
styler: (node: HTMLElement) => any,
from: NodePosition = new Position(container, PositionType.Begin).normalize(),
to: NodePosition = new Position(container, PositionType.End).normalize()
) {
let formatNodes: Node[] = [];
while (from && to && to.isAfter(from)) {
let formatNode = from.node;
let parentTag = getTagOfNode(formatNode.parentNode);
// The code below modifies DOM. Need to get the next sibling first otherwise you won't be able to reliably get a good next sibling node
let nextNode = getNextLeafSibling(container, formatNode);
if (formatNode.nodeType == NodeType.Text && ['TR', 'TABLE'].indexOf(parentTag) < 0) {
if (formatNode == to.node && !to.isAtEnd) {
formatNode = splitTextNode(formatNode, to.offset, true /*returnFirstPart*/);
}
// The code below modifies DOM. Need to get the next sibling first otherwise you won't be able to reliably get a good next sibling node
let nextNode = getNextLeafSibling(container, formatNode);
if (formatNode.nodeType == NodeType.Text && ['TR', 'TABLE'].indexOf(parentTag) < 0) {
if (formatNode == to.node && !to.isAtEnd) {
formatNode = splitTextNode(formatNode, to.offset, true /*returnFirstPart*/);
}
if (from.offset > 0) {
formatNode = splitTextNode(formatNode, from.offset, false /*returnFirstPart*/);
}
formatNodes.push(formatNode);
}
from = nextNode && new Position(nextNode, PositionType.Begin);
}
if (formatNodes.length > 0) {
if (formatNodes.every(node => node.parentNode == formatNodes[0].parentNode)) {
let newNode = formatNodes.shift();
formatNodes.forEach(node => {
newNode.nodeValue += node.nodeValue;
node.parentNode.removeChild(node);
});
formatNodes = [newNode];
}
formatNodes.forEach(node =>
styler(
getTagOfNode(node.parentNode) == 'SPAN'
? splitBalancedNodeRange(node)
editor.addUndoSnapshot(() => {
let childOfQuote = cacheGetQuoteChild(event, editor);
let parent: Node;
if (getTagOfNode(childOfQuote) == QUOTE_TAG) {
childOfQuote = wrap([].slice.call(childOfQuote.childNodes));
}
parent = splitBalancedNodeRange(childOfQuote);
unwrap(parent);
editor.select(childOfQuote, PositionType.Begin);
});
event.rawEvent.preventDefault();
editor.runAsync(() => editor.select(new Position(table, PositionType.Begin).normalize()));
}, ChangeSource.Format);
editor.runAsync(() => {
let newContainer = editor.getElementAtCursor();
if (
contains(vtable.table, newContainer) &&
!contains(td, newContainer, true /*treatSameNodeAsContain*/)
) {
let newPos = targetTd
? new Position(targetTd, PositionType.Begin)
: new Position(vtable.table, isUp ? PositionType.Before : PositionType.After);
if (hasShiftKey) {
newPos =
newPos.node.nodeType == NodeType.Element && isVoidHtmlElement(newPos.node)
? new Position(
newPos.node,
newPos.isAtEnd ? PositionType.After : PositionType.Before
)
: newPos;
editor
.getSelection()
.setBaseAndExtent(anchorNode, anchorOffset, newPos.node, newPos.offset);
} else {
editor.select(newPos);
}
}