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 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
29 #include "ExceptionCodePlaceholder.h"
30 #include "FragmentScriptingPermission.h"
31 #include "NamedNodeMap.h"
32 #include "ScrollTypes.h"
41 class ElementRareData;
44 class WebKitAnimationList;
46 enum SpellcheckAttributeState {
47 SpellcheckAttributeTrue,
48 SpellcheckAttributeFalse,
49 SpellcheckAttributeDefault
52 class Element : public ContainerNode {
54 static PassRefPtr<Element> create(const QualifiedName&, Document*);
57 DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
58 DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
59 DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
60 DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
61 DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
62 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
63 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
64 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
65 DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
66 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
67 DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
68 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
69 DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
70 DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
71 DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
72 DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
73 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
74 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
75 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
76 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
77 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
78 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
79 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
80 DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
81 DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
82 DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
84 // These four attribute event handler attributes are overridden by HTMLBodyElement
85 // and HTMLFrameSetElement to forward to the DOMWindow.
86 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
87 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
88 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
89 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
92 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
93 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
94 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
95 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
96 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
97 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
98 DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
99 DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
100 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
101 #if ENABLE(TOUCH_EVENTS)
102 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
103 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
104 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
105 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
107 #if ENABLE(FULLSCREEN_API)
108 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
111 bool hasAttribute(const QualifiedName&) const;
112 const AtomicString& getAttribute(const QualifiedName&) const;
113 void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&);
114 void removeAttribute(const QualifiedName&, ExceptionCode&);
116 // Typed getters and setters for language bindings.
117 int getIntegralAttribute(const QualifiedName& attributeName) const;
118 void setIntegralAttribute(const QualifiedName& attributeName, int value);
119 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
120 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
122 // Call this to get the value of an attribute that is known not to be the style
123 // attribute or one of the SVG animatable attributes.
124 bool fastHasAttribute(const QualifiedName&) const;
125 const AtomicString& fastGetAttribute(const QualifiedName&) const;
127 bool fastAttributeLookupAllowed(const QualifiedName&) const;
130 bool hasAttributes() const;
132 bool hasAttribute(const String& name) const;
133 bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
135 const AtomicString& getAttribute(const String& name) const;
136 const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
138 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
139 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
141 bool isIdAttributeName(const QualifiedName&) const;
142 const AtomicString& getIdAttribute() const;
143 void setIdAttribute(const AtomicString&);
145 // Call this to get the value of the id attribute for style resolution purposes.
146 // The value will already be lowercased if the document is in compatibility mode,
147 // so this function is not suitable for non-style uses.
148 const AtomicString& idForStyleResolution() const;
150 void scrollIntoView(bool alignToTop = true);
151 void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
153 void scrollByLines(int lines);
154 void scrollByPages(int pages);
160 Element* offsetParent();
165 virtual int scrollLeft();
166 virtual int scrollTop();
167 virtual void setScrollLeft(int);
168 virtual void setScrollTop(int);
169 virtual int scrollWidth();
170 virtual int scrollHeight();
172 LayoutRect boundsInRootViewSpace();
174 PassRefPtr<ClientRectList> getClientRects();
175 PassRefPtr<ClientRect> getBoundingClientRect();
177 // Returns the absolute bounding box translated into screen coordinates:
178 LayoutRect screenRect() const;
180 void removeAttribute(const String& name, ExceptionCode&);
181 void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
183 PassRefPtr<Attr> getAttributeNode(const String& name);
184 PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
185 PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
186 PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
187 PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
189 virtual CSSStyleDeclaration* style();
191 const QualifiedName& tagQName() const { return m_tagName; }
192 String tagName() const { return nodeName(); }
193 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
195 // A fast function for checking the local name against another atomic string.
196 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
197 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
199 const AtomicString& localName() const { return m_tagName.localName(); }
200 const AtomicString& prefix() const { return m_tagName.prefix(); }
201 const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
203 virtual KURL baseURI() const;
205 virtual String nodeName() const;
207 PassRefPtr<Element> cloneElementWithChildren();
208 PassRefPtr<Element> cloneElementWithoutChildren();
210 void normalizeAttributes();
211 String nodeNamePreservingCase() const;
213 // convenience methods which ignore exceptions
214 void setAttribute(const QualifiedName&, const AtomicString& value);
215 void setBooleanAttribute(const QualifiedName& name, bool);
217 NamedNodeMap* attributes(bool readonly = false) const;
219 // This method is called whenever an attribute is added, changed or removed.
220 virtual void attributeChanged(Attribute*, bool preserveDecls = false);
222 void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed);
223 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
225 virtual void copyNonAttributeProperties(const Element* source);
227 virtual void attach();
228 virtual void detach();
229 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
230 void recalcStyle(StyleChange = NoChange);
232 ShadowRoot* shadowRoot() const;
233 void setShadowRoot(PassRefPtr<ShadowRoot>, ExceptionCode&);
234 ShadowRoot* ensureShadowRoot();
235 void removeShadowRoot();
237 virtual const AtomicString& shadowPseudoId() const;
238 void setShadowPseudoId(const AtomicString&, ExceptionCode& = ASSERT_NO_EXCEPTION);
240 RenderStyle* computedStyle(PseudoId = NOPSEUDO);
242 void setStyleAffectedByEmpty();
243 bool styleAffectedByEmpty() const;
245 AtomicString computeInheritedLanguage() const;
247 void dispatchAttrRemovalEvent(Attribute*);
248 void dispatchAttrAdditionEvent(Attribute*);
250 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
252 virtual bool isURLAttribute(Attribute*) const;
254 KURL getURLAttribute(const QualifiedName&) const;
255 KURL getNonEmptyURLAttribute(const QualifiedName&) const;
257 virtual const QualifiedName& imageSourceAttributeName() const;
258 virtual String target() const { return String(); }
260 virtual void focus(bool restorePreviousSelection = true);
261 virtual void updateFocusAppearance(bool restorePreviousSelection);
267 virtual String title() const;
269 void updateId(const AtomicString& oldId, const AtomicString& newId);
271 LayoutSize minimumSizeForResizing() const;
272 void setMinimumSizeForResizing(const LayoutSize&);
274 // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
275 virtual void documentWillBecomeInactive() { }
276 virtual void documentDidBecomeActive() { }
278 // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
279 virtual void mediaVolumeDidChange() { }
281 // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
282 virtual void privateBrowsingStateDidChange() { }
284 virtual void didBecomeFullscreenElement() { }
285 virtual void willStopBeingFullscreenElement() { }
287 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
288 virtual void finishParsingChildren();
289 virtual void beginParsingChildren();
291 // ElementTraversal API
292 Element* firstElementChild() const;
293 Element* lastElementChild() const;
294 Element* previousElementSibling() const;
295 Element* nextElementSibling() const;
296 unsigned childElementCount() const;
298 bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
300 DOMTokenList* classList();
301 DOMTokenList* optionalClassList() const;
303 DOMStringMap* dataset();
306 virtual bool isMathMLElement() const { return false; }
308 static bool isMathMLElement() { return false; }
312 virtual bool isMediaElement() const { return false; }
315 #if ENABLE(INPUT_SPEECH)
316 virtual bool isInputFieldSpeechButtonElement() const { return false; }
319 virtual bool isFormControlElement() const { return false; }
320 virtual bool isEnabledFormControl() const { return true; }
321 virtual bool isReadOnlyFormControl() const { return false; }
322 virtual bool isSpinButtonElement() const { return false; }
323 virtual bool isTextFormControl() const { return false; }
324 virtual bool isOptionalFormControl() const { return false; }
325 virtual bool isRequiredFormControl() const { return false; }
326 virtual bool isDefaultButtonForForm() const { return false; }
327 virtual bool willValidate() const { return false; }
328 virtual bool isValidFormControlElement() { return false; }
329 virtual bool hasUnacceptableValue() const { return false; }
330 virtual bool isInRange() const { return false; }
331 virtual bool isOutOfRange() const { return false; }
332 virtual bool isFrameElementBase() const { return false; }
334 virtual bool canContainRangeEndPoint() const { return true; }
336 virtual const AtomicString& formControlName() const { return nullAtom; }
337 virtual const AtomicString& formControlType() const { return nullAtom; }
339 virtual bool shouldSaveAndRestoreFormControlState() const { return true; }
340 virtual bool saveFormControlState(String&) const { return false; }
341 virtual void restoreFormControlState(const String&) { }
343 virtual bool wasChangedSinceLastFormControlChangeEvent() const;
344 virtual void setChangedSinceLastFormControlChangeEvent(bool);
345 virtual void dispatchFormControlChangeEvent() { }
348 virtual bool childShouldCreateRenderer(Node*) const;
351 #if ENABLE(FULLSCREEN_API)
353 ALLOW_KEYBOARD_INPUT = 1
356 void webkitRequestFullScreen(unsigned short flags);
357 virtual bool containsFullScreenElement() const;
358 virtual void setContainsFullScreenElement(bool);
359 virtual void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
362 virtual bool isSpellCheckingEnabled() const;
364 PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
366 PassRefPtr<RenderStyle> styleForRenderer();
369 Element(const QualifiedName& tagName, Document* document, ConstructionType type)
370 : ContainerNode(document, type)
375 virtual void willRemove();
376 virtual void insertedIntoDocument();
377 virtual void removedFromDocument();
378 virtual void insertedIntoTree(bool);
379 virtual void removedFromTree(bool);
380 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
381 virtual bool willRecalcStyle(StyleChange) { return true; }
382 virtual void didRecalcStyle(StyleChange) { }
383 virtual PassRefPtr<RenderStyle> customStyleForRenderer();
385 // The implementation of Element::attributeChanged() calls the following two functions.
386 // They are separated to allow a different flow of control in StyledElement::attributeChanged().
387 void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
388 void updateAfterAttributeChanged(Attribute*);
390 void idAttributeChanged(Attribute*);
393 void scrollByUnits(int units, ScrollGranularity);
395 virtual void setPrefix(const AtomicString&, ExceptionCode&);
396 virtual NodeType nodeType() const;
397 virtual bool childTypeAllowed(NodeType) const;
399 virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
402 virtual void formatForDebugger(char* buffer, unsigned length) const;
405 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
407 void createAttributeMap() const;
409 virtual void updateStyleAttribute() const { }
412 virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
415 void cancelFocusAppearanceUpdate();
417 virtual const AtomicString& virtualPrefix() const { return prefix(); }
418 virtual const AtomicString& virtualLocalName() const { return localName(); }
419 virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
420 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
422 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
424 virtual PassRefPtr<Node> cloneNode(bool deep);
425 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
427 QualifiedName m_tagName;
428 virtual OwnPtr<NodeRareData> createRareData();
430 ElementRareData* rareData() const;
431 ElementRareData* ensureRareData();
433 SpellcheckAttributeState spellcheckAttributeState() const;
436 mutable RefPtr<NamedNodeMap> m_attributeMap;
439 inline Element* toElement(Node* node)
441 ASSERT(!node || node->isElementNode());
442 return static_cast<Element*>(node);
445 inline const Element* toElement(const Node* node)
447 ASSERT(!node || node->isElementNode());
448 return static_cast<const Element*>(node);
451 // This will catch anyone doing an unnecessary cast.
452 void toElement(const Element*);
454 inline bool Node::hasTagName(const QualifiedName& name) const
456 return isElementNode() && toElement(this)->hasTagName(name);
459 inline bool Node::hasLocalName(const AtomicString& name) const
461 return isElementNode() && toElement(this)->hasLocalName(name);
464 inline bool Node::hasAttributes() const
466 return isElementNode() && toElement(this)->hasAttributes();
469 inline NamedNodeMap* Node::attributes() const
471 return isElementNode() ? toElement(this)->attributes() : 0;
474 inline Element* Node::parentElement() const
476 ContainerNode* parent = parentNode();
477 return parent && parent->isElementNode() ? toElement(parent) : 0;
480 inline NamedNodeMap* Element::attributes(bool readonly) const
482 if (!isStyleAttributeValid())
483 updateStyleAttribute();
486 if (!areSVGAttributesValid())
487 updateAnimatedSVGAttribute(anyQName());
490 if (!readonly && !m_attributeMap)
491 createAttributeMap();
492 return m_attributeMap.get();
495 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
503 TreeScope* scope = treeScope();
504 if (!oldId.isEmpty())
505 scope->removeElementById(oldId, this);
506 if (!newId.isEmpty())
507 scope->addElementById(newId, this);
510 inline bool Element::fastHasAttribute(const QualifiedName& name) const
512 ASSERT(fastAttributeLookupAllowed(name));
513 return m_attributeMap && m_attributeMap->getAttributeItem(name);
516 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
518 ASSERT(fastAttributeLookupAllowed(name));
519 if (m_attributeMap) {
520 if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
521 return attribute->value();
526 inline const AtomicString& Element::idForStyleResolution() const
529 return m_attributeMap->idForStyleResolution();
532 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
534 // FIXME: This check is probably not correct for the case where the document has an id attribute
535 // with a non-null namespace, because it will return false, a false negative, if the prefixes
536 // don't match but the local name and namespace both do. However, since this has been like this
537 // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
538 return attributeName == document()->idAttributeName();
541 inline const AtomicString& Element::getIdAttribute() const
543 return fastGetAttribute(document()->idAttributeName());
546 inline void Element::setIdAttribute(const AtomicString& value)
548 setAttribute(document()->idAttributeName(), value);
551 inline Element* firstElementChild(const ContainerNode* container)
553 ASSERT_ARG(container, container);
554 Node* child = container->firstChild();
555 while (child && !child->isElementNode())
556 child = child->nextSibling();
557 return static_cast<Element*>(child);