📄 element.cpp
字号:
lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState()) lastElementBeforeInsertion->setChanged(); // We also have to handle node removal. The parser callback case is similar to node removal as well in that we need to change the last child // to match now. if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState()) newLastChild->setChanged(); } // The + selector. We need to invalidate the first element following the insertion point. It is the only possible element // that could be affected by this DOM change. if (style->childrenAffectedByDirectAdjacentRules() && afterChange) { Node* firstElementAfterInsertion = 0; for (firstElementAfterInsertion = afterChange; firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode(); firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {}; if (firstElementAfterInsertion && firstElementAfterInsertion->attached()) firstElementAfterInsertion->setChanged(); } // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type. // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type. // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the // backward case. // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to. // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids // here. recalcStyle will then force a walk of the children when it sees that this has happened. if ((style->childrenAffectedByForwardPositionalRules() && afterChange) || (style->childrenAffectedByBackwardPositionalRules() && beforeChange)) e->setChanged(); // :empty selector. if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes())) e->setChanged();}void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta){ ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); if (!changedByParser) checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);}void Element::finishParsingChildren(){ ContainerNode::finishParsingChildren(); m_parsingChildrenFinished = true; checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);}void Element::dispatchAttrRemovalEvent(Attribute*){ ASSERT(!eventDispatchForbidden());#if 0 if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER)) return; ExceptionCode ec = 0; dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(), attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);#endif}void Element::dispatchAttrAdditionEvent(Attribute*){ ASSERT(!eventDispatchForbidden());#if 0 if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER)) return; ExceptionCode ec = 0; dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(), attr->value(),document()->attrName(attr->id()), MutationEvent::ADDITION), ec);#endif}String Element::openTagStartToString() const{ String result = "<" + nodeName(); NamedAttrMap *attrMap = attributes(true); if (attrMap) { unsigned numAttrs = attrMap->length(); for (unsigned i = 0; i < numAttrs; i++) { result += " "; Attribute *attribute = attrMap->attributeItem(i); result += attribute->name().toString(); if (!attribute->value().isNull()) { result += "=\""; // FIXME: substitute entities for any instances of " or ' result += attribute->value(); result += "\""; } } } return result;}void Element::updateId(const AtomicString& oldId, const AtomicString& newId){ if (!inDocument()) return; if (oldId == newId) return; Document* doc = document(); if (!oldId.isEmpty()) doc->removeElementById(oldId, this); if (!newId.isEmpty()) doc->addElementById(newId, this);}#ifndef NDEBUGvoid Element::formatForDebugger(char* buffer, unsigned length) const{ String result; String s; s = nodeName(); if (s.length() > 0) { result += s; } s = getAttribute(idAttr); if (s.length() > 0) { if (result.length() > 0) result += "; "; result += "id="; result += s; } s = getAttribute(classAttr); if (s.length() > 0) { if (result.length() > 0) result += "; "; result += "class="; result += s; } strncpy(buffer, result.utf8().data(), length - 1);}#endifPassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec){ if (!attr) { ec = TYPE_MISMATCH_ERR; return 0; } return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));}PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec){ if (!attr) { ec = TYPE_MISMATCH_ERR; return 0; } return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));}PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec){ if (!attr) { ec = TYPE_MISMATCH_ERR; return 0; } if (attr->ownerElement() != this) { ec = NOT_FOUND_ERR; return 0; } if (document() != attr->document()) { ec = WRONG_DOCUMENT_ERR; return 0; } NamedAttrMap *attrs = attributes(true); if (!attrs) return 0; return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));}void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec){ String prefix, localName; if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec)) return; QualifiedName qName(prefix, localName, namespaceURI); setAttribute(qName, value, ec);}void Element::removeAttribute(const String& name, ExceptionCode& ec){ String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; if (namedAttrMap) { namedAttrMap->removeNamedItem(localName, ec); if (ec == NOT_FOUND_ERR) ec = 0; }}void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec){ removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);}PassRefPtr<Attr> Element::getAttributeNode(const String& name){ NamedAttrMap* attrs = attributes(true); if (!attrs) return 0; String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; return static_pointer_cast<Attr>(attrs->getNamedItem(localName));}PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName){ NamedAttrMap* attrs = attributes(true); if (!attrs) return 0; return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));}bool Element::hasAttribute(const String& name) const{ NamedAttrMap* attrs = attributes(true); if (!attrs) return false; // This call to String::lower() seems to be required but // there may be a way to remove it. String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; return attrs->getAttributeItem(localName, false);}bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const{ NamedAttrMap* attrs = attributes(true); if (!attrs) return false; return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));}CSSStyleDeclaration *Element::style(){ return 0;}void Element::focus(bool restorePreviousSelection){ Document* doc = document(); if (doc->focusedNode() == this) return; doc->updateLayoutIgnorePendingStylesheets(); if (!supportsFocus()) return; if (Page* page = doc->page()) page->focusController()->setFocusedNode(this, doc->frame()); if (!isFocusable()) { ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true); return; } cancelFocusAppearanceUpdate(); updateFocusAppearance(restorePreviousSelection);}void Element::updateFocusAppearance(bool /*restorePreviousSelection*/){ if (this == rootEditableElement()) { Frame* frame = document()->frame(); if (!frame) return; // FIXME: We should restore the previous selection if there is one. VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this); if (frame->shouldChangeSelection(newSelection)) { frame->selection()->setSelection(newSelection); frame->revealSelection(); } } // FIXME: I'm not sure all devices will want this off, but this is // currently turned off for Andriod.#if !ENABLE(DIRECTIONAL_PAD_NAVIGATION) else if (renderer() && !renderer()->isWidget()) renderer()->enclosingLayer()->scrollRectToVisible(getRect());#endif}void Element::blur(){ cancelFocusAppearanceUpdate(); Document* doc = document(); if (doc->focusedNode() == this) { if (doc->frame()) doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame()); else doc->setFocusedNode(0); }}String Element::innerText() const{ // We need to update layout, since plainText uses line boxes in the render tree. document()->updateLayoutIgnorePendingStylesheets(); if (!renderer()) return textContent(true); return plainText(rangeOfContents(const_cast<Element*>(this)).get());}String Element::outerText() const{ // Getting outerText is the same as getting innerText, only // setting is different. You would think this should get the plain // text for the outer range, but this is wrong, <br> for instance // would return different values for inner and outer text by such // a rule, but it doesn't in WinIE, and we want to match that. return innerText();}String Element::title() const{ return String();}IntSize Element::minimumSizeForResizing() const{ return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();}void Element::setMinimumSizeForResizing(const IntSize& size){ if (size == defaultMinimumSizeForResizing() && !hasRareData()) return; ensureRareData()->m_minimumSizeForResizing = size;}RenderStyle* Element::computedStyle(){ if (RenderStyle* usedStyle = renderStyle()) return usedStyle; if (!attached()) // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the // document tree and figure out when to destroy the computed style for such elements. return 0; ElementRareData* data = ensureRareData(); if (!data->m_computedStyle) data->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0); return data->m_computedStyle.get();}void Element::cancelFocusAppearanceUpdate(){ if (hasRareData()) rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false); if (document()->focusedNode() == this) document()->cancelFocusAppearanceUpdate();}void Element::normalizeAttributes(){ // Normalize attributes. NamedAttrMap* attrs = attributes(true); if (!attrs) return; unsigned numAttrs = attrs->length(); for (unsigned i = 0; i < numAttrs; i++) { if (Attr* attr = attrs->attributeItem(i)->attr()) attr->normalize(); }}// ElementTraversal APIElement* Element::firstElementChild() const{ Node* n = firstChild(); while (n && !n->isElementNode()) n = n->nextSibling(); return static_cast<Element*>(n);}Element* Element::lastElementChild() const{ Node* n = lastChild(); while (n && !n->isElementNode()) n = n->previousSibling(); return static_cast<Element*>(n);}Element* Element::previousElementSibling() const{ Node* n = previousSibling(); while (n && !n->isElementNode()) n = n->previousSibling(); return static_cast<Element*>(n);}Element* Element::nextElementSibling() const{ Node* n = nextSibling(); while (n && !n->isElementNode()) n = n->nextSibling(); return static_cast<Element*>(n);}unsigned Element::childElementCount() const{ unsigned count = 0; Node* n = firstChild(); while (n) { count += n->isElementNode(); n = n->nextSibling(); } return count;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -