All files / src/core/dom manipulation.ts

100% Statements 33/33
100% Branches 24/24
100% Functions 8/8
100% Lines 28/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91                        4x 24x 20x       20x 16x 8x     8x 24x 3x   24x       8x       16x 12x 1x   11x 2x       16x                   6x             6x             6x             6x           4x 23x 9x   21x 20x 20x 15x    
import { isArrayLike, isHTMLElement } from 'core/utils/types';
import { each } from 'core/utils/arrays';
import { parent } from 'core/dom/traversal';
 
type NodeCollection = ArrayLike<Node> | Node | undefined | null;
 
/**
 * Inserts Nodes before the given preferredAnchor element.
 * @param parent The parent of the preferredAnchor element or the element which shall be the parent of the inserted Nodes.
 * @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end.
 * @param insertedElms The Nodes which shall be inserted.
 */
const before: (parent: Node | null, preferredAnchor: Node | null, insertedElms: NodeCollection) => void = (parent, preferredAnchor, insertedElms) => {
    if (insertedElms) {
        let anchor: Node | null = preferredAnchor;
        let fragment: DocumentFragment | Node | undefined | null;
 
        // parent must be defined
        if (parent) {
            if (isArrayLike(insertedElms)) {
                fragment = document.createDocumentFragment();
 
                // append all insertedElms to the fragment and if one of these is the anchor, change the anchor
                each(insertedElms, (insertedElm) => {
                    if (insertedElm === anchor) {
                        anchor = insertedElm.previousSibling;
                    }
                    fragment!.appendChild(insertedElm);
                });
            }
            else {
                fragment = insertedElms;
            }
 
            // if the preferred anchor isn't null set it to a valid anchor
            if (preferredAnchor) {
                if (!anchor) {
                    anchor = parent.firstChild;
                }
                else if (anchor !== preferredAnchor) {
                    anchor = anchor.nextSibling;
                }
            }
 
            parent.insertBefore(fragment, anchor);
        }
    }
}
 
/**
 * Appends the given children at the end of the given Node.
 * @param node The Node to which the children shall be appended.
 * @param children The Nodes which shall be appended.
 */
export const appendChildren: (node: Node | null, children: NodeCollection) => void = (node, children) => { before(node, null, children) };
 
/**
 * Prepends the given children at the start of the given Node.
 * @param node The Node to which the children shall be prepended.
 * @param children The Nodes which shall be prepended.
 */
export const prependChildren: (node: Node | null, children: NodeCollection) => void = (node, children) => { before(node, node && node.firstChild, children) };
 
/**
 * Inserts the given Nodes before the given Node.
 * @param node The Node before which the given Nodes shall be inserted.
 * @param insertedNodes The Nodes which shall be inserted.
 */
export const insertBefore: (node: Node | null, insertedNodes: NodeCollection) => void = (node, insertedNodes) => { before(parent(node), node, insertedNodes) };
 
/**
 * Inserts the given Nodes after the given Node.
 * @param node The Node after which the given Nodes shall be inserted.
 * @param insertedNodes The Nodes which shall be inserted.
 */
export const insertAfter: (node: Node | null, insertedNodes: NodeCollection) => void = (node, insertedNodes) => { before(parent(node), node && node.nextSibling, insertedNodes) };
 
/**
 * Removes the given Nodes from their parent.
 * @param nodes The Nodes which shall be removed.
 */
export const removeElements: (nodes: NodeCollection) => void = (nodes) => {
    if (isArrayLike(nodes)) {
        each(Array.from(nodes), (e) => removeElements(e));
    }
    else if (nodes) {
        const parentNode = nodes.parentNode;
        if (parentNode)
            parentNode.removeChild(nodes);
    }
}