Пример #1
0
bool CaretBase::shouldRepaintCaret(Node& node) const {
    // If PositionAnchorType::BeforeAnchor or PositionAnchorType::AfterAnchor,
    // carets need to be repainted not only when the node is contentEditable but
    // also when its parentNode() is contentEditable.
    node.document().updateStyleAndLayoutTree();
    return hasEditableStyle(node) ||
           (node.parentNode() && hasEditableStyle(*node.parentNode()));
}
Пример #2
0
void InsertNodeBeforeCommand::doApply(EditingState*) {
  ContainerNode* parent = m_refChild->parentNode();
  document().updateStyleAndLayoutTree();
  if (!parent || (m_shouldAssumeContentIsAlwaysEditable ==
                      DoNotAssumeContentIsAlwaysEditable &&
                  !hasEditableStyle(*parent)))
    return;
  DCHECK(hasEditableStyle(*parent)) << parent;

  parent->insertBefore(m_insertChild.get(), m_refChild.get(), IGNORE_EXCEPTION);
}
Пример #3
0
bool SVGAElement::canStartSelection() const
{
    if (!isLink())
        return SVGElement::canStartSelection();

    return hasEditableStyle();
}
Пример #4
0
void HTMLAnchorElement::defaultEventHandler(Event* event)
{
    if (isLink()) {
        if (focused() && isEnterKeyKeydownEvent(event) && treatLinkAsLiveForEventType(NonMouseEvent)) {
            event->setDefaultHandled();
            dispatchSimulatedClick(event);
            return;
        }

        if (isLinkClick(event) && treatLinkAsLiveForEventType(eventType(event))) {
            handleClick(event);
            return;
        }

        if (hasEditableStyle()) {
            // This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked
            // for the LiveWhenNotFocused editable link behavior
            if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && toMouseEvent(event)->button() != RightButton && document().frame()) {
                setRootEditableElementForSelectionOnMouseDown(document().frame()->selection().selection().rootEditableElement());
                m_wasShiftKeyDownOnMouseDown = toMouseEvent(event)->shiftKey();
            } else if (event->type() == eventNames().mouseoverEvent) {
                // These are cleared on mouseover and not mouseout because their values are needed for drag events,
                // but drag events happen after mouse out events.
                clearRootEditableElementForSelectionOnMouseDown();
                m_wasShiftKeyDownOnMouseDown = false;
            }
        }
    }

    HTMLElement::defaultEventHandler(event);
}
Пример #5
0
void InsertNodeBeforeCommand::doUnapply() {
  document().updateStyleAndLayoutTree();
  if (!hasEditableStyle(*m_insertChild))
    return;

  m_insertChild->remove(IGNORE_EXCEPTION);
}
Пример #6
0
bool HTMLAnchorElement::treatLinkAsLiveForEventType(EventType eventType) const
{
    if (!hasEditableStyle())
        return true;

    Settings* settings = document().settings();
    if (!settings)
        return true;

    switch (settings->editableLinkBehavior()) {
    case EditableLinkDefaultBehavior:
    case EditableLinkAlwaysLive:
        return true;

    case EditableLinkNeverLive:
        return false;

    // If the selection prior to clicking on this link resided in the same editable block as this link,
    // and the shift key isn't pressed, we don't want to follow the link.
    case EditableLinkLiveWhenNotFocused:
        return eventType == MouseEventWithShiftKey || (eventType == MouseEventWithoutShiftKey && rootEditableElementForSelectionOnMouseDown() != rootEditableElement());

    case EditableLinkOnlyLiveWithShiftKey:
        return eventType == MouseEventWithShiftKey;
    }

    ASSERT_NOT_REACHED();
    return false;
}
Пример #7
0
void InsertIntoTextNodeCommand::doUnapply() {
  if (!hasEditableStyle(*m_node))
    return;

  m_node->deleteData(m_offset, m_text.length(), IGNORE_EXCEPTION);
  document().updateStyleAndLayout();
}
Пример #8
0
void HTMLAnchorElement::setActive(bool down, bool pause)
{
    if (hasEditableStyle()) {
        EditableLinkBehavior editableLinkBehavior = EditableLinkDefaultBehavior;
        if (Settings* settings = document().settings())
            editableLinkBehavior = settings->editableLinkBehavior();
            
        switch (editableLinkBehavior) {
            default:
            case EditableLinkDefaultBehavior:
            case EditableLinkAlwaysLive:
                break;

            case EditableLinkNeverLive:
                return;

            // Don't set the link to be active if the current selection is in the same editable block as
            // this link
            case EditableLinkLiveWhenNotFocused:
                if (down && document().frame() && document().frame()->selection().selection().rootEditableElement() == rootEditableElement())
                    return;
                break;
            
            case EditableLinkOnlyLiveWithShiftKey:
                return;
        }

    }
    
    HTMLElement::setActive(down, pause);
}
Пример #9
0
void SplitElementCommand::executeApply() {
  if (m_atChild->parentNode() != m_element2)
    return;

  HeapVector<Member<Node>> children;
  for (Node* node = m_element2->firstChild(); node != m_atChild;
       node = node->nextSibling())
    children.append(node);

  DummyExceptionStateForTesting exceptionState;

  ContainerNode* parent = m_element2->parentNode();
  if (!parent || !hasEditableStyle(*parent))
    return;
  parent->insertBefore(m_element1.get(), m_element2.get(), exceptionState);
  if (exceptionState.hadException())
    return;

  // Delete id attribute from the second element because the same id cannot be
  // used for more than one element
  m_element2->removeAttribute(HTMLNames::idAttr);

  for (const auto& child : children)
    m_element1->appendChild(child, exceptionState);
}
Пример #10
0
bool HTMLAnchorElement::supportsFocus() const
{
    if (hasEditableStyle())
        return HTMLElement::supportsFocus();
    // If not a link we should still be able to focus the element if it has tabIndex.
    return isLink() || HTMLElement::supportsFocus();
}
Пример #11
0
bool SVGAElement::supportsFocus() const
{
    if (hasEditableStyle())
        return SVGGraphicsElement::supportsFocus();
    // If not a link we should still be able to focus the element if it has a tabIndex.
    return isLink() || Element::supportsFocus();
}
void WrapContentsInDummySpanCommand::doReapply() {
  DCHECK(m_element);

  if (!m_dummySpan || !hasEditableStyle(*m_element))
    return;

  executeApply();
}
Пример #13
0
void DeleteFromTextNodeCommand::doUnapply() {
  DCHECK(m_node);

  if (!hasEditableStyle(*m_node))
    return;

  m_node->insertData(m_offset, m_text, IGNORE_EXCEPTION);
  m_node->document().updateStyleAndLayout();
}
Пример #14
0
void SplitElementCommand::doUnapply() {
  if (!m_element1 || !hasEditableStyle(*m_element1) ||
      !hasEditableStyle(*m_element2))
    return;

  NodeVector children;
  getChildNodes(*m_element1, children);

  Node* refChild = m_element2->firstChild();

  for (const auto& child : children)
    m_element2->insertBefore(child, refChild, IGNORE_EXCEPTION);

  // Recover the id attribute of the original element.
  const AtomicString& id = m_element1->getAttribute(HTMLNames::idAttr);
  if (!id.isNull())
    m_element2->setAttribute(HTMLNames::idAttr, id);

  m_element1->remove(IGNORE_EXCEPTION);
}
void WrapContentsInDummySpanCommand::doUnapply() {
  DCHECK(m_element);

  if (!m_dummySpan || !hasEditableStyle(*m_element))
    return;

  NodeVector children;
  getChildNodes(*m_dummySpan, children);

  for (auto& child : children)
    m_element->appendChild(child.release(), IGNORE_EXCEPTION);

  m_dummySpan->remove(IGNORE_EXCEPTION);
}
Пример #16
0
void DeleteFromTextNodeCommand::doApply(EditingState*) {
  DCHECK(m_node);

  document().updateStyleAndLayoutTree();
  if (!hasEditableStyle(*m_node))
    return;

  TrackExceptionState exceptionState;
  m_text = m_node->substringData(m_offset, m_count, exceptionState);
  if (exceptionState.hadException())
    return;

  m_node->deleteData(m_offset, m_count, exceptionState);
  m_node->document().updateStyleAndLayout();
}
Пример #17
0
InsertNodeBeforeCommand::InsertNodeBeforeCommand(
    Node* insertChild,
    Node* refChild,
    ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
    : SimpleEditCommand(refChild->document()),
      m_insertChild(insertChild),
      m_refChild(refChild),
      m_shouldAssumeContentIsAlwaysEditable(
          shouldAssumeContentIsAlwaysEditable) {
  DCHECK(m_insertChild);
  DCHECK(!m_insertChild->parentNode()) << m_insertChild;
  DCHECK(m_refChild);
  DCHECK(m_refChild->parentNode()) << m_refChild;

  DCHECK(hasEditableStyle(*m_refChild->parentNode()) ||
         !m_refChild->parentNode()->inActiveDocument())
      << m_refChild->parentNode();
}
Пример #18
0
void InsertIntoTextNodeCommand::doApply(EditingState*) {
  bool passwordEchoEnabled =
      document().settings() && document().settings()->passwordEchoEnabled();
  if (passwordEchoEnabled)
    document().updateStyleAndLayoutIgnorePendingStylesheets();

  if (!hasEditableStyle(*m_node))
    return;

  if (passwordEchoEnabled) {
    LayoutText* layoutText = m_node->layoutObject();
    if (layoutText && layoutText->isSecure())
      layoutText->momentarilyRevealLastTypedCharacter(m_offset +
                                                      m_text.length() - 1);
  }

  m_node->insertData(m_offset, m_text, IGNORE_EXCEPTION);
  document().updateStyleAndLayout();
}
void RemoveNodePreservingChildrenCommand::doApply(EditingState* editingState) {
  ABORT_EDITING_COMMAND_IF(!m_node->parentNode());
  ABORT_EDITING_COMMAND_IF(!hasEditableStyle(*m_node->parentNode()));
  if (m_node->isContainerNode()) {
    NodeVector children;
    getChildNodes(toContainerNode(*m_node), children);

    for (auto& currentChild : children) {
      Node* child = currentChild.release();
      removeNode(child, editingState, m_shouldAssumeContentIsAlwaysEditable);
      if (editingState->isAborted())
        return;
      insertNodeBefore(child, m_node, editingState,
                       m_shouldAssumeContentIsAlwaysEditable);
      if (editingState->isAborted())
        return;
    }
  }
  removeNode(m_node, editingState, m_shouldAssumeContentIsAlwaysEditable);
}
void SplitTextNodeContainingElementCommand::doApply(EditingState*) {
  DCHECK(m_text);
  DCHECK_GT(m_offset, 0);

  splitTextNode(m_text.get(), m_offset);

  Element* parent = m_text->parentElement();
  if (!parent || !parent->parentElement() ||
      !hasEditableStyle(*parent->parentElement()))
    return;

  LayoutObject* parentLayoutObject = parent->layoutObject();
  if (!parentLayoutObject || !parentLayoutObject->isInline()) {
    wrapContentsInDummySpan(parent);
    Node* firstChild = parent->firstChild();
    if (!firstChild || !firstChild->isElementNode())
      return;
    parent = toElement(firstChild);
  }

  splitElement(parent, m_text.get());
}
Пример #21
0
AtomicString getInputModeAttribute(Element* element) {
  if (!element)
    return AtomicString();

  bool queryAttribute = false;
  if (isHTMLInputElement(*element)) {
    queryAttribute = toHTMLInputElement(*element).supportsInputModeAttribute();
  } else if (isHTMLTextAreaElement(*element)) {
    queryAttribute = true;
  } else {
    element->document().updateStyleAndLayoutTree();
    if (hasEditableStyle(*element))
      queryAttribute = true;
  }

  if (!queryAttribute)
    return AtomicString();

  // TODO(dtapuska): We may wish to restrict this to a yet to be proposed
  // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016.
  return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
}
Пример #22
0
bool HTMLAnchorElement::canStartSelection() const
{
    return hasEditableStyle();
}
Пример #23
0
bool HTMLAnchorElement::isLiveLink() const
{
    return !hasEditableStyle();
}
Пример #24
0
bool HTMLAnchorElement::supportsFocus() const
{
    if (hasEditableStyle())
        return HTMLElement::supportsFocus();
    return true;
}
Пример #25
0
bool HTMLAnchorElement::canStartSelection() const
{
    if (!isLink())
        return HTMLElement::canStartSelection();
    return hasEditableStyle();
}
bool HTMLBodyElement::supportsFocus() const
{
    // This override is needed because the inherited method bails if the parent is editable.
    // The <body> should be focusable even if <html> is editable.
    return hasEditableStyle() || HTMLElement::supportsFocus();
}
Пример #27
0
void CaretBase::invalidateCaretRect(Node* node) {
    node->document().updateStyleAndLayoutTree();
    if (hasEditableStyle(*node))
        invalidateLocalCaretRect(node, localCaretRectWithoutUpdate());
}