📄 node.cpp
字号:
if (this == stayWithin) return 0; if (previousSibling()) return previousSibling(); const Node *n = this; while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin)) n = n->parentNode(); if (n) return n->previousSibling(); return 0;}void Node::checkSetPrefix(const AtomicString&, ExceptionCode& ec){ // Perform error checking as required by spec for setting Node.prefix. Used by // Element::setPrefix() and Attr::setPrefix() // FIXME: Implement support for INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character. // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly. if (isReadOnlyNode()) { ec = NO_MODIFICATION_ALLOWED_ERR; return; } // FIXME: Implement NAMESPACE_ERR: - Raised if the specified prefix is malformed // We have to comment this out, since it's used for attributes and tag names, and we've only // switched one over. /* // - if the namespaceURI of this node is null, // - if the specified prefix is "xml" and the namespaceURI of this node is different from // "http://www.w3.org/XML/1998/namespace", // - if this node is an attribute and the specified prefix is "xmlns" and // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/", // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces]. if ((namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) || (_prefix == "xml" && String(document()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) { ec = NAMESPACE_ERR; return; }*/}bool Node::canReplaceChild(Node* newChild, Node*){ if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) { if (!childTypeAllowed(newChild->nodeType())) return false; } else { for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) { if (!childTypeAllowed(n->nodeType())) return false; } } return true;}void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec){ // Perform error checking as required by spec for adding a new child. Used by // appendChild(), replaceChild() and insertBefore() // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null if (!newChild) { ec = NOT_FOUND_ERR; return; } // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly if (isReadOnlyNode()) { ec = NO_MODIFICATION_ALLOWED_ERR; return; } bool shouldAdoptChild = false; // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that // created this node. // We assume that if newChild is a DocumentFragment, all children are created from the same document // as the fragment itself (otherwise they could not have been added as children) if (newChild->document() != document()) { // but if the child is not in a document yet then loosen the // restriction, so that e.g. creating an element with the Option() // constructor and then adding it to a different document works, // as it does in Mozilla and Mac IE. if (!newChild->inDocument()) { shouldAdoptChild = true; } else { ec = WRONG_DOCUMENT_ERR; return; } } // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the // newChild node, or if the node to append is one of this node's ancestors. // check for ancestor/same node if (newChild == this || isDescendantOf(newChild)) { ec = HIERARCHY_REQUEST_ERR; return; } if (!canReplaceChild(newChild, oldChild)) { ec = HIERARCHY_REQUEST_ERR; return; } // change the document pointer of newChild and all of its children to be the new document if (shouldAdoptChild) for (Node* node = newChild; node; node = node->traverseNextNode(newChild)) node->setDocument(document());}void Node::checkAddChild(Node *newChild, ExceptionCode& ec){ // Perform error checking as required by spec for adding a new child. Used by // appendChild(), replaceChild() and insertBefore() // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null if (!newChild) { ec = NOT_FOUND_ERR; return; } // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly if (isReadOnlyNode()) { ec = NO_MODIFICATION_ALLOWED_ERR; return; } bool shouldAdoptChild = false; // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that // created this node. // We assume that if newChild is a DocumentFragment, all children are created from the same document // as the fragment itself (otherwise they could not have been added as children) if (newChild->document() != document()) { // but if the child is not in a document yet then loosen the // restriction, so that e.g. creating an element with the Option() // constructor and then adding it to a different document works, // as it does in Mozilla and Mac IE. if (!newChild->inDocument()) { shouldAdoptChild = true; } else { ec = WRONG_DOCUMENT_ERR; return; } } // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the // newChild node, or if the node to append is one of this node's ancestors. // check for ancestor/same node if (newChild == this || isDescendantOf(newChild)) { ec = HIERARCHY_REQUEST_ERR; return; } if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) { if (!childTypeAllowed(newChild->nodeType())) { ec = HIERARCHY_REQUEST_ERR; return; } } else { for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) { if (!childTypeAllowed(n->nodeType())) { ec = HIERARCHY_REQUEST_ERR; return; } } } // change the document pointer of newChild and all of its children to be the new document if (shouldAdoptChild) for (Node* node = newChild; node; node = node->traverseNextNode(newChild)) node->setDocument(document());}bool Node::isDescendantOf(const Node *other) const{ // Return true if other is an ancestor of this, otherwise false if (!other) return false; for (const Node *n = parentNode(); n; n = n->parentNode()) { if (n == other) return true; } return false;}bool Node::contains(const Node* node) const{ if (!node) return false; return this == node || node->isDescendantOf(this);}bool Node::childAllowed(Node* newChild){ return childTypeAllowed(newChild->nodeType());}void Node::attach(){ ASSERT(!attached()); ASSERT(!renderer() || (renderer()->style() && renderer()->parent())); // If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the // result of Text::rendererIsNeeded() for those nodes. if (renderer()) { for (Node* next = nextSibling(); next; next = next->nextSibling()) { if (next->renderer()) break; if (!next->attached()) break; // Assume this means none of the following siblings are attached. if (next->isTextNode()) next->createRendererIfNeeded(); } } m_attached = true;}void Node::willRemove(){}void Node::detach(){ m_inDetach = true; if (renderer()) renderer()->destroy(); setRenderer(0); Document* doc = document(); if (m_hovered) doc->hoveredNodeDetached(this); if (m_inActiveChain) doc->activeChainNodeDetached(this); m_active = false; m_hovered = false; m_inActiveChain = false; m_attached = false; m_inDetach = false;}Node *Node::previousEditable() const{ Node *node = previousLeafNode(); while (node) { if (node->isContentEditable()) return node; node = node->previousLeafNode(); } return 0;}Node *Node::nextEditable() const{ Node *node = nextLeafNode(); while (node) { if (node->isContentEditable()) return node; node = node->nextLeafNode(); } return 0;}RenderObject * Node::previousRenderer(){ for (Node *n = previousSibling(); n; n = n->previousSibling()) { if (n->renderer()) return n->renderer(); } return 0;}RenderObject * Node::nextRenderer(){ // Avoid an O(n^2) problem with this function by not checking for nextRenderer() when the parent element hasn't even // been attached yet. if (parent() && !parent()->attached()) return 0; for (Node *n = nextSibling(); n; n = n->nextSibling()) { if (n->renderer()) return n->renderer(); } return 0;}// FIXME: This code is used by editing. Seems like it could move over there and not pollute Node.Node *Node::previousNodeConsideringAtomicNodes() const{ if (previousSibling()) { Node *n = previousSibling(); while (!isAtomicNode(n) && n->lastChild()) n = n->lastChild(); return n; } else if (parentNode()) { return parentNode(); } else { return 0; }}Node *Node::nextNodeConsideringAtomicNodes() const{ if (!isAtomicNode(this) && firstChild()) return firstChild(); if (nextSibling()) return nextSibling(); const Node *n = this; while (n && !n->nextSibling()) n = n->parentNode(); if (n) return n->nextSibling(); return 0;}Node *Node::previousLeafNode() const{ Node *node = previousNodeConsideringAtomicNodes(); while (node) { if (isAtomicNode(node)) return node; node = node->previousNodeConsideringAtomicNodes(); } return 0;}Node *Node::nextLeafNode() const{ Node *node = nextNodeConsideringAtomicNodes(); while (node) { if (isAtomicNode(node)) return node; node = node->nextNodeConsideringAtomicNodes(); } return 0;}void Node::createRendererIfNeeded(){ if (!document()->shouldCreateRenderers()) return; ASSERT(!renderer()); Node* parent = parentNode(); ASSERT(parent); RenderObject* parentRenderer = parent->renderer(); if (parentRenderer && parentRenderer->canHaveChildren()#if ENABLE(SVG) && parent->childShouldCreateRenderer(this)#endif ) { RefPtr<RenderStyle> style = styleForRenderer(); if (rendererIsNeeded(style.get())) { if (RenderObject* r = createRenderer(document()->renderArena(), style.get())) { if (!parentRenderer->isChildAllowed(r, style.get())) r->destroy(); else { setRenderer(r); renderer()->setAnimatableStyle(style.release()); parentRenderer->addChild(renderer(), nextRenderer()); } } } }}PassRefPtr<RenderStyle> Node::styleForRenderer(){ if (isElementNode()) return document()->styleSelector()->styleForElement(static_cast<Element*>(this)); return parentNode() && parentNode()->renderer() ? parentNode()->renderer()->style() : 0;}bool Node::rendererIsNeeded(RenderStyle *style){ return (document()->documentElement() == this) || (style->display() != NONE);}RenderObject* Node::createRenderer(RenderArena*, RenderStyle*){ ASSERT(false); return 0;} RenderStyle* Node::nonRendererRenderStyle() const{ return 0; } void Node::setRenderStyle(PassRefPtr<RenderStyle> s){ if (m_renderer) m_renderer->setAnimatableStyle(s); }RenderStyle* Node::computedStyle(){ return parent() ? parent()->computedStyle() : 0;}int Node::maxCharacterOffset() const{ ASSERT_NOT_REACHED(); return 0;}// FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class// is obviously misplaced.bool Node::canStartSelection() const{ if (isContentEditable()) return true; return parent() ? parent()->canStartSelection() : true;}Node* Node::shadowAncestorNode(){#if ENABLE(SVG) // SVG elements living in a shadow tree only occour when <use> created them. // For these cases we do NOT want to return the shadowParentNode() here // but the actual shadow tree element - as main difference to the HTML forms // shadow tree concept. (This function _could_ be made virtual - opinions?) if (isSVGElement()) return this;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -