Java Code Examples for com.google.gwt.dom.client.Node

The following examples show how to use com.google.gwt.dom.client.Node. These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source Project: swellrt   Source File: ContentNode.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * {@inheritDoc}
 */
@Override
public String toString() {
  String name = getClass().getName();
  name = name.substring(name.lastIndexOf('.') + 1);
  String nodeletString = "destroyed";
  try {
    // Note(user): this toString can fail for text nodes that IE's editor has deleted
    nodeletString = getImplNodelet() == null ? "null" :
        new Pretty<Node>().print(context.rendering().getFullHtmlView(), getImplNodelet());
  } catch (Throwable t) {
  }
  String contentString = new Pretty<ContentNode>().print(
      FullContentView.INSTANCE, this);
  return name + ": " + contentString + " / " + nodeletString;
}
 
Example 2
private void collectHeadings(Element element, List<Element> headings) {
	for (int i = 0; i < element.getChildCount(); i++) {
		Node node = element.getChild(i);
		if (node instanceof Element) {
			Element child = (Element) node;
			String tagName = child.getTagName();
			if (tagName != null && Heading.HEADING_TAGS.contains(tagName.toLowerCase())) {
				if (this.spyName != null && this.spyName.equals(child.getAttribute(Heading.ATTRIBUTE_DATA_SUMMARY))) {
					headings.add(child);
				}
			} else {
				this.collectHeadings(child, headings);
			}
		}
	}
}
 
