예제 #1
0
  @Test
  public void clone_Deep() {
    // Arrange
    AnchorElement child = Document.get().createAnchorElement();
    child.setInnerText("child inner text");
    child.getStyle().setBackgroundColor("black");
    n.appendChild(child);

    // Act
    DivElement newNode = n.cloneNode(true).cast();

    // Assert
    assertEquals(Node.ELEMENT_NODE, newNode.getNodeType());
    DivElement source = n.cast();
    assertEquals(source.getInnerText(), newNode.getInnerText());
    assertEquals(source.getInnerHTML(), newNode.getInnerHTML());
    assertEquals(source.toString(), newNode.toString());

    assertNull(newNode.getParentNode());
    assertEquals(n.getChildNodes().getLength(), newNode.getChildNodes().getLength());

    assertEquals(Node.ELEMENT_NODE, newNode.getChildNodes().getItem(0).getNodeType());
    AnchorElement childElement = newNode.getChildNodes().getItem(0).cast();
    assertEquals("child inner text", childElement.getInnerText());

    Style newStyle = childElement.getStyle();
    assertTrue(newStyle != child.getStyle());
    assertEquals("black", newStyle.getBackgroundColor());
  }
예제 #2
0
 private Element getLastChildElement(Element parent) {
   Node lastTab = parent.getLastChild();
   while (lastTab.getNodeType() != Node.ELEMENT_NODE) {
     lastTab = lastTab.getPreviousSibling();
   }
   return Element.as(lastTab);
 }
예제 #3
0
  /**
   * Inserts a paragraph before or after the table containing the selection.
   *
   * <p>We decided to use Control/Meta+UpArrow for inserting a paragraph before a table and
   * Control/Meta+DownArrow for inserting a paragraph after a table. Here's the rationale:
   *
   * <ul>
   *   <li>We can't reliably detect if the user can place the caret before of after a table. Our
   *       playground is the DOM tree which we fully control but in the end the browser decides how
   *       to render each node. The table can have previous siblings or previous nodes in the DOM
   *       tree but they may not be rendered at all (as it happens with HTML garbage like empty
   *       elements) or not rendered before/after the table (as it happens with absolute positioned
   *       elements). So we have to insert the paragraph each time.
   *   <li>We can't use the same key to insert a paragraph before and after the table because we can
   *       have a table with just one empty cell. So we can't rely on the Enter key.
   *   <li>We can't use just the navigation keys because they would insert a paragraph before/after
   *       the table even when the user can navigate outside of the table.
   * </ul>
   *
   * We can replace the Ctrl with Alt. The idea is to use the Up/Down arrow keys with a modifier.
   * They will work form any table cell.
   *
   * @param event the native event that was fired
   * @param before {@code true} to insert a paragraph before the table, {@code false} to insert a
   *     paragraph after the table
   */
  protected void navigateOutsideTableCell(Event event, boolean before) {
    // Navigate only if the Control or Meta modifiers are pressed along with the Up/Down arrow keys.
    if (event.getAltKey() || event.getShiftKey() || !(event.getCtrlKey() ^ event.getMetaKey())) {
      return;
    }

    Selection selection = getTextArea().getDocument().getSelection();
    if (selection.getRangeCount() == 0) {
      return;
    } else {
      selection.collapseToStart();
    }

    Range range = selection.getRangeAt(0);
    Node ancestor = domUtils.getFirstAncestor(range.getStartContainer(), "table");
    if (ancestor == null) {
      return;
    }

    event.xPreventDefault();

    Document document = getTextArea().getDocument();
    Node paragraph = document.createPElement();
    paragraph.appendChild(document.createTextNode(""));

    if (before) {
      ancestor.getParentNode().insertBefore(paragraph, ancestor);
    } else {
      domUtils.insertAfter(paragraph, ancestor);
    }

    range.selectNodeContents(paragraph.getFirstChild());
    selection.removeAllRanges();
    selection.addRange(range);
  }
예제 #4
0
  /**
   * Overwrites the default rich text area behavior when the Tab key is being pressed.
   *
   * @param event the native event that was fired
   */
  protected void onTab(Event event) {
    Selection selection = getTextArea().getDocument().getSelection();
    if (selection.getRangeCount() == 0) {
      return;
    }

    // Prevent the default browser behavior.
    event.xPreventDefault();

    // See in which context the tab key has been pressed.
    Range range = selection.getRangeAt(0);
    List<String> specialTags = Arrays.asList(new String[] {LI, TD, TH});
    Node ancestor = range.getStartContainer();
    int index = specialTags.indexOf(ancestor.getNodeName().toLowerCase());
    while (ancestor != null && index < 0) {
      ancestor = ancestor.getParentNode();
      if (ancestor != null) {
        index = specialTags.indexOf(ancestor.getNodeName().toLowerCase());
      }
    }

    // Handle the tab key depending on the context.
    switch (index) {
      case 0:
        onTabInListItem(event, ancestor);
        break;
      case 1:
      case 2:
        onTabInTableCell(event, (TableCellElement) ancestor);
        break;
      default:
        onTabDefault(event);
        break;
    }
  }
