Optimizations to Element::getAttribute
[WebKit-https.git] / WebCore / dom / Element.cpp
1 /*
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)
9  *
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.
14  *
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.
19  *
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.
24  */
25
26 #include "config.h"
27 #include "Element.h"
28
29 #include "AXObjectCache.h"
30 #include "Attr.h"
31 #include "CSSParser.h"
32 #include "CSSSelectorList.h"
33 #include "CSSStyleSelector.h"
34 #include "CString.h"
35 #include "ClientRect.h"
36 #include "ClientRectList.h"
37 #include "Document.h"
38 #include "ElementRareData.h"
39 #include "ExceptionCode.h"
40 #include "FocusController.h"
41 #include "Frame.h"
42 #include "FrameView.h"
43 #include "HTMLElement.h"
44 #include "HTMLNames.h"
45 #include "NamedNodeMap.h"
46 #include "NodeList.h"
47 #include "NodeRenderStyle.h"
48 #include "Page.h"
49 #include "RenderView.h"
50 #include "RenderWidget.h"
51 #include "TextIterator.h"
52 #include "XMLNames.h"
53
54 #if ENABLE(SVG)
55 #include "SVGNames.h"
56 #endif
57
58 namespace WebCore {
59
60 using namespace HTMLNames;
61 using namespace XMLNames;
62     
63 Element::Element(const QualifiedName& tagName, Document* document, ConstructionType type)
64     : ContainerNode(document, type)
65     , m_tagName(tagName)
66 {
67 }
68
69 PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document)
70 {
71     return adoptRef(new Element(tagName, document, CreateElement));
72 }
73
74 Element::~Element()
75 {
76     if (namedAttrMap)
77         namedAttrMap->detachFromElement();
78 }
79
80 inline ElementRareData* Element::rareData() const
81 {
82     ASSERT(hasRareData());
83     return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
84 }
85     
86 inline ElementRareData* Element::ensureRareData()
87 {
88     return static_cast<ElementRareData*>(Node::ensureRareData());
89 }
90     
91 NodeRareData* Element::createRareData()
92 {
93     return new ElementRareData;
94 }
95     
96 PassRefPtr<Node> Element::cloneNode(bool deep)
97 {
98     return deep ? cloneElementWithChildren() : cloneElementWithoutChildren();
99 }
100
101 PassRefPtr<Element> Element::cloneElementWithChildren()
102 {
103     RefPtr<Element> clone = cloneElementWithoutChildren();
104     cloneChildNodes(clone.get());
105     return clone.release();
106 }
107
108 PassRefPtr<Element> Element::cloneElementWithoutChildren()
109 {
110     RefPtr<Element> clone = document()->createElement(tagQName(), false);
111     // This will catch HTML elements in the wrong namespace that are not correctly copied.
112     // This is a sanity check as HTML overloads some of the DOM methods.
113     ASSERT(isHTMLElement() == clone->isHTMLElement());
114
115     // Clone attributes.
116     if (namedAttrMap)
117         clone->attributes()->setAttributes(*attributes(true)); // Call attributes(true) to force attribute synchronization to occur (for svg and style) before cloning happens.
118
119     clone->copyNonAttributeProperties(this);
120     
121     return clone.release();
122 }
123
124 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
125 {
126     if (namedAttrMap) {
127         ec = 0;
128         namedAttrMap->removeNamedItem(name, ec);
129         if (ec == NOT_FOUND_ERR)
130             ec = 0;
131     }
132 }
133
134 void Element::setAttribute(const QualifiedName& name, const AtomicString& value)
135 {
136     ExceptionCode ec;
137     setAttribute(name, value, ec);
138 }
139
140 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
141 {
142     if (b)
143         setAttribute(name, name.localName());
144     else {
145         ExceptionCode ex;
146         removeAttribute(name, ex);
147     }
148 }
149
150 // Virtual function, defined in base class.
151 NamedNodeMap* Element::attributes() const
152 {
153     return attributes(false);
154 }
155
156 NamedNodeMap* Element::attributes(bool readonly) const
157 {
158     if (!m_isStyleAttributeValid)
159         updateStyleAttribute();
160
161 #if ENABLE(SVG)
162     if (!m_areSVGAttributesValid)
163         updateAnimatedSVGAttribute(String());
164 #endif
165
166     if (!readonly && !namedAttrMap)
167         createAttributeMap();
168     return namedAttrMap.get();
169 }
170
171 Node::NodeType Element::nodeType() const
172 {
173     return ELEMENT_NODE;
174 }
175
176 const AtomicString& Element::getIDAttribute() const
177 {
178     return namedAttrMap ? namedAttrMap->id() : nullAtom;
179 }
180
181 bool Element::hasAttribute(const QualifiedName& name) const
182 {
183     return hasAttributeNS(name.namespaceURI(), name.localName());
184 }
185
186 const AtomicString& Element::getAttribute(const QualifiedName& name) const
187 {
188     if (name == styleAttr && !m_isStyleAttributeValid)
189         updateStyleAttribute();
190
191 #if ENABLE(SVG)
192     if (!m_areSVGAttributesValid)
193         updateAnimatedSVGAttribute(name.localName());
194 #endif
195
196     if (namedAttrMap)
197         if (Attribute* a = namedAttrMap->getAttributeItem(name))
198             return a->value();
199
200     return nullAtom;
201 }
202
203 void Element::scrollIntoView(bool alignToTop) 
204 {
205     document()->updateLayoutIgnorePendingStylesheets();
206     IntRect bounds = getRect();    
207     if (renderer()) {
208         // Align to the top / bottom and to the closest edge.
209         if (alignToTop)
210             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
211         else
212             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
213     }
214 }
215
216 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
217 {
218     document()->updateLayoutIgnorePendingStylesheets();
219     IntRect bounds = getRect();    
220     if (renderer()) {
221         if (centerIfNeeded)
222             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
223         else
224             renderer()->enclosingLayer()->scrollRectToVisible(bounds, false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
225     }
226 }
227
228 void Element::scrollByUnits(int units, ScrollGranularity granularity)
229 {
230     document()->updateLayoutIgnorePendingStylesheets();
231     if (RenderObject *rend = renderer()) {
232         if (rend->hasOverflowClip()) {
233             ScrollDirection direction = ScrollDown;
234             if (units < 0) {
235                 direction = ScrollUp;
236                 units = -units;
237             }
238             toRenderBox(rend)->layer()->scroll(direction, granularity, units);
239         }
240     }
241 }
242
243 void Element::scrollByLines(int lines)
244 {
245     scrollByUnits(lines, ScrollByLine);
246 }
247
248 void Element::scrollByPages(int pages)
249 {
250     scrollByUnits(pages, ScrollByPage);
251 }
252
253 static float localZoomForRenderer(RenderObject* renderer)
254 {
255     // FIXME: This does the wrong thing if two opposing zooms are in effect and canceled each
256     // other out, but the alternative is that we'd have to crawl up the whole render tree every
257     // time (or store an additional bit in the RenderStyle to indicate that a zoom was specified).
258     float zoomFactor = 1.0f;
259     if (renderer->style()->effectiveZoom() != 1.0f) {
260         // Need to find the nearest enclosing RenderObject that set up
261         // a differing zoom, and then we divide our result by it to eliminate the zoom.
262         RenderObject* prev = renderer;
263         for (RenderObject* curr = prev->parent(); curr; curr = curr->parent()) {
264             if (curr->style()->effectiveZoom() != prev->style()->effectiveZoom()) {
265                 zoomFactor = prev->style()->zoom();
266                 break;
267             }
268             prev = curr;
269         }
270         if (prev->isRenderView())
271             zoomFactor = prev->style()->zoom();
272     }
273     return zoomFactor;
274 }
275
276 static int adjustForLocalZoom(int value, RenderObject* renderer)
277 {
278     float zoomFactor = localZoomForRenderer(renderer);
279     if (zoomFactor == 1)
280         return value;
281     // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
282     if (zoomFactor > 1)
283         value++;
284     return static_cast<int>(value / zoomFactor);
285 }
286
287 int Element::offsetLeft()
288 {
289     document()->updateLayoutIgnorePendingStylesheets();
290     if (RenderBoxModelObject* rend = renderBoxModelObject())
291         return adjustForLocalZoom(rend->offsetLeft(), rend);
292     return 0;
293 }
294
295 int Element::offsetTop()
296 {
297     document()->updateLayoutIgnorePendingStylesheets();
298     if (RenderBoxModelObject* rend = renderBoxModelObject())
299         return adjustForLocalZoom(rend->offsetTop(), rend);
300     return 0;
301 }
302
303 int Element::offsetWidth()
304 {
305     document()->updateLayoutIgnorePendingStylesheets();
306     if (RenderBoxModelObject* rend = renderBoxModelObject())
307         return adjustForAbsoluteZoom(rend->offsetWidth(), rend);
308     return 0;
309 }
310
311 int Element::offsetHeight()
312 {
313     document()->updateLayoutIgnorePendingStylesheets();
314     if (RenderBoxModelObject* rend = renderBoxModelObject())
315         return adjustForAbsoluteZoom(rend->offsetHeight(), rend);
316     return 0;
317 }
318
319 Element* Element::offsetParent()
320 {
321     document()->updateLayoutIgnorePendingStylesheets();
322     if (RenderObject* rend = renderer())
323         if (RenderObject* offsetParent = rend->offsetParent())
324             return static_cast<Element*>(offsetParent->node());
325     return 0;
326 }
327
328 int Element::clientLeft()
329 {
330     document()->updateLayoutIgnorePendingStylesheets();
331
332     if (RenderBox* rend = renderBox())
333         return adjustForAbsoluteZoom(rend->clientLeft(), rend);
334     return 0;
335 }
336
337 int Element::clientTop()
338 {
339     document()->updateLayoutIgnorePendingStylesheets();
340
341     if (RenderBox* rend = renderBox())
342         return adjustForAbsoluteZoom(rend->clientTop(), rend);
343     return 0;
344 }
345
346 int Element::clientWidth()
347 {
348     document()->updateLayoutIgnorePendingStylesheets();
349
350     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
351     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
352     bool inCompatMode = document()->inCompatMode();
353     if ((!inCompatMode && document()->documentElement() == this) ||
354         (inCompatMode && isHTMLElement() && document()->body() == this)) {
355         if (FrameView* view = document()->view()) {
356             if (RenderView* renderView = document()->renderView())
357                 return adjustForAbsoluteZoom(view->layoutWidth(), renderView);
358         }
359     }
360     
361     if (RenderBox* rend = renderBox())
362         return adjustForAbsoluteZoom(rend->clientWidth(), rend);
363     return 0;
364 }
365
366 int Element::clientHeight()
367 {
368     document()->updateLayoutIgnorePendingStylesheets();
369
370     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
371     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
372     bool inCompatMode = document()->inCompatMode();     
373
374     if ((!inCompatMode && document()->documentElement() == this) ||
375         (inCompatMode && isHTMLElement() && document()->body() == this)) {
376         if (FrameView* view = document()->view()) {
377             if (RenderView* renderView = document()->renderView())
378                 return adjustForAbsoluteZoom(view->layoutHeight(), renderView);
379         }
380     }
381     
382     if (RenderBox* rend = renderBox())
383         return adjustForAbsoluteZoom(rend->clientHeight(), rend);
384     return 0;
385 }
386
387 int Element::scrollLeft() const
388 {
389     document()->updateLayoutIgnorePendingStylesheets();
390     if (RenderBox* rend = renderBox())
391         return adjustForAbsoluteZoom(rend->scrollLeft(), rend);
392     return 0;
393 }
394
395 int Element::scrollTop() const
396 {
397     document()->updateLayoutIgnorePendingStylesheets();
398     if (RenderBox* rend = renderBox())
399         return adjustForAbsoluteZoom(rend->scrollTop(), rend);
400     return 0;
401 }
402
403 void Element::setScrollLeft(int newLeft)
404 {
405     document()->updateLayoutIgnorePendingStylesheets();
406     if (RenderBox* rend = renderBox())
407         rend->setScrollLeft(static_cast<int>(newLeft * rend->style()->effectiveZoom()));
408 }
409
410 void Element::setScrollTop(int newTop)
411 {
412     document()->updateLayoutIgnorePendingStylesheets();
413     if (RenderBox* rend = renderBox())
414         rend->setScrollTop(static_cast<int>(newTop * rend->style()->effectiveZoom()));
415 }
416
417 int Element::scrollWidth() const
418 {
419     document()->updateLayoutIgnorePendingStylesheets();
420     if (RenderBox* rend = renderBox())
421         return adjustForAbsoluteZoom(rend->scrollWidth(), rend);
422     return 0;
423 }
424
425 int Element::scrollHeight() const
426 {
427     document()->updateLayoutIgnorePendingStylesheets();
428     if (RenderBox* rend = renderBox())
429         return adjustForAbsoluteZoom(rend->scrollHeight(), rend);
430     return 0;
431 }
432
433 PassRefPtr<ClientRectList> Element::getClientRects() const
434 {
435     document()->updateLayoutIgnorePendingStylesheets();
436
437     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
438     if (!renderBoxModelObject)
439         return ClientRectList::create();
440
441     // FIXME: Handle SVG elements.
442     // FIXME: Handle table/inline-table with a caption.
443
444     Vector<FloatQuad> quads;
445     renderBoxModelObject->absoluteQuads(quads);
446
447     if (FrameView* view = document()->view()) {
448         IntRect visibleContentRect = view->visibleContentRect();
449         for (size_t i = 0; i < quads.size(); ++i) {
450             quads[i].move(-visibleContentRect.x(), -visibleContentRect.y());
451             adjustFloatQuadForAbsoluteZoom(quads[i], renderBoxModelObject);
452         }
453     }
454
455     return ClientRectList::create(quads);
456 }
457
458 PassRefPtr<ClientRect> Element::getBoundingClientRect() const
459 {
460     document()->updateLayoutIgnorePendingStylesheets();
461     RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject();
462     if (!renderBoxModelObject)
463         return ClientRect::create();
464
465     Vector<FloatQuad> quads;
466     renderBoxModelObject->absoluteQuads(quads);
467
468     if (quads.isEmpty())
469         return ClientRect::create();
470
471     IntRect result = quads[0].enclosingBoundingBox();
472     for (size_t i = 1; i < quads.size(); ++i)
473         result.unite(quads[i].enclosingBoundingBox());
474
475     if (FrameView* view = document()->view()) {
476         IntRect visibleContentRect = view->visibleContentRect();
477         result.move(-visibleContentRect.x(), -visibleContentRect.y());
478     }
479
480     adjustIntRectForAbsoluteZoom(result, renderBoxModelObject);
481
482     return ClientRect::create(result);
483 }
484
485 static inline bool shouldIgnoreAttributeCase(const Element* e)
486 {
487     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
488 }
489
490 const AtomicString& Element::getAttribute(const String& name) const
491 {
492     bool ignoreCase = shouldIgnoreAttributeCase(this);
493     
494     // Update the 'style' attribute if it's invalid and being requested:
495     if (!m_isStyleAttributeValid && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
496         updateStyleAttribute();
497
498 #if ENABLE(SVG)
499     if (!m_areSVGAttributesValid)
500         updateAnimatedSVGAttribute(name);
501 #endif
502
503     if (namedAttrMap)
504         if (Attribute* attribute = namedAttrMap->getAttributeItem(name, ignoreCase))
505             return attribute->value();
506     
507     return nullAtom;
508 }
509
510 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
511 {
512     return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
513 }
514
515 void Element::setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode& ec)
516 {
517     if (!Document::isValidName(name)) {
518         ec = INVALID_CHARACTER_ERR;
519         return;
520     }
521
522     const AtomicString& localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
523
524     // allocate attributemap if necessary
525     Attribute* old = attributes(false)->getAttributeItem(localName, false);
526
527     document()->incDOMTreeVersion();
528
529     if (localName == idAttr.localName())
530         updateId(old ? old->value() : nullAtom, value);
531     
532     if (old && value.isNull())
533         namedAttrMap->removeAttribute(old->name());
534     else if (!old && !value.isNull())
535         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value));
536     else if (old && !value.isNull()) {
537         old->setValue(value);
538         attributeChanged(old);
539     }
540 }
541
542 void Element::setAttribute(const QualifiedName& name, const AtomicString& value, ExceptionCode&)
543 {
544     document()->incDOMTreeVersion();
545
546     // allocate attributemap if necessary
547     Attribute* old = attributes(false)->getAttributeItem(name);
548
549     if (name == idAttr)
550         updateId(old ? old->value() : nullAtom, value);
551     
552     if (old && value.isNull())
553         namedAttrMap->removeAttribute(name);
554     else if (!old && !value.isNull())
555         namedAttrMap->addAttribute(createAttribute(name, value));
556     else if (old) {
557         old->setValue(value);
558         attributeChanged(old);
559     }
560 }
561
562 PassRefPtr<Attribute> Element::createAttribute(const QualifiedName& name, const AtomicString& value)
563 {
564     return Attribute::create(name, value);
565 }
566
567 void Element::attributeChanged(Attribute* attr, bool)
568 {
569     recalcStyleIfNeededAfterAttributeChanged(attr);
570     updateAfterAttributeChanged(attr);
571 }
572
573 void Element::updateAfterAttributeChanged(Attribute* attr)
574 {
575     AXObjectCache* axObjectCache = document()->axObjectCache();
576     if (!axObjectCache->accessibilityEnabled())
577         return;
578
579     const QualifiedName& attrName = attr->name();
580     if (attrName == aria_activedescendantAttr) {
581         // any change to aria-activedescendant attribute triggers accessibility focus change, but document focus remains intact
582         axObjectCache->handleActiveDescendantChanged(renderer());
583     } else if (attrName == roleAttr) {
584         // the role attribute can change at any time, and the AccessibilityObject must pick up these changes
585         axObjectCache->handleAriaRoleChanged(renderer());
586     } else if (attrName == aria_valuenowAttr) {
587         // If the valuenow attribute changes, AX clients need to be notified.
588         axObjectCache->postNotification(renderer(), AXObjectCache::AXValueChanged, true);
589     }
590 }
591     
592 void Element::recalcStyleIfNeededAfterAttributeChanged(Attribute* attr)
593 {
594     if (document()->attached() && document()->styleSelector()->hasSelectorForAttribute(attr->name().localName()))
595         setNeedsStyleRecalc();
596 }
597         
598 void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list)
599 {
600     document()->incDOMTreeVersion();
601
602     // If setting the whole map changes the id attribute, we need to call updateId.
603
604     Attribute* oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idAttr) : 0;
605     Attribute* newId = list ? list->getAttributeItem(idAttr) : 0;
606
607     if (oldId || newId)
608         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
609
610     if (namedAttrMap)
611         namedAttrMap->m_element = 0;
612
613     namedAttrMap = list;
614
615     if (namedAttrMap) {
616         namedAttrMap->m_element = this;
617         unsigned len = namedAttrMap->length();
618         for (unsigned i = 0; i < len; i++)
619             attributeChanged(namedAttrMap->m_attributes[i].get());
620         // FIXME: What about attributes that were in the old map that are not in the new map?
621     }
622 }
623
624 bool Element::hasAttributes() const
625 {
626     if (!m_isStyleAttributeValid)
627         updateStyleAttribute();
628
629 #if ENABLE(SVG)
630     if (!m_areSVGAttributesValid)
631         updateAnimatedSVGAttribute(String());
632 #endif
633
634     return namedAttrMap && namedAttrMap->length() > 0;
635 }
636
637 String Element::nodeName() const
638 {
639     return m_tagName.toString();
640 }
641
642 String Element::nodeNamePreservingCase() const
643 {
644     return m_tagName.toString();
645 }
646
647 void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec)
648 {
649     ec = 0;
650     checkSetPrefix(_prefix, ec);
651     if (ec)
652         return;
653
654     m_tagName.setPrefix(_prefix);
655 }
656
657 KURL Element::baseURI() const
658 {
659     KURL base(KURL(), getAttribute(baseAttr));
660     if (!base.protocol().isEmpty())
661         return base;
662
663     Node* parent = parentNode();
664     if (!parent)
665         return base;
666
667     const KURL& parentBase = parent->baseURI();
668     if (parentBase.isNull())
669         return base;
670
671     return KURL(parentBase, base.string());
672 }
673
674 void Element::createAttributeMap() const
675 {
676     namedAttrMap = NamedNodeMap::create(const_cast<Element*>(this));
677 }
678
679 bool Element::isURLAttribute(Attribute*) const
680 {
681     return false;
682 }
683
684 const QualifiedName& Element::imageSourceAttributeName() const
685 {
686     return srcAttr;
687 }
688
689 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
690 {
691     if (document()->documentElement() == this && style->display() == NONE) {
692         // Ignore display: none on root elements.  Force a display of block in that case.
693         RenderBlock* result = new (arena) RenderBlock(this);
694         if (result)
695             result->setAnimatableStyle(style);
696         return result;
697     }
698     return RenderObject::createObject(this, style);
699 }
700
701
702 void Element::insertedIntoDocument()
703 {
704     // need to do superclass processing first so inDocument() is true
705     // by the time we reach updateId
706     ContainerNode::insertedIntoDocument();
707
708     if (hasID()) {
709         if (NamedNodeMap* attrs = namedAttrMap.get()) {
710             Attribute* idItem = attrs->getAttributeItem(idAttr);
711             if (idItem && !idItem->isNull())
712                 updateId(nullAtom, idItem->value());
713         }
714     }
715 }
716
717 void Element::removedFromDocument()
718 {
719     if (hasID()) {
720         if (NamedNodeMap* attrs = namedAttrMap.get()) {
721             Attribute* idItem = attrs->getAttributeItem(idAttr);
722             if (idItem && !idItem->isNull())
723                 updateId(idItem->value(), nullAtom);
724         }
725     }
726
727     ContainerNode::removedFromDocument();
728 }
729
730 void Element::attach()
731 {
732     suspendPostAttachCallbacks();
733     RenderWidget::suspendWidgetHierarchyUpdates();
734
735     createRendererIfNeeded();
736     ContainerNode::attach();
737     if (hasRareData()) {   
738         ElementRareData* data = rareData();
739         if (data->needsFocusAppearanceUpdateSoonAfterAttach()) {
740             if (isFocusable() && document()->focusedNode() == this)
741                 document()->updateFocusAppearanceSoon();
742             data->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
743         }
744     }
745
746     RenderWidget::resumeWidgetHierarchyUpdates();
747     resumePostAttachCallbacks();
748 }
749
750 void Element::detach()
751 {
752     RenderWidget::suspendWidgetHierarchyUpdates();
753
754     cancelFocusAppearanceUpdate();
755     if (hasRareData())
756         rareData()->resetComputedStyle();
757     ContainerNode::detach();
758
759     RenderWidget::resumeWidgetHierarchyUpdates();
760 }
761
762 bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle)
763 {
764     ASSERT(currentStyle == renderStyle());
765
766     if (!renderer() || !currentStyle)
767         return false;
768
769     RenderStyle::PseudoStyleCache pseudoStyleCache;
770     currentStyle->getPseudoStyleCache(pseudoStyleCache);
771     size_t cacheSize = pseudoStyleCache.size();
772     for (size_t i = 0; i < cacheSize; ++i) {
773         RefPtr<RenderStyle> newPseudoStyle;
774         PseudoId pseudoId = pseudoStyleCache[i]->styleType();
775         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
776             newPseudoStyle = renderer()->uncachedFirstLineStyle(newStyle);
777         else
778             newPseudoStyle = renderer()->getUncachedPseudoStyle(pseudoId, newStyle, newStyle);
779
780         if (*newPseudoStyle != *pseudoStyleCache[i]) {
781             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
782                 newStyle->setHasPseudoStyle(pseudoId);
783             newStyle->addCachedPseudoStyle(newPseudoStyle);
784             return true;
785         }
786     }
787     return false;
788 }
789
790 void Element::recalcStyle(StyleChange change)
791 {
792     // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
793     RefPtr<RenderStyle> currentStyle(renderStyle());
794     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
795     bool hasPositionalRules = needsStyleRecalc() && currentStyle && currentStyle->childrenAffectedByPositionalRules();
796     bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
797
798 #if ENABLE(SVG)
799     if (!hasParentStyle && isShadowNode() && isSVGElement())
800         hasParentStyle = true;
801 #endif
802
803     if ((change > NoChange || needsStyleRecalc())) {
804         if (hasRareData())
805             rareData()->resetComputedStyle();
806     }
807     if (hasParentStyle && (change >= Inherit || needsStyleRecalc())) {
808         RefPtr<RenderStyle> newStyle = document()->styleSelector()->styleForElement(this);
809         StyleChange ch = diff(currentStyle.get(), newStyle.get());
810         if (ch == Detach || !currentStyle) {
811             if (attached())
812                 detach();
813             attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along.
814             // attach recalulates the style for all children. No need to do it twice.
815             setNeedsStyleRecalc(NoStyleChange);
816             setChildNeedsStyleRecalc(false);
817             return;
818         }
819
820         if (currentStyle) {
821             // Preserve "affected by" bits that were propagated to us from descendants in the case where we didn't do a full
822             // style change (e.g., only inline style changed).
823             if (currentStyle->affectedByHoverRules())
824                 newStyle->setAffectedByHoverRules(true);
825             if (currentStyle->affectedByActiveRules())
826                 newStyle->setAffectedByActiveRules(true);
827             if (currentStyle->affectedByDragRules())
828                 newStyle->setAffectedByDragRules(true);
829             if (currentStyle->childrenAffectedByForwardPositionalRules())
830                 newStyle->setChildrenAffectedByForwardPositionalRules();
831             if (currentStyle->childrenAffectedByBackwardPositionalRules())
832                 newStyle->setChildrenAffectedByBackwardPositionalRules();
833             if (currentStyle->childrenAffectedByFirstChildRules())
834                 newStyle->setChildrenAffectedByFirstChildRules();
835             if (currentStyle->childrenAffectedByLastChildRules())
836                 newStyle->setChildrenAffectedByLastChildRules();
837             if (currentStyle->childrenAffectedByDirectAdjacentRules())
838                 newStyle->setChildrenAffectedByDirectAdjacentRules();
839         }
840
841         if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get())) {
842             setRenderStyle(newStyle);
843         } else if (needsStyleRecalc() && (styleChangeType() != SyntheticStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
844             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
845             // fooled into believing this style is the same.  This is only necessary if the document actually uses
846             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
847             // descendants.
848             if (renderer())
849                 renderer()->setStyleInternal(newStyle.get());
850             else
851                 setRenderStyle(newStyle);
852         } else if (styleChangeType() == SyntheticStyleChange)
853              setRenderStyle(newStyle);
854
855         if (change != Force) {
856             // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating
857             // all the way down the tree.  This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
858             if (document()->usesRemUnits() && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize() && document()->documentElement() == this)
859                 change = Force;
860             else if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
861                 change = Force;
862             else
863                 change = ch;
864         }
865     }
866
867     // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
868     // For now we will just worry about the common case, since it's a lot trickier to get the second case right
869     // without doing way too much re-resolution.
870     bool forceCheckOfNextElementSibling = false;
871     for (Node *n = firstChild(); n; n = n->nextSibling()) {
872         bool childRulesChanged = n->needsStyleRecalc() && n->styleChangeType() == FullStyleChange;
873         if (forceCheckOfNextElementSibling && n->isElementNode())
874             n->setNeedsStyleRecalc();
875         if (change >= Inherit || n->isTextNode() || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
876             n->recalcStyle(change);
877         if (n->isElementNode())
878             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
879     }
880
881     setNeedsStyleRecalc(NoStyleChange);
882     setChildNeedsStyleRecalc(false);
883 }
884
885 bool Element::childTypeAllowed(NodeType type)
886 {
887     switch (type) {
888         case ELEMENT_NODE:
889         case TEXT_NODE:
890         case COMMENT_NODE:
891         case PROCESSING_INSTRUCTION_NODE:
892         case CDATA_SECTION_NODE:
893         case ENTITY_REFERENCE_NODE:
894             return true;
895             break;
896         default:
897             return false;
898     }
899 }
900
901 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
902                                         Node* beforeChange, Node* afterChange, int childCountDelta)
903 {
904     if (!style || (e->needsStyleRecalc() && style->childrenAffectedByPositionalRules()))
905         return;
906
907     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
908     // In the DOM case, we only need to do something if |afterChange| is not 0.
909     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
910     if (style->childrenAffectedByFirstChildRules() && afterChange) {
911         // Find our new first child.
912         Node* newFirstChild = 0;
913         for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
914         
915         // Find the first element node following |afterChange|
916         Node* firstElementAfterInsertion = 0;
917         for (firstElementAfterInsertion = afterChange;
918              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
919              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
920         
921         // This is the insert/append case.
922         if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
923             firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
924             firstElementAfterInsertion->setNeedsStyleRecalc();
925             
926         // We also have to handle node removal.
927         if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && newFirstChild->renderStyle() && !newFirstChild->renderStyle()->firstChildState())
928             newFirstChild->setNeedsStyleRecalc();
929     }
930
931     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
932     // In the DOM case, we only need to do something if |afterChange| is not 0.
933     if (style->childrenAffectedByLastChildRules() && beforeChange) {
934         // Find our new last child.
935         Node* newLastChild = 0;
936         for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
937         
938         // Find the last element node going backwards from |beforeChange|
939         Node* lastElementBeforeInsertion = 0;
940         for (lastElementBeforeInsertion = beforeChange;
941              lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
942              lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
943         
944         if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
945             lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
946             lastElementBeforeInsertion->setNeedsStyleRecalc();
947             
948         // 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
949         // to match now.
950         if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && newLastChild->renderStyle() && !newLastChild->renderStyle()->lastChildState())
951             newLastChild->setNeedsStyleRecalc();
952     }
953
954     // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
955     // that could be affected by this DOM change.
956     if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
957         Node* firstElementAfterInsertion = 0;
958         for (firstElementAfterInsertion = afterChange;
959              firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
960              firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
961         if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
962             firstElementAfterInsertion->setNeedsStyleRecalc();
963     }
964
965     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
966     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
967     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
968     // backward case.
969     // |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.
970     // 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
971     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
972     if ((style->childrenAffectedByForwardPositionalRules() && afterChange) ||
973         (style->childrenAffectedByBackwardPositionalRules() && beforeChange))
974         e->setNeedsStyleRecalc();
975     
976     // :empty selector.
977     if (style->affectedByEmpty() && (!style->emptyState() || e->hasChildNodes()))
978         e->setNeedsStyleRecalc();
979 }
980
981 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
982 {
983     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
984     if (!changedByParser)
985         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
986 }
987
988 void Element::finishParsingChildren()
989 {
990     ContainerNode::finishParsingChildren();
991     m_parsingChildrenFinished = true;
992     checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0);
993 }
994
995 void Element::dispatchAttrRemovalEvent(Attribute*)
996 {
997     ASSERT(!eventDispatchForbidden());
998 #if 0
999     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
1000         return;
1001     ExceptionCode ec = 0;
1002     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
1003         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
1004 #endif
1005 }
1006
1007 void Element::dispatchAttrAdditionEvent(Attribute*)
1008 {
1009     ASSERT(!eventDispatchForbidden());
1010 #if 0
1011     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
1012         return;
1013     ExceptionCode ec = 0;
1014     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
1015         attr->value(), document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
1016 #endif
1017 }
1018
1019 String Element::openTagStartToString() const
1020 {
1021     String result = "<" + nodeName();
1022
1023     NamedNodeMap* attrMap = attributes(true);
1024
1025     if (attrMap) {
1026         unsigned numAttrs = attrMap->length();
1027         for (unsigned i = 0; i < numAttrs; i++) {
1028             result += " ";
1029
1030             Attribute *attribute = attrMap->attributeItem(i);
1031             result += attribute->name().toString();
1032             if (!attribute->value().isNull()) {
1033                 result += "=\"";
1034                 // FIXME: substitute entities for any instances of " or '
1035                 result += attribute->value();
1036                 result += "\"";
1037             }
1038         }
1039     }
1040
1041     return result;
1042 }
1043
1044 void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
1045 {
1046     if (!inDocument())
1047         return;
1048
1049     if (oldId == newId)
1050         return;
1051
1052     Document* doc = document();
1053     if (!oldId.isEmpty())
1054         doc->removeElementById(oldId, this);
1055     if (!newId.isEmpty())
1056         doc->addElementById(newId, this);
1057 }
1058
1059 #ifndef NDEBUG
1060 void Element::formatForDebugger(char* buffer, unsigned length) const
1061 {
1062     String result;
1063     String s;
1064     
1065     s = nodeName();
1066     if (s.length() > 0) {
1067         result += s;
1068     }
1069           
1070     s = getAttribute(idAttr);
1071     if (s.length() > 0) {
1072         if (result.length() > 0)
1073             result += "; ";
1074         result += "id=";
1075         result += s;
1076     }
1077           
1078     s = getAttribute(classAttr);
1079     if (s.length() > 0) {
1080         if (result.length() > 0)
1081             result += "; ";
1082         result += "class=";
1083         result += s;
1084     }
1085           
1086     strncpy(buffer, result.utf8().data(), length - 1);
1087 }
1088 #endif
1089
1090 PassRefPtr<Attr> Element::setAttributeNode(Attr* attr, ExceptionCode& ec)
1091 {
1092     if (!attr) {
1093         ec = TYPE_MISMATCH_ERR;
1094         return 0;
1095     }
1096     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1097 }
1098
1099 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
1100 {
1101     if (!attr) {
1102         ec = TYPE_MISMATCH_ERR;
1103         return 0;
1104     }
1105     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
1106 }
1107
1108 PassRefPtr<Attr> Element::removeAttributeNode(Attr* attr, ExceptionCode& ec)
1109 {
1110     if (!attr) {
1111         ec = TYPE_MISMATCH_ERR;
1112         return 0;
1113     }
1114     if (attr->ownerElement() != this) {
1115         ec = NOT_FOUND_ERR;
1116         return 0;
1117     }
1118     if (document() != attr->document()) {
1119         ec = WRONG_DOCUMENT_ERR;
1120         return 0;
1121     }
1122
1123     NamedNodeMap* attrs = attributes(true);
1124     if (!attrs)
1125         return 0;
1126
1127     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
1128 }
1129
1130 void Element::setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode& ec)
1131 {
1132     String prefix, localName;
1133     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
1134         return;
1135
1136     QualifiedName qName(prefix, localName, namespaceURI);
1137     setAttribute(qName, value, ec);
1138 }
1139
1140 void Element::removeAttribute(const String& name, ExceptionCode& ec)
1141 {
1142     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1143
1144     if (namedAttrMap) {
1145         namedAttrMap->removeNamedItem(localName, ec);
1146         if (ec == NOT_FOUND_ERR)
1147             ec = 0;
1148     }
1149 }
1150
1151 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
1152 {
1153     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
1154 }
1155
1156 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
1157 {
1158     NamedNodeMap* attrs = attributes(true);
1159     if (!attrs)
1160         return 0;
1161     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1162     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
1163 }
1164
1165 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
1166 {
1167     NamedNodeMap* attrs = attributes(true);
1168     if (!attrs)
1169         return 0;
1170     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
1171 }
1172
1173 bool Element::hasAttribute(const String& name) const
1174 {
1175     NamedNodeMap* attrs = attributes(true);
1176     if (!attrs)
1177         return false;
1178
1179     // This call to String::lower() seems to be required but
1180     // there may be a way to remove it.
1181     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1182     return attrs->getAttributeItem(localName, false);
1183 }
1184
1185 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1186 {
1187     NamedNodeMap* attrs = attributes(true);
1188     if (!attrs)
1189         return false;
1190     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1191 }
1192
1193 CSSStyleDeclaration *Element::style()
1194 {
1195     return 0;
1196 }
1197
1198 void Element::focus(bool restorePreviousSelection)
1199 {
1200     Document* doc = document();
1201     if (doc->focusedNode() == this)
1202         return;
1203
1204     if (!supportsFocus())
1205         return;
1206
1207     // If the stylesheets have already been loaded we can reliably check isFocusable.
1208     // If not, we continue and set the focused node on the focus controller below so
1209     // that it can be updated soon after attach. 
1210     if (doc->haveStylesheetsLoaded()) {
1211         doc->updateLayoutIgnorePendingStylesheets();
1212         if (!isFocusable())
1213             return;
1214     }
1215
1216     if (Page* page = doc->page())
1217         page->focusController()->setFocusedNode(this, doc->frame());
1218
1219     // Setting the focused node above might have invalidated the layout due to scripts.
1220     doc->updateLayoutIgnorePendingStylesheets();
1221
1222     if (!isFocusable()) {
1223         ensureRareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
1224         return;
1225     }
1226         
1227     cancelFocusAppearanceUpdate();
1228     updateFocusAppearance(restorePreviousSelection);
1229 }
1230
1231 void Element::updateFocusAppearance(bool /*restorePreviousSelection*/)
1232 {
1233     if (this == rootEditableElement()) { 
1234         Frame* frame = document()->frame();
1235         if (!frame)
1236             return;
1237
1238         // FIXME: We should restore the previous selection if there is one.
1239         VisibleSelection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? VisibleSelection(Position(this, 0), DOWNSTREAM) : VisibleSelection::selectionFromContentsOfNode(this);
1240         
1241         if (frame->shouldChangeSelection(newSelection)) {
1242             frame->selection()->setSelection(newSelection);
1243             frame->revealSelection();
1244         }
1245     }
1246     // FIXME: I'm not sure all devices will want this off, but this is
1247     // currently turned off for Andriod.
1248 #if !ENABLE(DIRECTIONAL_PAD_NAVIGATION)
1249     else if (renderer() && !renderer()->isWidget())
1250         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
1251 #endif
1252 }
1253
1254 void Element::blur()
1255 {
1256     cancelFocusAppearanceUpdate();
1257     Document* doc = document();
1258     if (doc->focusedNode() == this) {
1259         if (doc->frame())
1260             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1261         else
1262             doc->setFocusedNode(0);
1263     }
1264 }
1265
1266 String Element::innerText() const
1267 {
1268     // We need to update layout, since plainText uses line boxes in the render tree.
1269     document()->updateLayoutIgnorePendingStylesheets();
1270
1271     if (!renderer())
1272         return textContent(true);
1273
1274     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1275 }
1276
1277 String Element::outerText() const
1278 {
1279     // Getting outerText is the same as getting innerText, only
1280     // setting is different. You would think this should get the plain
1281     // text for the outer range, but this is wrong, <br> for instance
1282     // would return different values for inner and outer text by such
1283     // a rule, but it doesn't in WinIE, and we want to match that.
1284     return innerText();
1285 }
1286
1287 String Element::title() const
1288 {
1289     return String();
1290 }
1291
1292 IntSize Element::minimumSizeForResizing() const
1293 {
1294     return hasRareData() ? rareData()->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1295 }
1296
1297 void Element::setMinimumSizeForResizing(const IntSize& size)
1298 {
1299     if (size == defaultMinimumSizeForResizing() && !hasRareData())
1300         return;
1301     ensureRareData()->m_minimumSizeForResizing = size;
1302 }
1303
1304 RenderStyle* Element::computedStyle()
1305 {
1306     if (RenderStyle* usedStyle = renderStyle())
1307         return usedStyle;
1308
1309     if (!attached())
1310         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1311         // document tree and figure out when to destroy the computed style for such elements.
1312         return 0;
1313
1314     ElementRareData* data = ensureRareData();
1315     if (!data->m_computedStyle)
1316         data->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
1317     return data->m_computedStyle.get();
1318 }
1319
1320 void Element::cancelFocusAppearanceUpdate()
1321 {
1322     if (hasRareData())
1323         rareData()->setNeedsFocusAppearanceUpdateSoonAfterAttach(false);
1324     if (document()->focusedNode() == this)
1325         document()->cancelFocusAppearanceUpdate();
1326 }
1327
1328 void Element::normalizeAttributes()
1329 {
1330     // Normalize attributes.
1331     NamedNodeMap* attrs = attributes(true);
1332     if (!attrs)
1333         return;
1334     unsigned numAttrs = attrs->length();
1335     for (unsigned i = 0; i < numAttrs; i++) {
1336         if (Attr* attr = attrs->attributeItem(i)->attr())
1337             attr->normalize();
1338     }
1339 }
1340
1341 // ElementTraversal API
1342 Element* Element::firstElementChild() const
1343 {
1344     Node* n = firstChild();
1345     while (n && !n->isElementNode())
1346         n = n->nextSibling();
1347     return static_cast<Element*>(n);
1348 }
1349
1350 Element* Element::lastElementChild() const
1351 {
1352     Node* n = lastChild();
1353     while (n && !n->isElementNode())
1354         n = n->previousSibling();
1355     return static_cast<Element*>(n);
1356 }
1357
1358 Element* Element::previousElementSibling() const
1359 {
1360     Node* n = previousSibling();
1361     while (n && !n->isElementNode())
1362         n = n->previousSibling();
1363     return static_cast<Element*>(n);
1364 }
1365
1366 Element* Element::nextElementSibling() const
1367 {
1368     Node* n = nextSibling();
1369     while (n && !n->isElementNode())
1370         n = n->nextSibling();
1371     return static_cast<Element*>(n);
1372 }
1373
1374 unsigned Element::childElementCount() const
1375 {
1376     unsigned count = 0;
1377     Node* n = firstChild();
1378     while (n) {
1379         count += n->isElementNode();
1380         n = n->nextSibling();
1381     }
1382     return count;
1383 }
1384
1385 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
1386 {
1387     if (selector.isEmpty()) {
1388         ec = SYNTAX_ERR;
1389         return false;
1390     }
1391
1392     bool strictParsing = !document()->inCompatMode();
1393     CSSParser p(strictParsing);
1394
1395     CSSSelectorList selectorList;
1396     p.parseSelector(selector, document(), selectorList);
1397
1398     if (!selectorList.first()) {
1399         ec = SYNTAX_ERR;
1400         return false;
1401     }
1402
1403     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1404     if (selectorList.selectorsNeedNamespaceResolution()) {
1405         ec = NAMESPACE_ERR;
1406         return false;
1407     }
1408
1409     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
1410     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
1411         if (selectorChecker.checkSelector(selector, this))
1412             return true;
1413     }
1414
1415     return false;
1416 }
1417
1418 KURL Element::getURLAttribute(const QualifiedName& name) const
1419 {
1420 #ifndef NDEBUG
1421     if (namedAttrMap) {
1422         if (Attribute* attribute = namedAttrMap->getAttributeItem(name))
1423             ASSERT(isURLAttribute(attribute));
1424     }
1425 #endif
1426     return document()->completeURL(deprecatedParseURL(getAttribute(name)));
1427 }
1428
1429 } // namespace WebCore