All files / src/support/dom manipulation.ts

100% Statements 33/33
100% Branches 26/26
100% Functions 8/8
100% Lines 32/32

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 92 93 94 95 96 97 98 99 100 101 102 103 104 105                        14x         2299x 2000x       2000x 1996x 624x     624x 982x 3x   982x     1372x       1996x 358x 1x 357x 2x       1996x                   14x 1935x               14x 7x               14x       255x               14x 102x             14x 761x 9x 759x 758x 758x 753x        
import { isArrayLike } from 'support/utils/types';
import { each, from } from 'support/utils/array';
import { parent } from 'support/dom/traversal';
 
type NodeCollection = ArrayLike<Node> | Node | false | null | undefined;
 
/**
 * Inserts Nodes before the given preferredAnchor element.
 * @param parentElm 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 = (
  parentElm: Node | false | null | undefined,
  preferredAnchor: Node | null | undefined,
  insertedElms: NodeCollection
): void => {
  if (insertedElms) {
    let anchor: Node | null | undefined = preferredAnchor;
    let fragment: DocumentFragment | Node | null | undefined;
 
    // parent must be defined
    if (parentElm) {
      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 = parentElm.firstChild;
        } else if (anchor !== preferredAnchor) {
          anchor = anchor.nextSibling;
        }
      }
 
      parentElm.insertBefore(fragment, anchor || null);
    }
  }
};
 
/**
 * 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 | undefined, children: NodeCollection): void => {
  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 | undefined, children: NodeCollection): void => {
  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 | undefined,
  insertedNodes: NodeCollection
): void => {
  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 | undefined, insertedNodes: NodeCollection): void => {
  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 => {
  if (isArrayLike(nodes)) {
    each(from(nodes), (e) => removeElements(e));
  } else if (nodes) {
    const parentElm = parent(nodes);
    if (parentElm) {
      parentElm.removeChild(nodes);
    }
  }
};