예제 #5
0
  /**
   * Tab key has been pressed inside a table cell.
   *
   * @param event the native event that was fired
   * @param cell The table cell in which the tab key has been pressed.
   */
  protected void onTabInTableCell(Event event, TableCellElement cell) {
    Node nextCell = event.getShiftKey() ? cell.getPreviousCell() : cell.getNextCell();
    if (nextCell == null) {
      if (event.getShiftKey()) {
        return;
      } else {
        getTextArea().getCommandManager().execute(new Command("insertrowafter"));
        nextCell = cell.getNextCell();
      }
    }

    Selection selection = getTextArea().getDocument().getSelection();
    Range range = selection.getRangeAt(0);

    // Place the caret at the beginning of the next cell.
    Node leaf = domUtils.getFirstLeaf(nextCell);
    if (leaf == nextCell || leaf.getNodeType() == Node.TEXT_NODE) {
      range.setStart(leaf, 0);
    } else {
      range.setStartBefore(leaf);
    }

    range.collapse(true);
    selection.removeAllRanges();
    selection.addRange(range);
  }
 /**
  * @param parent the parent node
  * @param child the child node
  * @return the position of the child node within the array of children or -1 if there is no parent
  *     child relationship
  */
 public static int indexOf(Node parent, Node child) {
   for (int i = 0; i < parent.getChildCount(); i++) {
     if (child.equals(parent.getChild(i))) {
       return i;
     }
   }
   return -1;
 }
예제 #7
0
 @PatchMethod
 static Element getFirstChild(Element elem) {
   Node firstChild = elem.getFirstChildElement();
   if (firstChild != null) {
     return firstChild.cast();
   } else {
     return null;
   }
 }
예제 #8
0
 private void getEmptyPseudo(JsNodeArray previousMatch, JsNodeArray matchingElms) {
   Node previous;
   for (int q = 0, qlen = previousMatch.size(); q < qlen; q++) {
     previous = previousMatch.getNode(q);
     if (!previous.hasChildNodes()) {
       matchingElms.addNode(previous);
     }
   }
 }
예제 #9
0
  @Test
  public void is() {
    // Arrange
    NodeList<OptionElement> list = JavaScriptObjects.newNodeList();

    // Act & Assert
    assertFalse("null is not a DOM node", Node.is(null));
    assertFalse("NodeList is not a DOM node", Node.is(list));
    assertTrue("AnchorElement is a DOM node", Node.is(Document.get().createAnchorElement()));
  }
  /**
   * @param root the root node
   * @param node the node to start from
   * @return a list of nodes starting with the parent closest to the root and ending with the given
   *     node
   */
  private List<Node> getParents(Element root, Node node) {
    ArrayList<Node> result = new ArrayList<Node>();
    while ((node != null) && !node.equals(root)) {
      result.add(node);

      node = node.getParentNode();
    }
    Collections.reverse(result);
    return result;
  }
예제 #11
0
 private static void getSiblingNodes(
     JsNodeArray matchingElms, JsObjectArray<String> nextTag, JsRegexp nextRegExp, Node prevRef) {
   while (JsUtils.truth(prevRef = SelectorEngine.getNextSibling(prevRef))
       && prevRef.getNodeType() != Node.ELEMENT_NODE) {}
   if (JsUtils.truth(prevRef)) {
     if (!JsUtils.truth(nextTag) || nextRegExp.test(prevRef.getNodeName())) {
       matchingElms.addNode(prevRef);
     }
   }
 }
예제 #12
0
 private static void getDescendantNodes(
     JsNodeArray matchingElms, String nextTagStr, Node prevRef) {
   NodeList<Element> children = getElementsByTagName(nextTagStr, prevRef);
   for (int k = 0, klen = children.getLength(); k < klen; k++) {
     Node child = children.getItem(k);
     if (child.getParentNode() == prevRef) {
       matchingElms.addNode(child);
     }
   }
 }
