Implement support for the WinIE clientLeft and clientTop extensions.
[WebKit-https.git] / WebCore / dom / Element.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2001 Peter Kelly (pmk@post.com)
7  *           (C) 2001 Dirk Mueller (mueller@kde.org)
8  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
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., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25 #include "config.h"
26 #include "Element.h"
27
28 #include "cssstyleselector.h"
29 #include "Document.h"
30 #include "ExceptionCode.h"
31 #include "Frame.h"
32 #include "HTMLNames.h"
33 #include "NamedAttrMap.h"
34 #include "RenderBlock.h"
35 #include "SelectionController.h"
36 #include "TextStream.h"
37
38 namespace WebCore {
39
40 using namespace HTMLNames;
41
42 Element::Element(const QualifiedName& qName, Document *doc)
43     : ContainerNode(doc)
44     , m_updateFocusAppearanceTimer(this, &Element::updateFocusAppearanceTimerFired)
45     , m_needsFocusAppearanceUpdate(false)
46     , m_tagName(qName)
47 {
48 }
49
50 Element::~Element()
51 {
52     if (namedAttrMap)
53         namedAttrMap->detachFromElement();
54 }
55
56 PassRefPtr<Node> Element::cloneNode(bool deep)
57 {
58     ExceptionCode ec = 0;
59     RefPtr<Element> clone = document()->createElementNS(namespaceURI(), nodeName(), ec);
60     assert(!ec);
61     
62     // clone attributes
63     if (namedAttrMap)
64         *clone->attributes() = *namedAttrMap;
65
66     clone->copyNonAttributeProperties(this);
67     
68     if (deep)
69         cloneChildNodes(clone.get());
70
71     return clone.release();
72 }
73
74 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
75 {
76     if (namedAttrMap) {
77         namedAttrMap->removeNamedItem(name, ec);
78         if (ec == NOT_FOUND_ERR)
79             ec = 0;
80     }
81 }
82
83 void Element::setAttribute(const QualifiedName& name, const String &value)
84 {
85     ExceptionCode ec = 0;
86     setAttribute(name, value.impl(), ec);
87 }
88
89 // Virtual function, defined in base class.
90 NamedAttrMap *Element::attributes() const
91 {
92     return attributes(false);
93 }
94
95 NamedAttrMap* Element::attributes(bool readonly) const
96 {
97     updateStyleAttributeIfNeeded();
98     if (!readonly && !namedAttrMap)
99         createAttributeMap();
100     return namedAttrMap.get();
101 }
102
103 Node::NodeType Element::nodeType() const
104 {
105     return ELEMENT_NODE;
106 }
107
108 const AtomicStringList* Element::getClassList() const
109 {
110     return 0;
111 }
112
113 const AtomicString& Element::getIDAttribute() const
114 {
115     return namedAttrMap ? namedAttrMap->id() : nullAtom;
116 }
117
118 bool Element::hasAttribute(const QualifiedName& name) const
119 {
120     return hasAttributeNS(name.namespaceURI(), name.localName());
121 }
122
123 const AtomicString& Element::getAttribute(const QualifiedName& name) const
124 {
125     if (name == styleAttr)
126         updateStyleAttributeIfNeeded();
127
128     if (namedAttrMap)
129         if (Attribute* a = namedAttrMap->getAttributeItem(name))
130             return a->value();
131
132     return nullAtom;
133 }
134
135 void Element::scrollIntoView(bool alignToTop) 
136 {
137     document()->updateLayoutIgnorePendingStylesheets();
138     IntRect bounds = getRect();    
139     if (renderer()) {
140         // Align to the top / bottom and to the closest edge.
141         if (alignToTop)
142             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
143         else
144             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignBottomAlways);
145     }
146 }
147
148 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
149 {
150     document()->updateLayoutIgnorePendingStylesheets();
151     IntRect bounds = getRect();    
152     if (renderer()) {
153         if (centerIfNeeded)
154             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignCenterIfNeeded, RenderLayer::gAlignCenterIfNeeded);
155         else
156             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
157     }
158 }
159
160 void Element::scrollByUnits(int units, ScrollGranularity granularity)
161 {
162     document()->updateLayoutIgnorePendingStylesheets();
163     if (RenderObject *rend = renderer()) {
164         if (rend->hasOverflowClip()) {
165             ScrollDirection direction = ScrollDown;
166             if (units < 0) {
167                 direction = ScrollUp;
168                 units = -units;
169             }
170             rend->layer()->scroll(direction, granularity, units);
171         }
172     }
173 }
174
175 void Element::scrollByLines(int lines)
176 {
177     scrollByUnits(lines, ScrollByLine);
178 }
179
180 void Element::scrollByPages(int pages)
181 {
182     scrollByUnits(pages, ScrollByPage);
183 }
184
185 int Element::offsetLeft()
186 {
187     document()->updateLayoutIgnorePendingStylesheets();
188     if (RenderObject* rend = renderer())
189         return rend->offsetLeft();
190     return 0;
191 }
192
193 int Element::offsetTop()
194 {
195     document()->updateLayoutIgnorePendingStylesheets();
196     if (RenderObject* rend = renderer())
197         return rend->offsetTop();
198     return 0;
199 }
200
201 int Element::offsetWidth()
202 {
203     document()->updateLayoutIgnorePendingStylesheets();
204     if (RenderObject* rend = renderer())
205         return rend->offsetWidth();
206     return 0;
207 }
208
209 int Element::offsetHeight()
210 {
211     document()->updateLayoutIgnorePendingStylesheets();
212     if (RenderObject* rend = renderer())
213         return rend->offsetHeight();
214     return 0;
215 }
216
217 Element* Element::offsetParent()
218 {
219     document()->updateLayoutIgnorePendingStylesheets();
220     if (RenderObject* rend = renderer())
221         if (RenderObject* offsetParent = rend->offsetParent())
222             return static_cast<Element*>(offsetParent->element());
223     return 0;
224 }
225
226 int Element::clientLeft()
227 {
228     document()->updateLayoutIgnorePendingStylesheets();
229
230     if (RenderObject* rend = renderer())
231         return rend->clientLeft();
232     return 0;
233 }
234
235 int Element::clientTop()
236 {
237     document()->updateLayoutIgnorePendingStylesheets();
238
239     if (RenderObject* rend = renderer())
240         return rend->clientTop();
241     return 0;
242 }
243
244 int Element::clientWidth()
245 {
246     document()->updateLayoutIgnorePendingStylesheets();
247
248     // When in strict mode, clientWidth for the document
249     // element should return the width of the containing frame.
250     if (!document()->inCompatMode() && document()->documentElement() == this)
251         return document()->frame()->view()->visibleWidth();
252     
253     if (RenderObject* rend = renderer())
254         return rend->clientWidth();
255     return 0;
256 }
257
258 int Element::clientHeight()
259 {
260     document()->updateLayoutIgnorePendingStylesheets();
261
262     // When in strict mode, clientHeight for the document
263     // element should return the height of the containing frame.
264     if (!document()->inCompatMode() && document()->documentElement() == this)
265         return document()->frame()->view()->visibleHeight();
266     
267     if (RenderObject* rend = renderer())
268         return rend->clientHeight();
269     return 0;
270 }
271
272 int Element::scrollLeft()
273 {
274     document()->updateLayoutIgnorePendingStylesheets();
275     RenderObject* rend = renderer();
276     if (rend && rend->layer())
277         return rend->layer()->scrollXOffset();
278     return 0;
279 }
280
281 int Element::scrollTop()
282 {
283     document()->updateLayoutIgnorePendingStylesheets();
284     RenderObject* rend = renderer();
285     if (rend && rend->layer())
286         return rend->layer()->scrollYOffset();
287     return 0;
288 }
289
290 void Element::setScrollLeft(int newLeft)
291 {
292     document()->updateLayoutIgnorePendingStylesheets();
293     RenderObject *rend = renderer();
294     if (rend && rend->hasOverflowClip())
295         rend->layer()->scrollToXOffset(newLeft);
296 }
297
298 void Element::setScrollTop(int newTop)
299 {
300     document()->updateLayoutIgnorePendingStylesheets();
301     RenderObject *rend = renderer();
302     if (rend && rend->hasOverflowClip())
303         rend->layer()->scrollToYOffset(newTop);
304 }
305
306 int Element::scrollWidth()
307 {
308     document()->updateLayoutIgnorePendingStylesheets();
309     if (RenderObject* rend = renderer())
310         return rend->scrollWidth();
311     return 0;
312 }
313
314 int Element::scrollHeight()
315 {
316     document()->updateLayoutIgnorePendingStylesheets();
317     if (RenderObject* rend = renderer())
318         return rend->scrollHeight();
319     return 0;
320 }
321
322 static inline bool inHTMLDocument(const Element* e)
323 {
324     return e && e->document()->isHTMLDocument();
325 }
326
327 const AtomicString& Element::getAttribute(const String& name) const
328 {
329     String localName = inHTMLDocument(this) ? name.lower() : name;
330     if (localName == styleAttr.localName())
331         updateStyleAttributeIfNeeded();
332     
333     if (namedAttrMap)
334         if (Attribute* a = namedAttrMap->getAttributeItem(localName))
335             return a->value();
336     
337     return nullAtom;
338 }
339
340 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
341 {
342     return getAttribute(QualifiedName(nullAtom, localName.impl(), namespaceURI.impl()));
343 }
344
345 void Element::setAttribute(const String& name, const String& value, ExceptionCode& ec)
346 {
347     if (!Document::isValidName(name)) {
348         ec = INVALID_CHARACTER_ERR;
349         return;
350     }
351
352     String localName = inHTMLDocument(this) ? name.lower() : name;
353
354     // allocate attributemap if necessary
355     Attribute* old = attributes(false)->getAttributeItem(localName);
356
357     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
358     if (namedAttrMap->isReadOnlyNode()) {
359         ec = NO_MODIFICATION_ALLOWED_ERR;
360         return;
361     }
362     
363     if (inDocument())
364         document()->incDOMTreeVersion();
365
366     if (localName == idAttr.localName())
367         updateId(old ? old->value() : nullAtom, value);
368     
369     if (old && value.isNull())
370         namedAttrMap->removeAttribute(old->name());
371     else if (!old && !value.isNull())
372         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName.impl(), nullAtom), value.impl()));
373     else if (old && !value.isNull()) {
374         old->setValue(value);
375         attributeChanged(old);
376     }
377 }
378
379 void Element::setAttribute(const QualifiedName& name, StringImpl* value, ExceptionCode& ec)
380 {
381     if (inDocument())
382         document()->incDOMTreeVersion();
383
384     // allocate attributemap if necessary
385     Attribute* old = attributes(false)->getAttributeItem(name);
386
387     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
388     if (namedAttrMap->isReadOnlyNode()) {
389         ec = NO_MODIFICATION_ALLOWED_ERR;
390         return;
391     }
392
393     if (name == idAttr)
394         updateId(old ? old->value() : nullAtom, value);
395     
396     if (old && !value)
397         namedAttrMap->removeAttribute(name);
398     else if (!old && value)
399         namedAttrMap->addAttribute(createAttribute(name, value));
400     else if (old && value) {
401         old->setValue(value);
402         attributeChanged(old);
403     }
404 }
405
406 Attribute* Element::createAttribute(const QualifiedName& name, StringImpl* value)
407 {
408     return new Attribute(name, value);
409 }
410
411 void Element::setAttributeMap(NamedAttrMap* list)
412 {
413     if (inDocument())
414         document()->incDOMTreeVersion();
415
416     // If setting the whole map changes the id attribute, we need to call updateId.
417
418     Attribute *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idAttr) : 0;
419     Attribute *newId = list ? list->getAttributeItem(idAttr) : 0;
420
421     if (oldId || newId)
422         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
423
424     if (namedAttrMap)
425         namedAttrMap->element = 0;
426
427     namedAttrMap = list;
428
429     if (namedAttrMap) {
430         namedAttrMap->element = this;
431         unsigned len = namedAttrMap->length();
432         for (unsigned i = 0; i < len; i++)
433             attributeChanged(namedAttrMap->attrs[i]);
434         // FIXME: What about attributes that were in the old map that are not in the new map?
435     }
436 }
437
438 bool Element::hasAttributes() const
439 {
440     updateStyleAttributeIfNeeded();
441     return namedAttrMap && namedAttrMap->length() > 0;
442 }
443
444 String Element::nodeName() const
445 {
446     return m_tagName.toString();
447 }
448
449 String Element::nodeNamePreservingCase() const
450 {
451     return m_tagName.toString();
452 }
453
454 void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec)
455 {
456     checkSetPrefix(_prefix, ec);
457     if (ec)
458         return;
459
460     m_tagName.setPrefix(_prefix);
461 }
462
463 Node* Element::insertAdjacentElement(const String& where, Node* newChild, int& exception)
464 {
465     if (!newChild) {
466         // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
467         exception = TYPE_MISMATCH_ERR;
468         return 0;
469     }
470     
471     // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
472     // a document fragment is created and the elements appended in the correct order. This document
473     // fragment isn't returned anywhere.
474     //
475     // This is impossible for us to implement as the DOM tree does not allow for such structures,
476     // Opera also appears to disallow such usage.
477     
478     if (equalIgnoringCase(where, "beforeBegin")) {
479         if (Node* p = parent())
480             return p->insertBefore(newChild, this, exception) ? newChild : 0;
481     } else if (equalIgnoringCase(where, "afterBegin")) {
482         return insertBefore(newChild, firstChild(), exception) ? newChild : 0;
483     } else if (equalIgnoringCase(where, "beforeEnd")) {
484         return appendChild(newChild, exception) ? newChild : 0;
485     } else if (equalIgnoringCase(where, "afterEnd")) {
486         if (Node* p = parent())
487             return p->insertBefore(newChild, nextSibling(), exception) ? newChild : 0;
488     } else {
489         // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
490         exception = NOT_SUPPORTED_ERR;
491     }
492     return 0;
493 }
494
495 bool Element::contains(const Element* element) const
496 {
497     if (!element)
498         return false;
499     return this == element || element->isAncestor(this);
500 }
501
502 void Element::createAttributeMap() const
503 {
504     namedAttrMap = new NamedAttrMap(const_cast<Element*>(this));
505 }
506
507 bool Element::isURLAttribute(Attribute *attr) const
508 {
509     return false;
510 }
511
512 RenderStyle *Element::styleForRenderer(RenderObject *parentRenderer)
513 {
514     return document()->styleSelector()->styleForElement(this);
515 }
516
517 RenderObject *Element::createRenderer(RenderArena *arena, RenderStyle *style)
518 {
519     if (document()->documentElement() == this && style->display() == NONE) {
520         // Ignore display: none on root elements.  Force a display of block in that case.
521         RenderBlock* result = new (arena) RenderBlock(this);
522         if (result) result->setStyle(style);
523         return result;
524     }
525     return RenderObject::createObject(this, style);
526 }
527
528
529 void Element::insertedIntoDocument()
530 {
531     // need to do superclass processing first so inDocument() is true
532     // by the time we reach updateId
533     ContainerNode::insertedIntoDocument();
534
535     if (hasID()) {
536         NamedAttrMap* attrs = attributes(true);
537         if (attrs) {
538             Attribute* idItem = attrs->getAttributeItem(idAttr);
539             if (idItem && !idItem->isNull())
540                 updateId(nullAtom, idItem->value());
541         }
542     }
543 }
544
545 void Element::removedFromDocument()
546 {
547     if (hasID()) {
548         NamedAttrMap* attrs = attributes(true);
549         if (attrs) {
550             Attribute* idItem = attrs->getAttributeItem(idAttr);
551             if (idItem && !idItem->isNull())
552                 updateId(idItem->value(), nullAtom);
553         }
554     }
555
556     ContainerNode::removedFromDocument();
557 }
558
559 void Element::attach()
560 {
561 #if !defined(SPEED_DEBUG) || SPEED_DEBUG < 1
562     createRendererIfNeeded();
563 #endif
564     ContainerNode::attach();
565     if (needsFocusAppearanceUpdate() && !m_updateFocusAppearanceTimer.isActive() && document()->focusNode() == this)
566         m_updateFocusAppearanceTimer.startOneShot(0);
567 }
568
569 void Element::detach()
570 {
571     stopUpdateFocusAppearanceTimer();
572     ContainerNode::detach();
573 }
574
575 void Element::recalcStyle(StyleChange change)
576 {
577     // ### should go away and be done in renderobject
578     RenderStyle* _style = renderStyle();
579     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
580     
581     if (hasParentStyle && (change >= Inherit || changed())) {
582         RenderStyle *newStyle = document()->styleSelector()->styleForElement(this);
583         StyleChange ch = diff(_style, newStyle);
584         if (ch == Detach) {
585             if (attached())
586                 detach();
587             // ### Suboptimal. Style gets calculated again.
588             attach();
589             // attach recalulates the style for all children. No need to do it twice.
590             setChanged(false);
591             setHasChangedChild(false);
592             newStyle->deref(document()->renderArena());
593             return;
594         }
595         else if (ch != NoChange) {
596             if (newStyle)
597                 setRenderStyle(newStyle);
598         }
599         else if (changed() && newStyle && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
600             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
601             // fooled into believing this style is the same.  This is only necessary if the document actually uses
602             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
603             // descendants.
604             if (renderer())
605                 renderer()->setStyleInternal(newStyle);
606             else
607                 setRenderStyle(newStyle);
608         }
609
610         newStyle->deref(document()->renderArena());
611
612         if (change != Force) {
613             if (document()->usesDescendantRules())
614                 change = Force;
615             else
616                 change = ch;
617         }
618     }
619
620     for (Node *n = fastFirstChild(); n; n = n->nextSibling()) {
621         if (change >= Inherit || n->isTextNode() || n->hasChangedChild() || n->changed())
622             n->recalcStyle(change);
623     }
624
625     setChanged(false);
626     setHasChangedChild(false);
627 }
628
629 bool Element::childTypeAllowed(NodeType type)
630 {
631     switch (type) {
632         case ELEMENT_NODE:
633         case TEXT_NODE:
634         case COMMENT_NODE:
635         case PROCESSING_INSTRUCTION_NODE:
636         case CDATA_SECTION_NODE:
637         case ENTITY_REFERENCE_NODE:
638             return true;
639             break;
640         default:
641             return false;
642     }
643 }
644
645 void Element::dispatchAttrRemovalEvent(Attribute*)
646 {
647     assert(!eventDispatchForbidden());
648 #if 0
649     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
650         return;
651     ExceptionCode ec = 0;
652     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
653         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
654 #endif
655 }
656
657 void Element::dispatchAttrAdditionEvent(Attribute *attr)
658 {
659     assert(!eventDispatchForbidden());
660 #if 0
661     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
662         return;
663     ExceptionCode ec = 0;
664     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
665         attr->value(),document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
666 #endif
667 }
668
669 String Element::openTagStartToString() const
670 {
671     String result = "<" + nodeName();
672
673     NamedAttrMap *attrMap = attributes(true);
674
675     if (attrMap) {
676         unsigned numAttrs = attrMap->length();
677         for (unsigned i = 0; i < numAttrs; i++) {
678             result += " ";
679
680             Attribute *attribute = attrMap->attributeItem(i);
681             result += attribute->name().toString();
682             if (!attribute->value().isNull()) {
683                 result += "=\"";
684                 // FIXME: substitute entities for any instances of " or '
685                 result += attribute->value();
686                 result += "\"";
687             }
688         }
689     }
690
691     return result;
692 }
693
694 String Element::toString() const
695 {
696     String result = openTagStartToString();
697
698     if (hasChildNodes()) {
699         result += ">";
700
701         for (Node *child = firstChild(); child != NULL; child = child->nextSibling()) {
702             result += child->toString();
703         }
704
705         result += "</";
706         result += nodeName();
707         result += ">";
708     } else {
709         result += " />";
710     }
711
712     return result;
713 }
714
715 void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
716 {
717     if (!inDocument())
718         return;
719
720     if (oldId == newId)
721         return;
722
723     Document* doc = document();
724     if (!oldId.isEmpty())
725         doc->removeElementById(oldId, this);
726     if (!newId.isEmpty())
727         doc->addElementById(newId, this);
728 }
729
730 #ifndef NDEBUG
731 void Element::dump(TextStream *stream, DeprecatedString ind) const
732 {
733     updateStyleAttributeIfNeeded();
734     if (namedAttrMap) {
735         for (unsigned i = 0; i < namedAttrMap->length(); i++) {
736             Attribute *attr = namedAttrMap->attributeItem(i);
737             *stream << " " << attr->name().localName().deprecatedString().ascii()
738                     << "=\"" << attr->value().deprecatedString().ascii() << "\"";
739         }
740     }
741
742     ContainerNode::dump(stream,ind);
743 }
744 #endif
745
746 #ifndef NDEBUG
747 void Element::formatForDebugger(char *buffer, unsigned length) const
748 {
749     String result;
750     String s;
751     
752     s = nodeName();
753     if (s.length() > 0) {
754         result += s;
755     }
756           
757     s = getAttribute(idAttr);
758     if (s.length() > 0) {
759         if (result.length() > 0)
760             result += "; ";
761         result += "id=";
762         result += s;
763     }
764           
765     s = getAttribute(classAttr);
766     if (s.length() > 0) {
767         if (result.length() > 0)
768             result += "; ";
769         result += "class=";
770         result += s;
771     }
772           
773     strncpy(buffer, result.deprecatedString().latin1(), length - 1);
774 }
775 #endif
776
777 PassRefPtr<Attr> Element::setAttributeNode(Attr *attr, ExceptionCode& ec)
778 {
779     ASSERT(attr);
780     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
781 }
782
783 PassRefPtr<Attr> Element::removeAttributeNode(Attr *attr, ExceptionCode& ec)
784 {
785     if (!attr || attr->ownerElement() != this) {
786         ec = NOT_FOUND_ERR;
787         return 0;
788     }
789     if (document() != attr->document()) {
790         ec = WRONG_DOCUMENT_ERR;
791         return 0;
792     }
793
794     NamedAttrMap *attrs = attributes(true);
795     if (!attrs)
796         return 0;
797
798     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
799 }
800
801 void Element::setAttributeNS(const String& namespaceURI, const String& qualifiedName, const String& value, ExceptionCode& ec)
802 {
803     String prefix, localName;
804     if (!Document::parseQualifiedName(qualifiedName, prefix, localName)) {
805         ec = INVALID_CHARACTER_ERR;
806         return;
807     }
808     setAttribute(QualifiedName(prefix.impl(), localName.impl(), namespaceURI.impl()), value.impl(), ec);
809 }
810
811 void Element::removeAttribute(const String& name, ExceptionCode& ec)
812 {
813     String localName = inHTMLDocument(this) ? name.lower() : name;
814
815     if (namedAttrMap) {
816         namedAttrMap->removeNamedItem(localName, ec);
817         if (ec == NOT_FOUND_ERR)
818             ec = 0;
819     }
820 }
821
822 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
823 {
824     removeAttribute(QualifiedName(nullAtom, localName.impl(), namespaceURI.impl()), ec);
825 }
826
827 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
828 {
829     NamedAttrMap *attrs = attributes(true);
830     if (!attrs)
831         return 0;
832     String localName = inHTMLDocument(this) ? name.lower() : name;
833     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
834 }
835
836 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
837 {
838     NamedAttrMap *attrs = attributes(true);
839     if (!attrs)
840         return 0;
841     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName.impl(), namespaceURI.impl())));
842 }
843
844 bool Element::hasAttribute(const String& name) const
845 {
846     NamedAttrMap *attrs = attributes(true);
847     if (!attrs)
848         return false;
849     String localName = inHTMLDocument(this) ? name.lower() : name;
850     return attrs->getAttributeItem(localName);
851 }
852
853 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
854 {
855     NamedAttrMap *attrs = attributes(true);
856     if (!attrs)
857         return false;
858     return attrs->getAttributeItem(QualifiedName(nullAtom, localName.impl(), namespaceURI.impl()));
859 }
860
861 CSSStyleDeclaration *Element::style()
862 {
863     return 0;
864 }
865
866 void Element::focus()
867 {
868     Document* doc = document();
869     doc->updateLayout();
870     
871     if (!supportsFocus())
872         return;                
873         
874     doc->setFocusNode(this);
875
876     if (!isFocusable()) {
877         setNeedsFocusAppearanceUpdate(true);
878         return;
879     }
880         
881     updateFocusAppearance();
882 }
883
884 void Element::updateFocusAppearance()
885 {
886     if (this == rootEditableElement()) { 
887         Frame* frame = document()->frame();
888         if (!frame)
889             return;
890         
891         // FIXME: We should restore the previous selection if there is one.
892         Selection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? Selection(Position(this, 0), DOWNSTREAM) : Selection::selectionFromContentsOfNode(this);
893         
894         if (frame->shouldChangeSelection(newSelection)) {
895             frame->selectionController()->setSelection(newSelection);
896             frame->revealSelection();
897         }
898     } else if (renderer() && !renderer()->isWidget())
899         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
900 }
901
902 void Element::updateFocusAppearanceTimerFired(Timer<Element>*)
903 {
904     stopUpdateFocusAppearanceTimer();
905     Document* doc = document();
906     doc->updateLayout();
907     if (isFocusable())
908         updateFocusAppearance();
909 }
910     
911 void Element::blur()
912 {
913     stopUpdateFocusAppearanceTimer();
914     Document* doc = document();
915     if (doc->focusNode() == this)
916         doc->setFocusNode(0);
917 }
918
919 void Element::stopUpdateFocusAppearanceTimer()
920 {
921     if (m_updateFocusAppearanceTimer.isActive()) {
922         m_updateFocusAppearanceTimer.stop();
923         setNeedsFocusAppearanceUpdate(false);
924     }
925 }
926
927 }