How to use roosterjs-editor-dom - 10 common examples

To help you get started, we’ve selected a few roosterjs-editor-dom examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github microsoft / roosterjs / packages / roosterjs-editor-api / lib / format / clearBlockFormat.ts View on Github external
return false;
    }

    // 1. Recursively clear format of all its child nodes
    let allChildrenAreBlock = ([].slice.call(node.childNodes) as Node[])
        .map(n => clearNodeFormat(n, tagsToUnwrap, tagsToStopUnwrap, attributesToPreserve))
        .reduce((previousValue, value) => previousValue && value, true);

    if (!canCollapse(tagsToStopUnwrap, node)) {
        return false;
    }

    let returnBlockElement = isBlockElement(node);

    // 2. If we should unwrap this tag, put it into an array and unwrap it later
    if (tagsToUnwrap.indexOf(getTagOfNode(node)) >= 0 || allChildrenAreBlock) {
        if (returnBlockElement && !allChildrenAreBlock) {
            wrap(node);
        }
        unwrap(node);
    } else {
        // 3. Otherwise, remove all attributes
        clearAttribute(node as HTMLElement, attributesToPreserve);
    }

    return returnBlockElement;
}
github microsoft / roosterjs / packages / roosterjs-editor-plugins / lib / ContentEdit / features / insertLineBeforeStructuredNodeFeature.ts View on Github external
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();
github microsoft / roosterjs / packages / roosterjs-editor-plugins / lib / ContentEdit / features / insertLineBeforeStructuredNodeFeature.ts View on Github external
return cacheGetEventData(event, 'FIRST_STRUCTURE', () => {
        // Provide a chance to keep browser default behavior by pressing SHIFT
        let element = event.rawEvent.shiftKey ? null : editor.getElementAtCursor(CHILD_SELECTOR);

        if (element) {
            let range = editor.getSelectionRange();
            if (
                range &&
                range.collapsed &&
                isPositionAtBeginningOf(Position.getStart(range), element) &&
                !editor.getBodyTraverser(element).getPreviousBlockElement()
            ) {
                return editor.getElementAtCursor(CHILD_PARENT_TAG_MAP[getTagOfNode(element)]);
            }
        }

        return null;
    });
}
github microsoft / roosterjs / packages / roosterjs-editor-core / lib / coreAPI / createEventHandlers.ts View on Github external
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);
}
github microsoft / roosterjs / packages / roosterjs-editor-core / lib / coreAPI / selectRange.ts View on Github external
export const selectRange: SelectRange = (
    core: EditorCore,
    range: Range,
    skipSameRange?: boolean
) => {
    let selection: Selection;
    let needAddRange = true;

    if (
        !contains(core.contentDiv, range) ||
        !(selection = core.document.defaultView.getSelection())
    ) {
        return false;
    }

    if (selection.rangeCount > 0) {
        // Workaround IE exception 800a025e
        try {
            let currentRange: Range;
            // Do not remove/add range if current selection is the same with target range
            // Without this check, execCommand() may fail in Edge since we changed the selection
            if (
                (skipSameRange || Browser.isEdge) &&
                (currentRange = selection.rangeCount == 1 ? selection.getRangeAt(0) : null) &&
                currentRange.startContainer == range.startContainer &&
                currentRange.startOffset == range.startOffset &&
github microsoft / roosterjs / packages / roosterjs-editor-core / lib / coreAPI / createEventHandlers.ts View on Github external
selectionRange.collapsed &&
        (focusNode = selectionRange.startContainer) &&
        (focusNode == core.contentDiv ||
            (focusNode.nodeType == NodeType.Text && focusNode.parentNode == core.contentDiv))
    ) {
        let editorSelection = new EditorSelection(
            core.contentDiv,
            selectionRange,
            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>', core.document);
            let element = core.contentDiv.appendChild(nodes[0]) as HTMLElement;
            applyFormat(element, core.defaultFormat);
            // element points to a wrapping node we added "<div><br></div>". We should move the selection left to <br>
            selectEditorPoint(core, 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, core.defaultFormat);
            }
            // Last restore the selection using the normalized editor point
github microsoft / roosterjs / packages / roosterjs-editor-api / lib / utils / processList.ts View on Github external
function workaroundForChrome(editor: Editor) {
    let traverser = editor.getSelectionTraverser();
    let block = traverser &amp;&amp; traverser.currentBlockElement;
    while (block) {
        let container = block.getStartNode();

        if (container) {
            // Add a temp <img> tag before all other nodes in the block to avoid Chrome remove existing format when toggle list
            const tempNode = fromHtml(TEMP_NODE_HTML, editor.getDocument())[0];
            if (isVoidHtmlElement(container) || !isBlockElement(container)) {
                container.parentNode.insertBefore(tempNode, container);
            } else {
                container.insertBefore(tempNode, container.firstChild);
            }
        }

        block = traverser.getNextBlockElement();
    }
}
github microsoft / roosterjs / packages / roosterjs-editor-core / lib / corePlugins / TypeInContainerPlugin.ts View on Github external
if (block) {
            formatNode = block.collapseToSingleElement();

            // if the block is empty, apply default format
            // Otherwise, leave it as it is as we don't want to change the style for existing data
            // unless the block was just created by the keyboard event (e.g. ctrl+a &amp; start typing)
            const shouldSetNodeStyles =
                isNodeEmpty(formatNode) ||
                (event &amp;&amp; this.wasNodeJustCreatedByKeyboardEvent(event, formatNode));
            formatNode = formatNode &amp;&amp; shouldSetNodeStyles ? formatNode : null;
        } else {
            // 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());
github microsoft / roosterjs / packages / roosterjs-editor-core / lib / editor / Editor.ts View on Github external
public insertContent(content: string, option?: InsertOption) {
        if (content) {
            let allNodes = fromHtml(content, this.core.document);
            // If it is to insert on new line, and there are more than one node in the collection, wrap all nodes with
            // a parent DIV before calling insertNode on each top level sub node. Otherwise, every sub node may get wrapped
            // separately to show up on its own line
            if (option &amp;&amp; option.insertOnNewLine &amp;&amp; allNodes.length &gt; 0) {
                allNodes = [wrapAll(allNodes)];
            }
            for (let i = 0; i &lt; allNodes.length; i++) {
                this.insertNode(allNodes[i], option);
            }
        }
    }
github microsoft / roosterjs / packages / roosterjs-editor-api / lib / utils / toggleTagCore.ts View on Github external
let startBlock = editor.getBlockElementAtNode(startNode);
            let endNode = Position.getEnd(range).normalize().node;
            let endBlock = editor.getBlockElementAtNode(endNode);
            let nodes =
                startBlock &amp;&amp; endBlock
                    ? 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] &amp;&amp;
                    editor.contains(nodes[0].parentNode) &amp;&amp;