예제 #13
0
  public void setTag(String category) {
    assert category != null;
    assert rootElement.getChild(1) != null;

    Node node = rootElement.getChild(1);
    node.removeAllChildren();
    Node text = JSFunctions.createTextNode(category);
    node.insertFirst(text);

    assert rootElement.getChild(1) != null;
    assert rootElement.getChild(1).getChild(0) != null;
  }
예제 #14
0
  @Test
  public void isOrHasChild_hasChild() {
    // Arrange
    Element a = Document.get().createAnchorElement();
    Element div = Document.get().createDivElement();

    div.appendChild(a);
    n.appendChild(div);

    // Act & Assert
    assertTrue(n.isOrHasChild(a));
  }
 /** {@inheritDoc} */
 @Override
 public void assertHealthy(ContentElement paragraph) {
   ContentView renderedContent = paragraph.getRenderedContentView();
   if (renderedContent.getFirstChild(paragraph) != null) {
     Node child = paragraph.getImplNodelet().getFirstChild();
     while (child != null) {
       assert !isSpacer(child) : "Non-empty paragraph should not have spacer";
       child = child.getNextSibling();
     }
   }
   super.assertHealthy(paragraph);
 }
예제 #16
0
  @Test
  public void getParentNode() {
    // Pre-Assert
    assertNull(n.getParentNode());

    // Arrange
    BaseElement be = Document.get().createBaseElement();
    n.appendChild(be);

    // Act & assert
    assertEquals(n, be.getParentNode());
  }
예제 #17
0
  @Test
  public void hasChildNodes() {
    // Pre-Assert
    assertFalse("New element should not have child nodes", n.hasChildNodes());

    // Arrange
    BaseElement be = Document.get().createBaseElement();
    n.appendChild(be);

    // Act & Assert
    assertTrue("Element should have a child node", n.hasChildNodes());
  }
예제 #18
0
  @Test
  public void nodeValue_Element() {
    // Arrange
    Node doucmentNode = Document.get().getDocumentElement();
    // Pre-Assert
    assertNull(doucmentNode.getNodeValue());

    // Act
    doucmentNode.setNodeValue("node");

    // Assert
    assertNull(doucmentNode.getNodeValue());
  }
예제 #19
0
 /** Improves splitter visibility. */
 private void tuneSplitter() {
   NodeList<Node> nodes = splitLayoutPanel.getElement().getChildNodes();
   for (int i = 0; i < nodes.getLength(); i++) {
     Node node = nodes.getItem(i);
     if (node.hasChildNodes()) {
       com.google.gwt.dom.client.Element el = node.getFirstChild().cast();
       if ("gwt-SplitLayoutPanel-HDragger".equals(el.getClassName())) {
         tuneSplitter(el);
         return;
       }
     }
   }
 }
예제 #20
0
  @Test
  public void getPreviousSibling() {
    // Pre-Assert
    assertNull(n.getPreviousSibling());

    // Arrange
    ButtonElement be0 = Document.get().createPushButtonElement();
    ButtonElement be1 = Document.get().createPushButtonElement();
    n.appendChild(be0);
    n.appendChild(be1);

    // Act & Assert
    assertEquals(be0, be1.getPreviousSibling());
  }
예제 #21
0
    private void commitPosition(int pos) {
      lastElementX_ = pos;

      // check to see if we're overlapping with another tab
      for (int i = 0; i < dragTabsHost_.getChildCount(); i++) {
        // skip non-element DOM nodes
        Node node = dragTabsHost_.getChild(i);
        if (node.getNodeType() != Node.ELEMENT_NODE) {
          continue;
        }

        // skip the current candidate (no point in testing it for swap)
        if (i == candidatePos_) {
          continue;
        }

        // skip the element we're dragging and elements that are not tabs
        Element ele = (Element) node;
        if (ele == dragElement_ || ele.getClassName().indexOf("gwt-TabLayoutPanelTab") < 0) {
          continue;
        }

        int left = DomUtils.leftRelativeTo(dragTabsHost_, ele);
        int right = left + ele.getClientWidth();
        int minOverlap = Math.min(initDragWidth_ / 2, ele.getClientWidth() / 2);

        // a little complicated: compute the number of overlapping pixels
        // with this element; if the overlap is more than half of our width
        // (or the width of the candidate), it's swapping time
        if (Math.min(lastElementX_ + initDragWidth_, right) - Math.max(lastElementX_, left)
            >= minOverlap) {
          dragTabsHost_.removeChild(dragPlaceholder_);
          if (candidatePos_ > i) {
            dragTabsHost_.insertBefore(dragPlaceholder_, ele);
          } else {
            dragTabsHost_.insertAfter(dragPlaceholder_, ele);
          }
          candidatePos_ = i;

          // account for the extra element when moving to the right of the
          // original location
          if (dragElement_ != null && startPos_ != null) {
            destPos_ = startPos_ <= candidatePos_ ? candidatePos_ - 1 : candidatePos_;
          } else {
            destPos_ = candidatePos_;
          }
        }
      }
    }
