function getPointForNonTextNode()

in src/component/selection/getDraftEditorSelectionWithNodes.js [152:226]


function getPointForNonTextNode(
  editorRoot: ?HTMLElement,
  startNode: Node,
  childOffset: number,
): SelectionPoint {
  let node = startNode;
  const offsetKey: ?string = findAncestorOffsetKey(node);

  invariant(
    offsetKey != null ||
      (editorRoot && (editorRoot === node || editorRoot.firstChild === node)),
    'Unknown node in selection range.',
  );

  // If the editorRoot is the selection, step downward into the content
  // wrapper.
  if (editorRoot === node) {
    node = node.firstChild;
    invariant(
      isElement(node),
      'Invalid DraftEditorContents node. Expected element but instead got a node with type of %s.',
      [node?.nodeType],
    );
    const castedNode: Element = (node: any);

    // assignment only added for flow :/
    // otherwise it throws in line 200 saying that node can be null or undefined
    node = castedNode;
    invariant(
      node.getAttribute('data-contents') === 'true',
      'Invalid DraftEditorContents structure.',
    );
    if (childOffset > 0) {
      childOffset = node.childNodes.length;
    }
  }

  // If the child offset is zero and we have an offset key, we're done.
  // If there's no offset key because the entire editor is selected,
  // find the leftmost ("first") leaf in the tree and use that as the offset
  // key.
  if (childOffset === 0) {
    let key: ?string = null;
    if (offsetKey != null) {
      key = offsetKey;
    } else {
      const firstLeaf = getFirstLeaf(node);
      key = nullthrows(getSelectionOffsetKeyForNode(firstLeaf));
    }
    return {key, offset: 0};
  }

  const nodeBeforeCursor = node.childNodes[childOffset - 1];
  let leafKey: ?string = null;
  let textLength: ?number = null;

  if (!getSelectionOffsetKeyForNode(nodeBeforeCursor)) {
    // Our target node may be a leaf or a text node, in which case we're
    // already where we want to be and can just use the child's length as
    // our offset.
    leafKey = nullthrows(offsetKey);
    textLength = getTextContentLength(nodeBeforeCursor);
  } else {
    // Otherwise, we'll look at the child to the left of the cursor and find
    // the last leaf node in its subtree.
    const lastLeaf = getLastLeaf(nodeBeforeCursor);
    leafKey = nullthrows(getSelectionOffsetKeyForNode(lastLeaf));
    textLength = getTextContentLength(lastLeaf);
  }

  return {
    key: leafKey,
    offset: textLength,
  };
}