Example 3
Source Project: incubator-retired-wave   Source File: ContentTextNode.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Same as {@link #findNodeletWithOffset(int, HtmlPoint)}, but does not do
 * a consistency check. Instead it accepts the impl nodelet of the next
 * wrapper (or null) and assumes everthing is consistent.
 */
public void findNodeletWithOffset(int offset, HtmlPoint output, Node nextImpl) {
  HtmlView filteredHtml = getFilteredHtmlView();

  int sum = 0;
  int prevSum;
  for (Text nodelet = getImplNodelet(); nodelet != nextImpl;
      nodelet = filteredHtml.getNextSibling(nodelet).cast()) {
    prevSum = sum;
    sum += nodelet.getLength();
    if (sum >= offset) {
      output.setNode(nodelet);
      output.setOffset(offset - prevSum);
      return;
    }
  }

  output.setNode(null);
}
 
Example 4
Source Project: swellrt   Source File: TypingExtractor.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * @param point
 * @return The offset of the point with respect to the start of our typing
 *    sequence, not with respect to its container text node. Returns -1
 *    if the point's container node isn't one of the impl nodes of our
 *    mutatingNode.
 */
private int getAbsoluteOffset(Point<Node> point) {
  // This method is used to calculate minpre and minpost.
  // We shouldn't need this method if mutatingNode is null, because
  // in such cases minpre and minpost are both trivially zero.
  assert firstWrapper != null;

  if (partOfMutatingRange(point.getContainer())) {
    // TODO(danilatos): check for mutatingNodeOwns duplicates a loop which
    // is done in getOffset
    Text toFind = point.getContainer().<Text>cast();
    HtmlView filteredHtml = filteredHtmlView;

    return ContentTextNode.getOffset(
        toFind,
        htmlRange.getStartNode(filteredHtml).<Text>cast(),
        htmlRange.getNodeAfter(),
        filteredHtml) + point.getTextOffset();
  }

  return -1;
}
 
Example 5
Source Project: gwt-traction   Source File: GroupedListBox.java    License: Apache License 2.0 6 votes vote down vote up
@Override
public Node getInsertBeforeElement(int index) {
    Node before;

    // adjust the index to inside the group
    int adjusted = getIndexInGroup(name, index);

    // we had a real index (wasn't negative which means
    // add to the end), but it was too low for this group.
    // put it at the beginning of the group.
    if (adjusted < 0 && index >= 0) {
        adjusted = 0;
    }

    // check the range and if it's out of range, we'll
    // just add it to the end
    // of the group (before == null)
    if (0 <= adjusted && adjusted < count) {
        before = element.getChild(adjusted);
    }
    else {
        before = null;
    }

    return before;
}
 
Example 6
Source Project: swellrt   Source File: SelectionImplIE.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * @param target collapsed text range
 * @return HtmlPoint matching the collapsed text range
 */
private Point<Node> pointAtCollapsedRangeInner(JsTextRangeIE target) {
  // The point is (mostly) either directly in target's parent,
  // or in a text node child of parent. (Occasionally, the point
  // sits right after the parent, see below.)
  Element parent = target.parentElement();

  // XXX(zdwang): For some reason IE 7 likes to focus on the input box of the
  // contacts pop up during the on key press event when you press shift+enter
  // on a blip. This causes attempt.moveToElementText(el) to thrown an
  // exception.
  // TODO(user): check with zdwang if this is still needed...
  if (parent.getTagName().equals("INPUT")) {
    return Point.inElement(parent, parent.getFirstChild());
  }

  // This catches an corner case where the target is actually
  // *outside* its parent node. This happens, e.g., in this case:
  // <p><thumbnail/>|</p>. Best look out for other such cases!
  while (parent.getAttribute("contentEditable").equalsIgnoreCase("false")) {
    parent = parent.getParentElement();
  }
  return binarySearchForRange(target, parent);
  // return searchForRangeUsingPaste(target, parent);
  // return linearSearchForRange(target, parent);
}
 
Example 7
Source Project: swellrt   Source File: SelectionImplIE.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Search for node by pasting that element at a textRange and locating that
 * element directly using getElementById. This is a huge shortcut when there
 * are many nodes in parent. However, use with caution as it can fragment text
 * nodes.
 *
 * NOTE(user): The text node fragmentation is a real issue, it causes repairs
 * to happen. The constant splitting and repairing can also have performance
 * issues that needs to be investigated. We should repair the damage here,
 * when its clear how to fix the problem.
 *
 * @param target
 * @param parent
 * @return Point
 */
@SuppressWarnings("unused") // NOTE(user): Use later for nodes with many siblings.
private Point<Node> searchForRangeUsingPaste(JsTextRangeIE target, Element parent) {
  Element elem = null;
  try {
    target.pasteHTML("<b id='__paste_target__'>X</b>");
    elem = Document.get().getElementById("__paste_target__");
    Node nextSibling = elem.getNextSibling();
    if (DomHelper.isTextNode(nextSibling)) {
      return Point.inText(nextSibling, 0);
    } else {
      return Point.inElement(parent, nextSibling);
    }
  } finally {
    if (elem != null) {
      elem.removeFromParent();
    }
  }
}
 
Example 8
Source Project: swellrt   Source File: SelectionMatcher.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Note the points if matched.
 *
 * If the initial content start or content end match the boundary of source,
 * then note the html point on the corresponding boundary of clone.
 *
 * If source is a text node, or is empty, note the html point inside the
 * corresponding position in clone.
 *
 * @param source
 * @param clone
 */
public void maybeNoteHtml(ContentNode source, Node clone) {
  Preconditions.checkArgument(source != null, "Source must be non-null");
  Preconditions.checkArgument(source.getParentElement() != null, "Source must have parent.");
  assert htmlRootContainer.isOrHasChild(clone) : "Reference node must be attached";
  if (htmlStart == null) {
    maybeSetStartAtBoundary(source, clone);
    maybeSetStartInText(source, clone);
    maybeSetStartInEmptyElement(source, clone);
  }

  if (htmlEnd == null) {
    maybeSetEndAtBoundary(source, clone);
    maybeSetEndInText(source, clone);
    maybeSetEndInEmptyElement(source, clone);
  }
}
 
Example 9
Source Project: swellrt   Source File: ContentNode.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Same as {@link #getImplNodeletRightwards()} but with early exit
 * @param toExcl Stop here if reached
 */
public Node getImplNodeletRightwards(ContentNode toExcl) {
  // TODO(danilatos): This implementation will skip over an html-only node
  // in the midst of other impl nodelets. This might not be desirable in
  // some contexts...
  assert isContentAttached();
  ContentNode node = this;
  Node nodelet = null;
  ContentView renderedContent = getRenderedContentView();
  while (node != toExcl) {
    nodelet = node.getImplNodelet();
    if (nodelet != null) {
      break;
    }
    node = renderedContent.getNextSibling(node);
  }
  return nodelet;
}
 
Example 10
Source Project: swellrt   Source File: ParagraphHelperBr.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Get the spacer for the given paragraph.
 * Lazily creates & registers one if not present.
 * If there's one that the browser created, registers it as our own.
 * If the browser put a different one in to the one that we were already
 * using, replace ours with the browser's.
 * @param paragraph
 * @return The spacer
 */
protected BRElement getSpacer(Element paragraph) {
  Node last = paragraph.getLastChild();
  BRElement spacer = paragraph.getPropertyJSO(BR_REF).cast();
  if (spacer == null) {
    // Register our spacer, using one the browser put in if present
    spacer = isSpacer(last) ? last.<BRElement>cast() : Document.get().createBRElement();
    setupSpacer(paragraph, spacer);
  } else if (isSpacer(last) && last != spacer) {
    // The browser put a different one in by itself, so let's use that one
    if (spacer.hasParentElement()) {
      spacer.removeFromParent();
    }
    spacer = last.<BRElement>cast();
    setupSpacer(paragraph, spacer);
  }
  return spacer;
}
 
Example 11
Source Project: incubator-retired-wave   Source File: DomHelper.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Ensures the given container contains exactly one child, the given one.
 * Provides the important property that if the container is already the parent
 * of the given child, then the child is not removed and re-added, it is left
 * there; any siblings, if present, are removed.
 *
 * @param container
 * @param child
 */
public static void setOnlyChild(Element container, Node child) {
  if (child.getParentElement() != container) {
    // simple case
    emptyElement(container);
    container.appendChild(child);
  } else {
    // tricky case - avoid removing then re-appending the same child
    while (child.getNextSibling() != null) {
      child.getNextSibling().removeFromParent();
    }
    while (child.getPreviousSibling() != null) {
      child.getPreviousSibling().removeFromParent();
    }
  }
}
 
Example 12
Source Project: swellrt   Source File: TypingExtractor.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Specify that a typing sequence might be starting between two elements,
 * or in an empty element. If there is a text node at the cursor,
 * {@link #startTypingSequence(Point.Tx)} should be called instead
 * @param point A point between nodes
 */
private void startTypingSequence(Point.El<Node> point) {
  htmlRange = RestrictedRange.collapsedAt(filteredHtmlView, point);
  assert htmlRange.getContainer() != null;
  assert
      (htmlRange.getNodeBefore() == null || !DomHelper.isTextNode(htmlRange.getNodeBefore())) &&
      (htmlRange.getNodeAfter() == null || !DomHelper.isTextNode(htmlRange.getNodeAfter()));

  contentRange = RestrictedRange.<ContentNode>boundedBy(
      NodeManager.getBackReference(htmlRange.getContainer().<Element>cast()),
      NodeManager.getBackReference(htmlRange.getNodeBefore().<Element>cast()),
      NodeManager.getBackReference(htmlRange.getNodeAfter().<Element>cast()));
}
 
Example 13
Source Project: incubator-retired-wave   Source File: TypingExtractor.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * @param selection
 * @return The typing state that the given text node is a part of, or null if none
 */
private TypingState findTypingState(Point<Node> selection) {
  for (int i = 0; i < numStates; i++) {
    TypingState t = statePool.get(i);
    if (t.isClear()) {
      continue;
    }
    if (t.isPartOfThisState(selection)) {
      return t;
    }
  }
  return null;
}
 
Example 14
Source Project: incubator-retired-wave   Source File: SelectionImplIE.java    License: Apache License 2.0 5 votes vote down vote up
private boolean pointMatchesRange(Point<Node> point, JsTextRangeIE target) {
  try {
  JsTextRangeIE tr = collapsedRangeAtPoint(point);
  return tr.compareEndPoints(StartToStart, target) == 0;
  } catch (Exception e) {
    return false;
  }
}
 
Example 15
Source Project: swellrt   Source File: NodeManager.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Converts a nodelet to a Point of contentNode
 *
 * @param nodelet
 * @return content node point
 * @throws HtmlInserted
 * @throws HtmlMissing
 */
public Point<ContentNode> nodeletPointToWrapperPoint(Point<Node> nodelet) throws HtmlInserted,
    HtmlMissing {
  if (nodelet.isInTextNode()) {
    return textNodeToWrapperPoint(nodelet.getContainer().<Text> cast(), nodelet.getTextOffset());
  } else {
    return elementNodeToWrapperPoint(nodelet.getContainer().<Element> cast(), nodelet
        .getNodeAfter());
  }
}
 
Example 16
Source Project: swellrt   Source File: StrippingHtmlView.java    License: Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public Node getVisibleNode(Node node) {
  Node next;
  while (true) {
    next = node.getParentElement();
    if (maybeStrip(node) == false) {
      return node;
    }
    node = next;
  }
}
 
Example 17
Source Project: swellrt   Source File: SelectionUtil.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Takes an html selection and returns it, or null if it's not related to editor content.
 *
 * @param htmlSelection Selection range to filter.
 * @return htmlSelection or null if there's no related content.
 */
public static FocusedPointRange<Node> filterNonContentSelection(
    FocusedPointRange<Node> htmlSelection) {
  if (htmlSelection == null) {
    return null; // quick exit
  }

  // get just the focus point, finding the element it is inside.
  Point<Node> htmlFocus = htmlSelection.getFocus();
  Element el;
  if (htmlFocus.isInTextNode()) {
    el = htmlFocus.getContainer().getParentElement();
  } else {
    el = htmlFocus.getContainer().cast();
  }

  // Assume given range is always in the editor, the htmlHelper should guarantee that.
  while (!NodeManager.hasBackReference(el)) {
    if (NodeManager.getTransparency(el) == Skip.DEEP
        || el.getPropertyBoolean(ContentElement.COMPLEX_IMPLEMENTATION_MARKER)) {

      // Exception: when we explicitly want the selection still to be reported
      if (!NodeManager.mayContainSelectionEvenWhenDeep(el)) {
        htmlSelection = null;
        break;
      }
    }
    el = el.getParentElement();
  }

  return htmlSelection;
}
 
Example 18
Source Project: swellrt   Source File: SelectionMatcher.java    License: Apache License 2.0 5 votes vote down vote up
private void maybeSetEndAtBoundary(ContentNode c, Node node) {
  if (contentEnd.equals(Point.inElement(c.getParentElement(), c))) {
    htmlEnd = beforeNode(node);
  } else if (contentEnd.equals((Point.inElement(c.getParentElement(), c.getNextSibling())))) {
    htmlEnd = afterNode(node);
  }
}
 
Example 19
Source Project: incubator-retired-wave   Source File: StrippingHtmlView.java    License: Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public Node getPreviousSibling(Node node) {
  Node n;
  while (maybeStrip(n = node.getPreviousSibling())) { }
  return n;
}
 
Example 20
Source Project: swellrt   Source File: ContentTextNode.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * @see RawDocument#deleteData(Object, int, int)
 */
void deleteData(int offset, int count, boolean affectImpl) {
  String data = getData();

  setContentData(
      data.substring(0, offset) +
      data.substring(offset + count, data.length()));

  if (affectImpl) {
    if (isImplAttached()) {
      findNodeletWithOffset(offset, nodeletOffsetOutput, getRepairer());
      Text nodelet = nodeletOffsetOutput.getNode().cast();
      int subOffset = nodeletOffsetOutput.getOffset();

      if (nodelet.getLength() - subOffset >= count) {
        // Handle the special case where the delete is in a single text nodelet
        // carefully, to avoid splitting it
        nodelet.deleteData(subOffset, count);
        getExtendedContext().editing().textNodeletAffected(
            nodelet, subOffset, -count, TextNodeChangeType.DATA);
      } else {
        // General case
        Node toExcl = implSplitText(offset + count);
        Node fromIncl = implSplitText(offset);

        HtmlView filteredHtml = getFilteredHtmlView();
        for (Node node = fromIncl; node != toExcl && node != null;) {
          Node next = filteredHtml.getNextSibling(node);
          node.removeFromParent();
          node = next;
        }
      }
    } else {
      // TODO(user): have these assertion failure fixed (b/2129931)
      // assert getImplNodelet().getLength() == getLength() :
      //    "text node's html impl not normalised while not attached to html dom";
      getImplNodelet().deleteData(offset, count);
    }
  }
}
 
Example 21
/** {@inheritDoc} */
public FocusedContentRange getSelectionPoints() {
  FocusedPointRange<Node> range = htmlHelper.getHtmlSelection();
  try {
    needsCorrection = false;

    range = SelectionUtil.filterNonContentSelection(range);

    if (range == null) {
      return null;
    }
    Point<ContentNode>
      anchor = nodeletPointToFixedContentPoint(range.getAnchor()),
      focus = range.isCollapsed()
            ? anchor : nodeletPointToFixedContentPoint(range.getFocus());

    if (anchor == null || focus == null) {
      return null;
    }

    // Uncomment for verbose debugging
    // if (Debug.isOn(LogSeverity.DEBUG)) {
    //   logger.logXml("SELECTION: " + start + " - " + end);
    // }

    FocusedContentRange ret = range.isCollapsed()
        ? new FocusedContentRange(anchor) : new FocusedContentRange(anchor, focus);

    if (needsCorrection && ret != null) {
      setSelectionPoints(ret.getAnchor(), ret.getFocus());
    }

    return ret;
  } finally {
    needsCorrection = false;
  }
}
 
Example 22
Source Project: swellrt   Source File: ContentTextNode.java    License: Apache License 2.0 5 votes vote down vote up
private static int sumTextNodesLength(Text fromIncl, Node toExcl, HtmlView filteredHtml) {
  int length = 0;
  for (Text n = fromIncl; n != toExcl && n != null;
      n = filteredHtml.getNextSibling(n).cast()) {
    length += n.getLength();
  }

  return length;
}
 
Example 23
Source Project: swellrt   Source File: SelectionW3CNative.java    License: Apache License 2.0 5 votes vote down vote up
public final void setAnchorAndFocus(Node anchorNode, int anchorOffset,
    Node focusNode, int focusOffset) {
  if (QuirksConstants.HAS_BASE_AND_EXTENT) {
    // NOTE(danilatos): While extend() would also work for webkit,
    // we have to use setBaseAndExtent because it appears to reuse
    // the existing range, rather than needing to replace it, and
    // doing otherwise stuffs up the IME composition state
    setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
  } else {

    // We assume that anchor node is in the same focusable area.
    // If not, death will ensue.
    setFocusElement(focusNode);

    // TODO(danilatos): Investigate just using extend() twice - i.e.
    // extend to the anchor -> collapse to end -> extend to the focus.
    JsRange range = JsRange.create();
    range.setStart(anchorNode, anchorOffset);
    range.collapse(true);

    removeAllRanges();
    addRange(range);

    if (focusNode != anchorNode || focusOffset != anchorOffset) {
      try {
          extend(focusNode, focusOffset);
      } catch (JavaScriptException e) {
        NativeSelectionUtil.LOG.error().logPlainText(
            "error extending selection from " + anchorNode + ":" + anchorOffset +
            " to " + focusNode + ":" + focusOffset);
        removeAllRanges();
        range = JsRange.create();
        range.setStart(anchorNode, anchorOffset);
        range.collapse(true);
        range.setEnd(focusNode, focusOffset);
        addRange(range);
      }
    }
  }
}
 
Example 24
public RemovalEntry(Node removedNode, Element oldParent, Node oldNodeAfter,
    boolean removeAfter) {
  if (oldParent == null) {
    throw new IllegalArgumentException("Old parent cannot be null");
  }
  this.removeAfter = removeAfter;
  this.removedNode = removedNode;
  this.oldParent = oldParent;
  this.oldNodeAfter = oldNodeAfter;
}
 
Example 25
public DoubleVector inverseScreenTransform(SvgElement relative, DoubleVector point) {
  ensureSourceRegistered(relative);

  SvgSvgElement owner = relative.getOwnerSvgElement();
  ensureSourceRegistered(owner);

  Node ownerTarget = myMappingMap.get(owner).getTarget();
  return inverseScreenTransform(ownerTarget, point.x, point.y);
}
 
Example 26
Source Project: swellrt   Source File: NodeManager.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * @param point point of node
 * @return htmlpoint
 */
public static HtmlPoint nodeletPointToHtmlPoint(Point<Node> point) {
  if (point.isInTextNode()) {
    return new HtmlPoint(point.getContainer(), point.getTextOffset());
  } else {
    return point.getNodeAfter() == null
        ? new HtmlPoint(point.getContainer(), point.getContainer().getChildCount())
        : new HtmlPoint(point.getContainer(), DomHelper.findChildIndex(point.getNodeAfter()));
  }
}
 
Example 27
Source Project: swellrt   Source File: FakeUser.java    License: Apache License 2.0 5 votes vote down vote up
@SuppressWarnings("unchecked")  // NOTE(zdwang): This is for (Point<Node>) action[1]
public void run(TypingExtractor extractor, Object... actions) throws HtmlMissing, HtmlInserted {
  for (Object a : actions) {
    Object[] action = (Object[]) a;
    Point<Node> sel = getSelectionStart();
    Text txt = sel == null ? null : sel.getContainer().<Text>cast();
    Action type = (Action) action[0];
    switch (type) {
      case MOVE:
        //extractor.flush();
        setCaret((Point<Node>) action[1]);
        break;
      case TYPE:
        String typed = (String) action[1];
        extractor.somethingHappened(getSelectionStart());
        if (sel.isInTextNode()) {
          txt.insertData(sel.getTextOffset(), (String) action[1]);
          moveCaret(((String) action[1]).length());
        } else {
          txt = Document.get().createTextNode(typed);
          sel.getContainer().insertBefore(txt, sel.getNodeAfter());
          setCaret(Point.inText((Node)txt, typed.length()));
        }
        break;
      case BACKSPACE:
      case DELETE:
        extractor.somethingHappened(getSelectionStart());
        int amount = (Integer) action[1];
        if (type == Action.BACKSPACE) {
          moveCaret(-amount);
        }
        deleteText(amount);
        break;
      case SPLIT:
        sel.getContainer().<Text>cast().splitText(sel.getTextOffset());
        moveCaret(0);
        break;
    }
  }
}
 
Example 28
Source Project: swellrt   Source File: StrippingHtmlView.java    License: Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public Node getFirstChild(Node node) {
  Node n;
  while (maybeStrip(n = node.getFirstChild())) { }
  return n;
}
 
Example 29
Source Project: incubator-retired-wave   Source File: SelectionImplW3C.java    License: Apache License 2.0 5 votes vote down vote up
@Override
FocusedPointRange<Node> get() {
  SelectionW3CNative selection = SelectionW3CNative.getSelectionGuarded();
  if (selection == null) {
    // NOTE(danilatos): This seems to happen very rarely with FF.
    // I wonder what the reproducible cause is.
    return null;
  }
  Node anchorNode = selection.anchorNode();
  Node focusNode = selection.focusNode();
  return focusNode == null ? null : constructRange(
      anchorNode, selection.anchorOffset(),
      focusNode, selection.focusOffset());
}
 
Example 30
Source Project: swellrt   Source File: SelectionImplW3C.java    License: Apache License 2.0 5 votes vote down vote up
@Override
void set(Point<Node> anchor, Point<Node> focus) {

  int anchorOffset;
  int focusOffset;
  JsRange range = JsRange.create();

  Node anchorNode = anchor.getContainer();
  Node focusNode = focus.getContainer();

  assert anchorNode != null : "Anchor node must not be null.";
  assert focusNode != null : "Focus node must not be null.";

  if (anchor.isInTextNode()) {
    anchorOffset = anchor.getTextOffset();
  } else if (anchor.getNodeAfter() == null) {
    anchorOffset = anchorNode.getChildCount();
  } else {
    anchorNode = anchor.getNodeAfter().getParentElement();
    range.setStartBefore(anchor.getNodeAfter());
    anchorOffset = range.startOffset();
  }

  if (focus.isInTextNode()) {
    focusOffset = focus.getTextOffset();
  } else {
    Node focusNodeAfter = focus.getNodeAfter();
    if (focusNodeAfter == null) {
      focusOffset = focusNode.getChildCount();
    } else {
      focusNode = focusNodeAfter.getParentElement();
      assert focusNode != null : "focus node must not be null";
      range.setStartBefore(focusNodeAfter);
      focusOffset = range.startOffset();
    }
  }

  SelectionW3CNative.getSelectionUnsafe().setAnchorAndFocus(
      anchorNode, anchorOffset, focusNode, focusOffset);
}