예제 #22
0
 @PatchMethod
 static void setNodeValue(Node node, String nodeValue) {
   switch (node.getNodeType()) {
     case Node.DOCUMENT_NODE:
       // nothing to do
       break;
     case Node.ELEMENT_NODE:
       // nothing to do
       break;
     case Node.TEXT_NODE:
       Text text = node.cast();
       text.setData(nodeValue);
       break;
   }
 }
예제 #23
0
 @PatchMethod
 static String getNodeValue(Node node) {
   switch (node.getNodeType()) {
     case Node.DOCUMENT_NODE:
       return null;
     case Node.ELEMENT_NODE:
       return null;
     case Node.TEXT_NODE:
       Text text = node.cast();
       return text.getData();
     default:
       throw new GwtTestDomException(
           "Invalid Node type (not a Document / Element / Text : " + node.getNodeType());
   }
 }
예제 #24
0
  @Test
  public void removeChild() {
    // Arrange
    BaseElement c0 = Document.get().createBaseElement();
    ButtonElement c1 = Document.get().createPushButtonElement();
    n.appendChild(c0);
    n.appendChild(c1);

    // Act
    n.removeChild(c1);

    // Assert
    assertEquals(1, n.getChildNodes().getLength());
    assertEquals(c0, n.getChildNodes().getItem(0));
  }
예제 #25
0
  @PatchMethod
  static Node getNextSibling(Node node) {
    Node parent = node.getParentNode();
    if (parent == null) return null;

    List<Node> list = getChildNodeList(parent);

    for (int i = 0; i < list.size(); i++) {
      Node current = list.get(i);
      if (current.equals(node) && i < list.size() - 1) {
        return list.get(i + 1);
      }
    }

    return null;
  }
예제 #26
0
  @Test
  public void isOrHasChild_notChild() {
    // Arrange
    Element a = Document.get().createAnchorElement();

    // Act & Assert
    assertFalse(n.isOrHasChild(a));
  }
예제 #27
0
  /**
   * Specific function which does not inspect deep.
   *
   * @param tag
   * @return
   */
  private static NodeList<Element> getElementByTagName(TableElement e, String tagName) {

    NodeList<Node> childs = e.getChildNodes();
    List<Element> list = new ArrayList<Element>();

    for (int i = 0; i < childs.getLength(); i++) {
      Node n = childs.getItem(i);
      if (Element.is(n)) {
        Element childElement = n.cast();
        if (tagName.equalsIgnoreCase(childElement.getTagName())) {
          list.add(childElement);
        }
      }
    }

    return JavaScriptObjects.newNodeList(list);
  }
예제 #28
0
 /**
  * @param container A block level element containing the start of the given range.
  * @param range A DOM range.
  * @return true if the start of the given range is at the beginning of its block level container.
  */
 protected boolean isAtStart(Node container, Range range) {
   if (!container.hasChildNodes()) {
     return true;
   }
   if (range.getStartOffset() > 0) {
     return false;
   }
   return domUtils.getFirstLeaf(container) == domUtils.getFirstLeaf(range.getStartContainer());
 }
예제 #29
0
  private static void setupChildNodes(Node newNode, Node oldNode, boolean deep) {

    List<Node> childs = getChildNodeList(oldNode);
    if (deep) {
      // copy all child nodes
      for (Node child : childs) {
        appendChild(newNode, cloneNode(child, true));
      }
    } else {
      // only copy the TextNode if exists
      for (Node child : childs) {
        if (Node.TEXT_NODE == child.getNodeType()) {
          appendChild(newNode, Document.get().createTextNode(child.getNodeValue()));
          break;
        }
      }
    }
  }
예제 #30
0
 @PatchMethod
 static String getNodeName(Node node) {
   switch (node.getNodeType()) {
     case Node.DOCUMENT_NODE:
       return "#document";
     case Node.ELEMENT_NODE:
       Element e = node.cast();
       return e.getTagName();
     case Node.TEXT_NODE:
       return "#text";
     case com.google.gwt.xml.client.Node.ATTRIBUTE_NODE:
       return JavaScriptObjects.getString(node, JsoProperties.XML_ATTR_NAME);
     default:
       throw new GwtTestDomException(
           "Invalid Node type (not a Document / Element / Text / Attribute) : "
               + node.getNodeType());
   }
 }