2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Peter Kelly (pmk@post.com)
5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * (C) 2007 David Smith (catfish.man@gmail.com)
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
8 * (C) 2007 Eric Seidel (eric@webkit.org)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
29 #include "AXObjectCache.h"
30 #include "CSSStyleSelector.h"
32 #include "ClientRect.h"
33 #include "ClientRectList.h"
36 #include "ElementRareData.h"
37 #include "ExceptionCode.h"
38 #include "FocusController.h"
40 #include "FrameView.h"
41 #include "HTMLElement.h"
42 #include "HTMLNames.h"
43 #include "NamedAttrMap.h"
45 #include "NodeRenderStyle.h"
47 #include "PlatformString.h"
48 #include "RenderBlock.h"
52 #include "SelectionController.h"
53 #include "TextIterator.h"
58 using namespace HTMLNames;
59 using namespace XMLNames;
61 Element::Element(const QualifiedName& tagName, Document* doc)
62 : ContainerNode(doc, true)
70 namedAttrMap->detachFromElement();
73 inline ElementRareData* Element::rareData() const
75 ASSERT(hasRareData());
76 return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
79 inline ElementRareData* Element::ensureRareData()
81 return static_cast<ElementRareData*>(Node::ensureRareData());
84 NodeRareData* Element::createRareData()
86 return new ElementRareData;
89 PassRefPtr<Node> Element::cloneNode(bool deep)
91 RefPtr<Element> clone = document()->createElement(tagQName(), false);
92 // This will catch HTML elements in the wrong namespace that are not correctly copied.
93 // This is a sanity check as HTML overloads some of the DOM methods.
94 ASSERT(isHTMLElement() == clone->isHTMLElement());
98 clone->attributes()->setAttributes(*namedAttrMap);
100 clone->copyNonAttributeProperties(this);
103 cloneChildNodes(clone.get());
105 return clone.release();
108 PassRefPtr<Element> Element::cloneElement()
110 return static_pointer_cast<Element>(cloneNode(false));
113 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
116 namedAttrMap->removeNamedItem(name, ec);
117 if (ec == NOT_FOUND_ERR)
122 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
125 setAttribute(name, value, ec);
128 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
131 setAttribute(name, name.localName());
134 removeAttribute(name, ex);
138 // Virtual function, defined in base class.
139 NamedAttrMap* Element::attributes() const
141 return attributes(false);
144 NamedAttrMap* Element::attributes(bool readonly) const
146 if (!m_isStyleAttributeValid)
147 updateStyleAttribute();
150 if (!m_areSVGAttributesValid)
151 updateAnimatedSVGAttribute(String());
154 if (!readonly && !namedAttrMap)
155 createAttributeMap();
156 return namedAttrMap.get();
159 Node::NodeType Element::nodeType() const
164 const AtomicString& Element::getIDAttribute() const
166 return namedAttrMap ? namedAttrMap->id() : nullAtom;
169 bool Element::hasAttribute(const QualifiedName& name) const
171 return hasAttributeNS(name.namespaceURI(), name.localName());
174 const AtomicString& Element::getAttribute(const QualifiedName& name) const
176 if (name == styleAttr && !m_isStyleAttributeValid)
177 updateStyleAttribute();
180 if (!m_areSVGAttributesValid)
181 updateAnimatedSVGAttribute(name.localName());
185 if (Attribute* a = namedAttrMap->getAttributeItem(name))
191 void Element::scrollIntoView(bool alignToTop)
193 document()->updateLayoutIgnorePendingStylesheets();
194 IntRect bounds = getRect();
196 // Align to the top / bottom and to the closest edge.
198 renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
200 renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignBottomAlways);
204 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
206 document()->updateLayoutIgnorePendingStylesheets();
207 IntRect bounds = getRect();
210 renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignCenterIfNeeded, RenderLayer::gAlignCenterIfNeeded);
212 renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
216 void Element::scrollByUnits(int units, ScrollGranularity granularity)
218 document()->updateLayoutIgnorePendingStylesheets();
219 if (RenderObject *rend = renderer()) {
220 if (rend->hasOverflowClip()) {
221 ScrollDirection direction = ScrollDown;
223 direction = ScrollUp;
226 toRenderBox(rend)->layer()->scroll(direction, granularity, units);
231 void Element::scrollByLines(int lines)
233 scrollByUnits(lines, ScrollByLine);
236 void Element::scrollByPages(int pages)
238 scrollByUnits(pages, ScrollByPage);
241 static float localZoomForRenderer(RenderObject* renderer)
243 // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
244 // other out, but the alternative is that we'd have to crawl up the whole render tree every
245 // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
246 float zoomFactor = 1.0f;
247 if (renderer->style()->effectiveZoom() != 1.0f) {
248 // Need to find the nearest enclosing RenderObject that set up
249 // a differing zoom, and then we divide our result by it to eliminate the zoom.
250 RenderObject* prev = renderer;
251 for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
252 if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
253 zoomFactor = prev->style()->zoom();
258 if (prev->isRenderView())
259 zoomFactor = prev->style()->zoom();
264 static int adjustForLocalZoom(int value, RenderObject* renderer)
266 float zoomFactor = localZoomForRenderer(renderer);
267 if (zoomFactor == 1.0f)
269 return static_cast<int>(value / zoomFactor);
272 static int adjustForAbsoluteZoom(int value, RenderObject* renderer)
274 float zoomFactor = renderer->style()->effectiveZoom();
275 if (zoomFactor == 1.0f)
277 return static_cast<int>(value / zoomFactor);
280 int Element::offsetLeft()
282 document()->updateLayoutIgnorePendingStylesheets();
283 if (RenderBoxModelObject* rend = renderBoxModelObject())
284 return adjustForLocalZoom(rend->offsetLeft(), rend);
288 int Element::offsetTop()
290 document()->updateLayoutIgnorePendingStylesheets();
291 if (RenderBoxModelObject* rend = renderBoxModelObject())
292 return adjustForLocalZoom(rend->offsetTop(), rend);
296 int Element::offsetWidth()
298 document()->updateLayoutIgnorePendingStylesheets();
299 if (RenderBoxModelObject* rend = renderBoxModelObject())
300 return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
304 int Element::offsetHeight()
306 document()->updateLayoutIgnorePendingStylesheets();
307 if (RenderBoxModelObject* rend = renderBoxModelObject())
308 return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
312 Element* Element::offsetParent()
314 document()->updateLayoutIgnorePendingStylesheets();
315 if (RenderObject* rend = renderer())
316 if (RenderObject* offsetParent = rend->offsetParent())
317 return static_cast<Element*>(offsetParent->node());
321 int Element::clientLeft()
323 document()->updateLayoutIgnorePendingStylesheets();
325 if (RenderBox* rend = renderBox())
326 return adjustForAbsoluteZoom(rend->clientLeft(), rend);
330 int Element::clientTop()
332 document()->updateLayoutIgnorePendingStylesheets();
334 if (RenderBox* rend = renderBox())
335 return adjustForAbsoluteZoom(rend->clientTop(), rend);
339 int Element::clientWidth()
341 document()->updateLayoutIgnorePendingStylesheets();
343 // When in strict mode, clientWidth for the document element should return the width of the containing frame.
344 // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
345 bool inCompatMode = document()->inCompatMode();
346 if ((!inCompatMode && document()->documentElement() == this) ||
347 (inCompatMode && isHTMLElement() && document()->body() == this)) {
348 if (FrameView* view = document()->view())
349 return view->layoutWidth();
352 if (RenderBox* rend = renderBox())
353 return adjustForAbsoluteZoom(rend->clientWidth(), rend);
357 int Element::clientHeight()
359 document()->updateLayoutIgnorePendingStylesheets();
361 // When in strict mode, clientHeight for the document element should return the height of the containing frame.
362 // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
363 bool inCompatMode = document()->inCompatMode();
365 if ((!inCompatMode && document()->documentElement() == this) ||
366 (inCompatMode && isHTMLElement() && document()->body() == this)) {
367 if (FrameView* view = document()->view())
368 return view->layoutHeight();
371 if (RenderBox* rend = renderBox())
372 return adjustForAbsoluteZoom(rend->clientHeight(), rend);
376 int Element::scrollLeft()
378 document()->updateLayoutIgnorePendingStylesheets();
379 if (RenderBox* rend = renderBox())
380 return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
384 int Element::scrollTop()
386 document()->updateLayoutIgnorePendingStylesheets();
387 if (RenderBox* rend = renderBox())
388 return adjustForAbsoluteZoom(rend->scrollTop(), rend);
392 void Element::setScrollLeft(int newLeft)
394 document()->updateLayoutIgnorePendingStylesheets();
395 if (RenderBox* rend = renderBox())
396 rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
399 void Element::setScrollTop(int newTop)
401 document()->updateLayoutIgnorePendingStylesheets();
402 if (RenderBox* rend = renderBox())
403 rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
406 int Element::scrollWidth()
408 document()->updateLayoutIgnorePendingStylesheets();
409 if (RenderBox* rend = renderBox())
410 return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
414 int Element::scrollHeight()
416 document()->updateLayoutIgnorePendingStylesheets();
417 if (RenderBox* rend = renderBox())
418 return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
422 PassRefPtr<ClientRectList> Element::getClientRects() const
424 document()->updateLayoutIgnorePendingStylesheets();
426 RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
427 if (!renderBoxModelObject)
428 return ClientRectList::create();
430 // FIXME: Handle SVG elements.
431 // FIXME: Handle table/inline-table with a caption.
433 Vector<FloatQuad> quads;
434 renderBoxModelObject->absoluteQuads(quads);
436 if (FrameView* view = document()->view()) {
437 IntRect visibleContentRect = view->visibleContentRect();
438 for (size_t i = 0; i < quads.size(); ++i)
439 quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
442 return ClientRectList::create(quads);
445 PassRefPtr<ClientRect> Element::getBoundingClientRect() const
447 document()->updateLayoutIgnorePendingStylesheets();
448 RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
449 if (!renderBoxModelObject)
450 return ClientRect::create();
452 Vector<FloatQuad> quads;
453 renderBoxModelObject->absoluteQuads(quads);
456 return ClientRect::create();
458 IntRect result = quads[0].enclosingBoundingBox();
459 for (size_t i = 1; i < quads.size(); ++i)
460 result.unite(quads[i].enclosingBoundingBox());
462 if (FrameView* view = document()->view()) {
463 IntRect visibleContentRect = view->visibleContentRect();
464 result.move(-visibleContentRect.x(), -visibleContentRect.y());
467 return ClientRect::create(result);
470 static inline bool shouldIgnoreAttributeCase(const Element* e)
472 return e && e->document()->isHTMLDocument() && e->isHTMLElement();
475 const AtomicString& Element::getAttribute(const String& name) const
477 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
478 if (localName == styleAttr.localName() && !m_isStyleAttributeValid)
479 updateStyleAttribute();
482 if (!m_areSVGAttributesValid)
483 updateAnimatedSVGAttribute(name);
487 if (Attribute* a = namedAttrMap->getAttributeItem(name, shouldIgnoreAttributeCase(this)))
493 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
495 return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
498 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
500 if (!Document::isValidName(name)) {
501 ec = INVALID_CHARACTER_ERR;
505 const AtomicString& localName = (shouldIgnoreAttributeCase(this) && !name.string().impl()->isLower()) ? AtomicString(name.string().lower()) : name;
507 // allocate attributemap if necessary
508 Attribute* old = attributes(false)->getAttributeItem(localName, false);
510 document()->incDOMTreeVersion();
512 if (localName == idAttr.localName())
513 updateId(old ? old->value() : nullAtom, value);
515 if (old && value.isNull())
516 namedAttrMap->removeAttribute(old->name());
517 else if (!old && !value.isNull())
518 namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value));
519 else if (old && !value.isNull()) {
520 old->setValue(value);
521 attributeChanged(old);
525 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
527 document()->incDOMTreeVersion();
529 // allocate attributemap if necessary
530 Attribute* old = attributes(false)->getAttributeItem(name);
533 updateId(old ? old->value() : nullAtom, value);
535 if (old && value.isNull())
536 namedAttrMap->removeAttribute(name);
537 else if (!old && !value.isNull())
538 namedAttrMap->addAttribute(createAttribute(name, value));
540 old->setValue(value);
541 attributeChanged(old);
545 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
547 return Attribute::create(name, value);
550 void Element::attributeChanged(Attribute* attr, bool)
552 if (!document()->axObjectCache()->accessibilityEnabled())
555 const QualifiedName& attrName = attr->name();
556 if (attrName == aria_activedescendantAttr) {
557 // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
558 document()->axObjectCache()->handleActiveDescendantChanged(renderer());
559 } else if (attrName == roleAttr) {
560 // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
561 document()->axObjectCache()->handleAriaRoleChanged(renderer());
565 void Element::setAttributeMap(PassRefPtr<NamedAttrMap> list)
567 document()->incDOMTreeVersion();
569 // If setting the whole map changes the id attribute, we need to call updateId.
571 Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idAttr) : 0;
572 Attribute* newId = list ? list->getAttributeItem(idAttr) : 0;
575 updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
578 namedAttrMap->m_element = 0;
583 namedAttrMap->m_element = this;
584 unsigned len = namedAttrMap->length();
585 for (unsigned i = 0; i < len; i++)
586 attributeChanged(namedAttrMap->m_attributes[i].get());
587 // FIXME: What about attributes that were in the old map that are not in the new map?
591 bool Element::hasAttributes() const
593 if (!m_isStyleAttributeValid)
594 updateStyleAttribute();
597 if (!m_areSVGAttributesValid)
598 updateAnimatedSVGAttribute(String());
601 return namedAttrMap && namedAttrMap->length() > 0;
604 String Element::nodeName() const
606 return m_tagName.toString();
609 String Element::nodeNamePreservingCase() const
611 return m_tagName.toString();
614 void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec)
617 checkSetPrefix(_prefix, ec);
621 m_tagName.setPrefix(_prefix);
624 KURL Element::baseURI() const
626 KURL base(getAttribute(baseAttr));
627 if (!base.protocol().isEmpty())
630 Node* parent = parentNode();
634 const KURL& parentBase = parent->baseURI();
635 if (parentBase.isNull())
638 return KURL(parentBase, base.string());
641 void Element::createAttributeMap() const
643 namedAttrMap = NamedAttrMap::create(const_cast<Element*>(this));
646 bool Element::isURLAttribute(Attribute*) const
651 const QualifiedName& Element::imageSourceAttributeName() const
656 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
658 if (document()->documentElement() == this && style->display() == NONE) {
659 // Ignore display: none on root elements. Force a display of block in that case.
660 RenderBlock* result = new (arena) RenderBlock(this);
662 result->setAnimatableStyle(style);
665 return RenderObject::createObject(this, style);
669 void Element::insertedIntoDocument()
671 // need to do superclass processing first so inDocument() is true
672 // by the time we reach updateId
673 ContainerNode::insertedIntoDocument();
676 if (NamedAttrMap* attrs = namedAttrMap.get()) {
677 Attribute* idItem = attrs->getAttributeItem(idAttr);
678 if (idItem && !idItem->isNull())
679 updateId(nullAtom, idItem->value());
684 void Element::removedFromDocument()
687 if (NamedAttrMap* attrs = namedAttrMap.get()) {
688 Attribute* idItem = attrs->getAttributeItem(idAttr);
689 if (idItem && !idItem->isNull())
690 updateId(idItem->value(), nullAtom);
694 ContainerNode::removedFromDocument();
697 void Element::attach()
699 createRendererIfNeeded();
700 ContainerNode::attach();
702 ElementRareData* data = rareData();
703 if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
704 if (isFocusable() && document()->focusedNode() == this)
705 document()->updateFocusAppearanceSoon();
706 data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
711 void Element::detach()
713 cancelFocusAppearanceUpdate();
715 rareData()->resetComputedStyle();
716 ContainerNode::detach();
719 void Element::recalcStyle(StyleChange change)
721 RenderStyle* currentStyle = renderStyle();
722 bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
723 bool hasPositionalRules = changed() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
724 bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
727 if (!hasParentStyle && isShadowNode() && isSVGElement())
728 hasParentStyle = true;
731 if ((change > NoChange || changed())) {
733 rareData()->resetComputedStyle();
735 if (hasParentStyle && (change >= Inherit || changed())) {
736 RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
737 StyleChange ch = diff(currentStyle, newStyle.get());
738 if (ch == Detach || !currentStyle) {
741 attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
742 // attach recalulates the style for all children. No need to do it twice.
743 setChanged(NoStyleChange);
744 setHasChangedChild(false);
749 // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
750 // style change (e.g., only inline style changed).
751 if (currentStyle->affectedByHoverRules())
752 newStyle->setAffectedByHoverRules(true);
753 if (currentStyle->affectedByActiveRules())
754 newStyle->setAffectedByActiveRules(true);
755 if (currentStyle->affectedByDragRules())
756 newStyle->setAffectedByDragRules(true);
757 if (currentStyle->childrenAffectedByForwardPositionalRules())
758 newStyle->setChildrenAffectedByForwardPositionalRules();
759 if (currentStyle->childrenAffectedByBackwardPositionalRules())
760 newStyle->setChildrenAffectedByBackwardPositionalRules();
761 if (currentStyle->childrenAffectedByFirstChildRules())
762 newStyle->setChildrenAffectedByFirstChildRules();
763 if (currentStyle->childrenAffectedByLastChildRules())
764 newStyle->setChildrenAffectedByLastChildRules();
765 if (currentStyle->childrenAffectedByDirectAdjacentRules())
766 newStyle->setChildrenAffectedByDirectAdjacentRules();
769 if (ch != NoChange) {
770 setRenderStyle(newStyle);
771 } else if (changed() && (styleChangeType() != AnimationStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
772 // Although no change occurred, we use the new style so that the cousin style sharing code won't get
773 // fooled into believing this style is the same. This is only necessary if the document actually uses
774 // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
777 renderer()->setStyleInternal(newStyle.get());
779 setRenderStyle(newStyle);
780 } else if (styleChangeType() == AnimationStyleChange)
781 setRenderStyle(newStyle);
783 if (change != Force) {
784 if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
791 // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
792 // For now we will just worry about the common case, since it's a lot trickier to get the second case right
793 // without doing way too much re-resolution.
794 bool forceCheckOfNextElementSibling = false;
795 for (Node *n = firstChild(); n; n = n->nextSibling()) {
796 bool childRulesChanged = n->changed() && n->styleChangeType() == FullStyleChange;
797 if (forceCheckOfNextElementSibling && n->isElementNode())
799 if (change >= Inherit || n->isTextNode() || n->hasChangedChild() || n->changed())
800 n->recalcStyle(change);
801 if (n->isElementNode())
802 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
805 setChanged(NoStyleChange);
806 setHasChangedChild(false);
809 bool Element::childTypeAllowed(NodeType type)
815 case PROCESSING_INSTRUCTION_NODE:
816 case CDATA_SECTION_NODE:
817 case ENTITY_REFERENCE_NODE:
825 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
826 Node* beforeChange, Node* afterChange, int childCountDelta)
828 if (!style || (e->changed() && style->childrenAffectedByPositionalRules()))
831 // :first-child. In the parser callback case, we don't have to check anything, since we were right the first time.
832 // In the DOM case, we only need to do something if |afterChange| is not 0.
833 // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
834 if (style->childrenAffectedByFirstChildRules() && afterChange) {
835 // Find our new first child.
836 Node* newFirstChild = 0;
837 for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
839 // Find the first element node following |afterChange|
840 Node* firstElementAfterInsertion = 0;
841 for (firstElementAfterInsertion = afterChange;
842 firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
843 firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
845 // This is the insert/append case.
846 if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
847 firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
848 firstElementAfterInsertion->setChanged();
850 // We also have to handle node removal.
851 if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
852 newFirstChild->setChanged();
855 // :last-child. In the parser callback case, we don't have to check anything, since we were right the first time.
856 // In the DOM case, we only need to do something if |afterChange| is not 0.
857 if (style->childrenAffectedByLastChildRules() && beforeChange) {
858 // Find our new last child.
859 Node* newLastChild = 0;
860 for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
862 // Find the last element node going backwards from |beforeChange|
863 Node* lastElementBeforeInsertion = 0;
864 for (lastElementBeforeInsertion = beforeChange;
865 lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
866 lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
868 if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
869 lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
870 lastElementBeforeInsertion->setChanged();
872 // 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
874 if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
875 newLastChild->setChanged();
878 // The + selector. We need to invalidate the first element following the insertion point. It is the only possible element
879 // that could be affected by this DOM change.
880 if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
881 Node* firstElementAfterInsertion = 0;
882 for (firstElementAfterInsertion = afterChange;
883 firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
884 firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
885 if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
886 firstElementAfterInsertion->setChanged();
889 // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
890 // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
891 // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
893 // |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.
894 // 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
895 // here. recalcStyle will then force a walk of the children when it sees that this has happened.
896 if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
897 (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
901 if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()))
905 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
907 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
908 if (!changedByParser)
909 checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
912 void Element::finishParsingChildren()
914 ContainerNode::finishParsingChildren();
915 m_parsingChildrenFinished = true;
916 checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
919 void Element::dispatchAttrRemovalEvent(Attribute*)
921 ASSERT(!eventDispatchForbidden());
923 if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
925 ExceptionCode ec = 0;
926 dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
927 attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
931 void Element::dispatchAttrAdditionEvent(Attribute*)
933 ASSERT(!eventDispatchForbidden());
935 if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
937 ExceptionCode ec = 0;
938 dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
939 attr->value(),document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
943 String Element::openTagStartToString() const
945 String result = "<" + nodeName();
947 NamedAttrMap *attrMap = attributes(true);
950 unsigned numAttrs = attrMap->length();
951 for (unsigned i = 0; i < numAttrs; i++) {
954 Attribute *attribute = attrMap->attributeItem(i);
955 result += attribute->name().toString();
956 if (!attribute->value().isNull()) {
958 // FIXME: substitute entities for any instances of " or '
959 result += attribute->value();
968 void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
976 Document* doc = document();
977 if (!oldId.isEmpty())
978 doc->removeElementById(oldId, this);
979 if (!newId.isEmpty())
980 doc->addElementById(newId, this);
984 void Element::formatForDebugger(char* buffer, unsigned length) const
990 if (s.length() > 0) {
994 s = getAttribute(idAttr);
995 if (s.length() > 0) {
996 if (result.length() > 0)
1002 s = getAttribute(classAttr);
1003 if (s.length() > 0) {
1004 if (result.length() > 0)
1010 strncpy(buffer, result.utf8().data(), length - 1);
1014 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
1017 ec = TYPE_MISMATCH_ERR;
1020 return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1023 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
1026 ec = TYPE_MISMATCH_ERR;
1029 return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1032 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
1035 ec = TYPE_MISMATCH_ERR;
1038 if (attr->ownerElement() != this) {
1042 if (document() != attr->document()) {
1043 ec = WRONG_DOCUMENT_ERR;
1047 NamedAttrMap *attrs = attributes(true);
1051 return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
1054 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec)
1056 String prefix, localName;
1057 if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
1060 QualifiedName qName(prefix, localName, namespaceURI);
1061 setAttribute(qName, value, ec);
1064 void Element::removeAttribute(const String& name, ExceptionCode& ec)
1066 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1069 namedAttrMap->removeNamedItem(localName, ec);
1070 if (ec == NOT_FOUND_ERR)
1075 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
1077 removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
1080 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
1082 NamedAttrMap* attrs = attributes(true);
1085 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1086 return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
1089 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
1091 NamedAttrMap* attrs = attributes(true);
1094 return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
1097 bool Element::hasAttribute(const String& name) const
1099 NamedAttrMap* attrs = attributes(true);
1103 // This call to String::lower() seems to be required but
1104 // there may be a way to remove it.
1105 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1106 return attrs->getAttributeItem(localName, false);
1109 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1111 NamedAttrMap* attrs = attributes(true);
1114 return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1117 CSSStyleDeclaration *Element::style()
1122 void Element::focus(bool restorePreviousSelection)
1124 Document* doc = document();
1125 if (doc->focusedNode() == this)
1128 doc->updateLayoutIgnorePendingStylesheets();
1130 if (!supportsFocus())
1133 if (Page* page = doc->page())
1134 page->focusController()->setFocusedNode(this, doc->frame());
1136 if (!isFocusable()) {
1137 ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
1141 cancelFocusAppearanceUpdate();
1142 updateFocusAppearance(restorePreviousSelection);
1145 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
1147 if (this == rootEditableElement()) {
1148 Frame* frame = document()->frame();
1152 // FIXME: We should restore the previous selection if there is one.
1153 VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this);
1155 if (frame->shouldChangeSelection(newSelection)) {
1156 frame->selection()->setSelection(newSelection);
1157 frame->revealSelection();
1160 // FIXME: I'm not sure all devices will want this off, but this is
1161 // currently turned off for Andriod.
1162 #if !ENABLE(DIRECTIONAL_PAD_NAVIGATION)
1163 else if (renderer() && !renderer()->isWidget())
1164 renderer()->enclosingLayer()->scrollRectToVisible(getRect());
1168 void Element::blur()
1170 cancelFocusAppearanceUpdate();
1171 Document* doc = document();
1172 if (doc->focusedNode() == this) {
1174 doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1176 doc->setFocusedNode(0);
1180 String Element::innerText() const
1182 // We need to update layout, since plainText uses line boxes in the render tree.
1183 document()->updateLayoutIgnorePendingStylesheets();
1186 return textContent(true);
1188 return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1191 String Element::outerText() const
1193 // Getting outerText is the same as getting innerText, only
1194 // setting is different. You would think this should get the plain
1195 // text for the outer range, but this is wrong, <br> for instance
1196 // would return different values for inner and outer text by such
1197 // a rule, but it doesn't in WinIE, and we want to match that.
1201 String Element::title() const
1206 IntSize Element::minimumSizeForResizing() const
1208 return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1211 void Element::setMinimumSizeForResizing(const IntSize& size)
1213 if (size == defaultMinimumSizeForResizing() && !hasRareData())
1215 ensureRareData()->m_minimumSizeForResizing = size;
1218 RenderStyle* Element::computedStyle()
1220 if (RenderStyle* usedStyle = renderStyle())
1224 // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1225 // document tree and figure out when to destroy the computed style for such elements.
1228 ElementRareData* data = ensureRareData();
1229 if (!data->m_computedStyle)
1230 data->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
1231 return data->m_computedStyle.get();
1234 void Element::cancelFocusAppearanceUpdate()
1237 rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1238 if (document()->focusedNode() == this)
1239 document()->cancelFocusAppearanceUpdate();
1242 void Element::normalizeAttributes()
1244 // Normalize attributes.
1245 NamedAttrMap* attrs = attributes(true);
1248 unsigned numAttrs = attrs->length();
1249 for (unsigned i = 0; i < numAttrs; i++) {
1250 if (Attr* attr = attrs->attributeItem(i)->attr())
1255 // ElementTraversal API
1256 Element* Element::firstElementChild() const
1258 Node* n = firstChild();
1259 while (n && !n->isElementNode())
1260 n = n->nextSibling();
1261 return static_cast<Element*>(n);
1264 Element* Element::lastElementChild() const
1266 Node* n = lastChild();
1267 while (n && !n->isElementNode())
1268 n = n->previousSibling();
1269 return static_cast<Element*>(n);
1272 Element* Element::previousElementSibling() const
1274 Node* n = previousSibling();
1275 while (n && !n->isElementNode())
1276 n = n->previousSibling();
1277 return static_cast<Element*>(n);
1280 Element* Element::nextElementSibling() const
1282 Node* n = nextSibling();
1283 while (n && !n->isElementNode())
1284 n = n->nextSibling();
1285 return static_cast<Element*>(n);
1288 unsigned Element::childElementCount() const
1291 Node* n = firstChild();
1293 count += n->isElementNode();
1294 n = n->nextSibling();