📄 range.cpp
字号:
ec = NOT_FOUND_ERR; return; } // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of // the Range is read-only. if (containedByReadOnly()) { ec = NO_MODIFICATION_ALLOWED_ERR; return; } // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were // not created from the same document. if (newNode->document() != m_start.container()->document()) { ec = WRONG_DOCUMENT_ERR; return; } // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that // does not allow children of the type of newNode or if newNode is an ancestor of the container. // an extra one here - if a text node is going to split, it must have a parent to insert into bool startIsText = m_start.container()->isTextNode(); if (startIsText && !m_start.container()->parentNode()) { ec = HIERARCHY_REQUEST_ERR; return; } // In the case where the container is a text node, we check against the container's parent, because // text nodes get split up upon insertion. Node* checkAgainst; if (startIsText) checkAgainst = m_start.container()->parentNode(); else checkAgainst = m_start.container(); Node::NodeType newNodeType = newNode->nodeType(); int numNewChildren; if (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) { // check each child node, not the DocumentFragment itself numNewChildren = 0; for (Node* c = newNode->firstChild(); c; c = c->nextSibling()) { if (!checkAgainst->childTypeAllowed(c->nodeType())) { ec = HIERARCHY_REQUEST_ERR; return; } ++numNewChildren; } } else { numNewChildren = 1; if (!checkAgainst->childTypeAllowed(newNodeType)) { ec = HIERARCHY_REQUEST_ERR; return; } } for (Node* n = m_start.container(); n; n = n->parentNode()) { if (n == newNode) { ec = HIERARCHY_REQUEST_ERR; return; } } // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node. if (newNodeType == Node::ATTRIBUTE_NODE || newNodeType == Node::ENTITY_NODE || newNodeType == Node::NOTATION_NODE || newNodeType == Node::DOCUMENT_NODE) { ec = RangeException::INVALID_NODE_TYPE_ERR; return; } bool collapsed = m_start == m_end; if (startIsText) { RefPtr<Text> newText = static_cast<Text*>(m_start.container())->splitText(m_start.offset(), ec); if (ec) return; m_start.container()->parentNode()->insertBefore(newNode.release(), newText.get(), ec); if (ec) return; // This special case doesn't seem to match the DOM specification, but it's currently required // to pass Acid3. We might later decide to remove this. if (collapsed) m_end.setToChild(newText.get()); } else { RefPtr<Node> lastChild; if (collapsed) lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode; int startOffset = m_start.offset(); m_start.container()->insertBefore(newNode.release(), m_start.container()->childNode(startOffset), ec); if (ec) return; // This special case doesn't seem to match the DOM specification, but it's currently required // to pass Acid3. We might later decide to remove this. if (collapsed) m_end.set(m_start.container(), startOffset + numNewChildren, lastChild.get()); }}String Range::toString(ExceptionCode& ec) const{ if (!m_start.container()) { ec = INVALID_STATE_ERR; return String(); } Vector<UChar> result; Node* pastLast = pastLastNode(); for (Node* n = firstNode(); n != pastLast; n = n->traverseNextNode()) { if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) { String data = static_cast<CharacterData*>(n)->data(); int length = data.length(); int start = (n == m_start.container()) ? min(max(0, m_start.offset()), length) : 0; int end = (n == m_end.container()) ? min(max(start, m_end.offset()), length) : length; result.append(data.characters() + start, end - start); } } return String::adopt(result);}String Range::toHTML() const{ return createMarkup(this);}String Range::text() const{ if (!m_start.container()) return String(); // We need to update layout, since plainText uses line boxes in the render tree. // FIXME: As with innerText, we'd like this to work even if there are no render objects. m_start.container()->document()->updateLayout(); return plainText(this);}PassRefPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionCode& ec) const{ if (!m_start.container()) { ec = INVALID_STATE_ERR; return 0; } Node* element = m_start.container()->isElementNode() ? m_start.container() : m_start.container()->parentNode(); if (!element || !element->isHTMLElement()) { ec = NOT_SUPPORTED_ERR; return 0; } RefPtr<DocumentFragment> fragment = static_cast<HTMLElement*>(element)->createContextualFragment(markup); if (!fragment) { ec = NOT_SUPPORTED_ERR; return 0; } return fragment.release();}void Range::detach(ExceptionCode& ec){ if (!m_start.container()) { ec = INVALID_STATE_ERR; return; } m_ownerDocument->detachRange(this); m_start.clear(); m_end.clear();}Node* Range::checkNodeWOffset(Node* n, int offset, ExceptionCode& ec) const{ switch (n->nodeType()) { case Node::DOCUMENT_TYPE_NODE: case Node::ENTITY_NODE: case Node::NOTATION_NODE: ec = RangeException::INVALID_NODE_TYPE_ERR; return 0; case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::TEXT_NODE: if (static_cast<unsigned>(offset) > static_cast<CharacterData*>(n)->length()) ec = INDEX_SIZE_ERR; return 0; case Node::PROCESSING_INSTRUCTION_NODE: if (static_cast<unsigned>(offset) > static_cast<ProcessingInstruction*>(n)->data().length()) ec = INDEX_SIZE_ERR; return 0; case Node::ATTRIBUTE_NODE: case Node::DOCUMENT_FRAGMENT_NODE: case Node::DOCUMENT_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_REFERENCE_NODE: case Node::XPATH_NAMESPACE_NODE: { if (!offset) return 0; Node* childBefore = n->childNode(offset - 1); if (!childBefore) ec = INDEX_SIZE_ERR; return childBefore; } } ASSERT_NOT_REACHED(); return 0;}void Range::checkNodeBA(Node* n, ExceptionCode& ec) const{ // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an // Attr, Document or DocumentFragment node or part of a shadow DOM tree // or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation node. switch (n->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::DOCUMENT_FRAGMENT_NODE: case Node::DOCUMENT_NODE: case Node::ENTITY_NODE: case Node::NOTATION_NODE: ec = RangeException::INVALID_NODE_TYPE_ERR; return; case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::DOCUMENT_TYPE_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_REFERENCE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::TEXT_NODE: case Node::XPATH_NAMESPACE_NODE: break; } Node* root = n; while (Node* parent = root->parentNode()) root = parent; switch (root->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::DOCUMENT_NODE: case Node::DOCUMENT_FRAGMENT_NODE: break; case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::DOCUMENT_TYPE_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_NODE: case Node::ENTITY_REFERENCE_NODE: case Node::NOTATION_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::TEXT_NODE: case Node::XPATH_NAMESPACE_NODE: if (root->isShadowNode()) break; ec = RangeException::INVALID_NODE_TYPE_ERR; return; }}PassRefPtr<Range> Range::cloneRange(ExceptionCode& ec) const{ if (!m_start.container()) { ec = INVALID_STATE_ERR; return 0; } return Range::create(m_ownerDocument, m_start.container(), m_start.offset(), m_end.container(), m_end.offset());}void Range::setStartAfter(Node* refNode, ExceptionCode& ec){ if (!m_start.container()) { ec = INVALID_STATE_ERR; return; } if (!refNode) { ec = NOT_FOUND_ERR; return; } if (refNode->document() != m_ownerDocument) { ec = WRONG_DOCUMENT_ERR; return; } ec = 0; checkNodeBA(refNode, ec); if (ec) return; setStart(refNode->parentNode(), refNode->nodeIndex() + 1, ec);}void Range::setEndBefore(Node* refNode, ExceptionCode& ec){ if (!m_start.container()) { ec = INVALID_STATE_ERR; return; } if (!refNode) { ec = NOT_FOUND_ERR; return; } if (refNode->document() != m_ownerDocument) { ec = WRONG_DOCUMENT_ERR; return; } ec = 0; checkNodeBA(refNode, ec); if (ec) return; setEnd(refNode->parentNode(), refNode->nodeIndex(), ec);}void Range::setEndAfter(Node* refNode, ExceptionCode& ec){ if (!m_start.container()) { ec = INVALID_STATE_ERR; return; } if (!refNode) { ec = NOT_FOUND_ERR; return; } if (refNode->document() != m_ownerDocument) { ec = WRONG_DOCUMENT_ERR; return; } ec = 0; checkNodeBA(refNode, ec); if (ec) return; setEnd(refNode->parentNode(), refNode->nodeIndex() + 1, ec);}void Range::selectNode(Node* refNode, ExceptionCode& ec){ if (!m_start.container()) { ec = INVALID_STATE_ERR; return; } if (!refNode) { ec = NOT_FOUND_ERR; return; } // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation // node. for (Node* anc = refNode->parentNode(); anc; anc = anc->parentNode()) { switch (anc->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::DOCUMENT_FRAGMENT_NODE: case Node::DOCUMENT_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_REFERENCE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::TEXT_NODE: case Node::XPATH_NAMESPACE_NODE: break; case Node::DOCUMENT_TYPE_NODE: case Node::ENTITY_NODE: case Node::NOTATION_NODE: ec = RangeException::INVALID_NODE_TYPE_ERR; return; } } switch (refNode->nodeType()) { case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::DOCUMENT_TYPE_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_REFERENCE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::TEXT_NODE: case Node::XPATH_NAMESPACE_NODE: break; case Node::ATTRIBUTE_NODE: case Node::DOCUMENT_FRAGMENT_NODE: case Node::DOCUMENT_NODE: case Node::ENTITY_NODE: case Node::NOTATION_NODE: ec = RangeException::INVALID_NODE_TYPE_ERR; return; } ec = 0; setStartBefore(refNode, ec); if (ec) return; setEndAfter(refNode, ec);}void Range::selectNodeContents(Node* refNode, ExceptionCode& ec){ if (!m_start.container()) { ec = INVALID_STATE_ERR; return; } if (!refNode) { ec = NOT_FOUND_ERR; return; } // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation // or DocumentType node. for (Node* n = refNode; n; n = n->parentNode()) { switch (n->nodeType()) { case Node::ATTRIBUTE_NODE: case Node::CDATA_SECTION_NODE: case Node::COMMENT_NODE: case Node::DOCUMENT_FRAGMENT_NODE: case Node::DOCUMENT_NODE: case Node::ELEMENT_NODE: case Node::ENTITY_REFERENCE_NODE: case Node::PROCESSING_INSTRUCTION_NODE: case Node::TEXT_NODE: case Node::XPATH_NAMESPACE_NODE: break; case Node::DOCUMENT_TYPE_NODE: case Node::ENTITY_NODE: case Node::NOTATION_NODE: ec = RangeException::INVALID_NODE_TYPE_ERR; return; } } m_start.setToStart(refNode); m_end.setToEnd(refNode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -