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.
28 #include "CollectionType.h"
30 #include "FragmentScriptingPermission.h"
31 #include "HTMLNames.h"
32 #include "NamedNodeMap.h"
33 #include "ScrollTypes.h"
42 class ElementRareData;
45 class WebKitAnimationList;
47 enum SpellcheckAttributeState {
48 SpellcheckAttributeTrue,
49 SpellcheckAttributeFalse,
50 SpellcheckAttributeDefault
53 class Element : public ContainerNode {
55 static PassRefPtr<Element> create(const QualifiedName&, Document*);
58 DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
59 DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
60 DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
61 DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
62 DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
63 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
64 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
65 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
66 DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
67 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
68 DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
69 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
70 DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
71 DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
72 DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
73 DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
74 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
75 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
76 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
77 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
78 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
79 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
80 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
81 DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
82 DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
83 DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
85 // These four attribute event handler attributes are overridden by HTMLBodyElement
86 // and HTMLFrameSetElement to forward to the DOMWindow.
87 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
88 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
89 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
90 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
93 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
94 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
95 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
96 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
97 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
98 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
99 DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
100 DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
101 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
102 #if ENABLE(TOUCH_EVENTS)
103 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
104 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
105 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
106 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
108 #if ENABLE(FULLSCREEN_API)
109 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
110 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror);
113 bool hasAttribute(const QualifiedName&) const;
114 const AtomicString& getAttribute(const QualifiedName&) const;
115 void setAttribute(const QualifiedName&, const AtomicString& value);
116 void removeAttribute(const QualifiedName&);
118 // Typed getters and setters for language bindings.
119 int getIntegralAttribute(const QualifiedName& attributeName) const;
120 void setIntegralAttribute(const QualifiedName& attributeName, int value);
121 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
122 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
124 // Call this to get the value of an attribute that is known not to be the style
125 // attribute or one of the SVG animatable attributes.
126 bool fastHasAttribute(const QualifiedName&) const;
127 const AtomicString& fastGetAttribute(const QualifiedName&) const;
129 bool fastAttributeLookupAllowed(const QualifiedName&) const;
132 bool hasAttributes() const;
134 bool hasAttribute(const String& name) const;
135 bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
137 const AtomicString& getAttribute(const String& name) const;
138 const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
140 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
141 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
143 bool isIdAttributeName(const QualifiedName&) const;
144 const AtomicString& getIdAttribute() const;
145 void setIdAttribute(const AtomicString&);
147 // Call this to get the value of the id attribute for style resolution purposes.
148 // The value will already be lowercased if the document is in compatibility mode,
149 // so this function is not suitable for non-style uses.
150 const AtomicString& idForStyleResolution() const;
152 void scrollIntoView(bool alignToTop = true);
153 void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
155 void scrollByLines(int lines);
156 void scrollByPages(int pages);
162 Element* offsetParent();
167 virtual int scrollLeft();
168 virtual int scrollTop();
169 virtual void setScrollLeft(int);
170 virtual void setScrollTop(int);
171 virtual int scrollWidth();
172 virtual int scrollHeight();
174 LayoutRect boundsInRootViewSpace();
176 PassRefPtr<ClientRectList> getClientRects();
177 PassRefPtr<ClientRect> getBoundingClientRect();
179 // Returns the absolute bounding box translated into screen coordinates:
180 LayoutRect screenRect() const;
182 void removeAttribute(const String& name);
183 void removeAttributeNS(const String& namespaceURI, const String& localName);
185 PassRefPtr<Attr> getAttributeNode(const String& name);
186 PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
187 PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
188 PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
189 PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
191 virtual CSSStyleDeclaration* style();
193 const QualifiedName& tagQName() const { return m_tagName; }
194 String tagName() const { return nodeName(); }
195 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
197 // A fast function for checking the local name against another atomic string.
198 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
199 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
201 const AtomicString& localName() const { return m_tagName.localName(); }
202 const AtomicString& prefix() const { return m_tagName.prefix(); }
203 const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
205 virtual KURL baseURI() const;
207 virtual String nodeName() const;
209 PassRefPtr<Element> cloneElementWithChildren();
210 PassRefPtr<Element> cloneElementWithoutChildren();
212 void normalizeAttributes();
213 String nodeNamePreservingCase() const;
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 // Only called by the parser immediately after element construction.
223 void parserSetAttributeMap(PassOwnPtr<NamedNodeMap>, FragmentScriptingPermission);
225 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
227 ElementAttributeData* attributeData() const { return m_attributeMap ? m_attributeMap->attributeData() : 0; }
228 ElementAttributeData* ensureAttributeData() const { return attributes()->attributeData(); }
230 void setAttributesFromElement(const Element&);
232 virtual void copyNonAttributeProperties(const Element* source);
234 virtual void attach();
235 virtual void detach();
236 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
237 void recalcStyle(StyleChange = NoChange);
239 ShadowRoot* shadowRoot() const;
240 void setShadowRoot(PassRefPtr<ShadowRoot>, ExceptionCode&);
241 ShadowRoot* ensureShadowRoot();
242 void removeShadowRoot();
244 virtual const AtomicString& shadowPseudoId() const;
245 void setShadowPseudoId(const AtomicString&, ExceptionCode& = ASSERT_NO_EXCEPTION);
247 RenderStyle* computedStyle(PseudoId = NOPSEUDO);
249 void setStyleAffectedByEmpty();
250 bool styleAffectedByEmpty() const;
252 AtomicString computeInheritedLanguage() const;
254 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
256 virtual bool isURLAttribute(Attribute*) const;
258 KURL getURLAttribute(const QualifiedName&) const;
259 KURL getNonEmptyURLAttribute(const QualifiedName&) const;
261 virtual const QualifiedName& imageSourceAttributeName() const;
262 virtual String target() const { return String(); }
264 virtual void focus(bool restorePreviousSelection = true);
265 virtual void updateFocusAppearance(bool restorePreviousSelection);
271 virtual String title() const;
273 void updateId(const AtomicString& oldId, const AtomicString& newId);
274 void updateName(const AtomicString& oldName, const AtomicString& newName);
276 void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
277 void willRemoveAttribute(const QualifiedName&, const AtomicString& value);
278 void didModifyAttribute(Attribute*);
279 void didRemoveAttribute(Attribute*);
281 LayoutSize minimumSizeForResizing() const;
282 void setMinimumSizeForResizing(const LayoutSize&);
284 // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
285 virtual void documentWillSuspendForPageCache() { }
286 virtual void documentDidResumeFromPageCache() { }
288 // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
289 virtual void mediaVolumeDidChange() { }
291 // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
292 virtual void privateBrowsingStateDidChange() { }
294 virtual void didBecomeFullscreenElement() { }
295 virtual void willStopBeingFullscreenElement() { }
297 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
298 virtual void finishParsingChildren();
299 virtual void beginParsingChildren();
301 // ElementTraversal API
302 Element* firstElementChild() const;
303 Element* lastElementChild() const;
304 Element* previousElementSibling() const;
305 Element* nextElementSibling() const;
306 unsigned childElementCount() const;
308 #if ENABLE(STYLE_SCOPED)
309 void registerScopedHTMLStyleChild();
310 void unregisterScopedHTMLStyleChild();
311 bool hasScopedHTMLStyleChild() const;
312 size_t numberOfScopedHTMLStyleChildren() const;
315 bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
317 DOMTokenList* classList();
318 DOMTokenList* optionalClassList() const;
320 DOMStringMap* dataset();
323 virtual bool isMathMLElement() const { return false; }
325 static bool isMathMLElement() { return false; }
329 virtual bool isMediaElement() const { return false; }
332 #if ENABLE(INPUT_SPEECH)
333 virtual bool isInputFieldSpeechButtonElement() const { return false; }
336 virtual bool isFormControlElement() const { return false; }
337 virtual bool isEnabledFormControl() const { return true; }
338 virtual bool isReadOnlyFormControl() const { return false; }
339 virtual bool isSpinButtonElement() const { return false; }
340 virtual bool isTextFormControl() const { return false; }
341 virtual bool isOptionalFormControl() const { return false; }
342 virtual bool isRequiredFormControl() const { return false; }
343 virtual bool isDefaultButtonForForm() const { return false; }
344 virtual bool willValidate() const { return false; }
345 virtual bool isValidFormControlElement() { return false; }
346 virtual bool hasUnacceptableValue() const { return false; }
347 virtual bool isInRange() const { return false; }
348 virtual bool isOutOfRange() const { return false; }
349 virtual bool isFrameElementBase() const { return false; }
351 virtual bool canContainRangeEndPoint() const { return true; }
353 virtual const AtomicString& formControlName() const { return nullAtom; }
354 virtual const AtomicString& formControlType() const { return nullAtom; }
356 virtual bool wasChangedSinceLastFormControlChangeEvent() const;
357 virtual void setChangedSinceLastFormControlChangeEvent(bool);
358 virtual void dispatchFormControlChangeEvent() { }
361 virtual bool childShouldCreateRenderer(Node*) const;
364 #if ENABLE(FULLSCREEN_API)
366 ALLOW_KEYBOARD_INPUT = 1
369 void webkitRequestFullScreen(unsigned short flags);
370 virtual bool containsFullScreenElement() const;
371 virtual void setContainsFullScreenElement(bool);
372 virtual void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool);
375 virtual bool isSpellCheckingEnabled() const;
377 PassRefPtr<WebKitAnimationList> webkitGetAnimations() const;
379 PassRefPtr<RenderStyle> styleForRenderer();
382 Element(const QualifiedName& tagName, Document* document, ConstructionType type)
383 : ContainerNode(document, type)
388 virtual void willRemove();
389 virtual void insertedIntoDocument();
390 virtual void removedFromDocument();
391 virtual void insertedIntoTree(bool);
392 virtual void removedFromTree(bool);
393 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
394 virtual bool willRecalcStyle(StyleChange) { return true; }
395 virtual void didRecalcStyle(StyleChange) { }
396 virtual PassRefPtr<RenderStyle> customStyleForRenderer();
398 virtual bool shouldRegisterAsNamedItem() const { return false; }
399 virtual bool shouldRegisterAsExtraNamedItem() const { return false; }
401 // The implementation of Element::attributeChanged() calls the following two functions.
402 // They are separated to allow a different flow of control in StyledElement::attributeChanged().
403 void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
404 void updateAfterAttributeChanged(Attribute*);
406 void idAttributeChanged(Attribute*);
408 HTMLCollection* ensureCachedHTMLCollection(CollectionType);
411 void scrollByUnits(int units, ScrollGranularity);
413 virtual void setPrefix(const AtomicString&, ExceptionCode&);
414 virtual NodeType nodeType() const;
415 virtual bool childTypeAllowed(NodeType) const;
417 void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value);
418 virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
421 virtual void formatForDebugger(char* buffer, unsigned length) const;
424 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
426 void createAttributeMap() const;
428 virtual void updateStyleAttribute() const { }
431 virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
434 void cancelFocusAppearanceUpdate();
436 virtual const AtomicString& virtualPrefix() const { return prefix(); }
437 virtual const AtomicString& virtualLocalName() const { return localName(); }
438 virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
439 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
441 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
443 virtual PassRefPtr<Node> cloneNode(bool deep);
444 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren();
446 QualifiedName m_tagName;
447 virtual OwnPtr<NodeRareData> createRareData();
449 ElementRareData* rareData() const;
450 ElementRareData* ensureRareData();
452 SpellcheckAttributeState spellcheckAttributeState() const;
454 void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
455 void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName);
458 mutable OwnPtr<NamedNodeMap> m_attributeMap;
461 inline Element* toElement(Node* node)
463 ASSERT(!node || node->isElementNode());
464 return static_cast<Element*>(node);
467 inline const Element* toElement(const Node* node)
469 ASSERT(!node || node->isElementNode());
470 return static_cast<const Element*>(node);
473 // This will catch anyone doing an unnecessary cast.
474 void toElement(const Element*);
476 inline bool Node::hasTagName(const QualifiedName& name) const
478 return isElementNode() && toElement(this)->hasTagName(name);
481 inline bool Node::hasLocalName(const AtomicString& name) const
483 return isElementNode() && toElement(this)->hasLocalName(name);
486 inline bool Node::hasAttributes() const
488 return isElementNode() && toElement(this)->hasAttributes();
491 inline NamedNodeMap* Node::attributes() const
493 return isElementNode() ? toElement(this)->attributes() : 0;
496 inline Element* Node::parentElement() const
498 ContainerNode* parent = parentNode();
499 return parent && parent->isElementNode() ? toElement(parent) : 0;
502 inline NamedNodeMap* Element::attributes(bool readonly) const
504 if (!isStyleAttributeValid())
505 updateStyleAttribute();
508 if (!areSVGAttributesValid())
509 updateAnimatedSVGAttribute(anyQName());
512 if (!readonly && !m_attributeMap)
513 createAttributeMap();
514 return m_attributeMap.get();
517 inline void Element::setAttributesFromElement(const Element& other)
519 if (NamedNodeMap* attributeMap = other.attributes(true))
520 attributes(false)->setAttributes(*attributeMap);
523 inline void Element::updateName(const AtomicString& oldName, const AtomicString& newName)
528 if (oldName == newName)
531 if (shouldRegisterAsNamedItem())
532 updateNamedItemRegistration(oldName, newName);
535 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
543 TreeScope* scope = treeScope();
544 if (!oldId.isEmpty())
545 scope->removeElementById(oldId, this);
546 if (!newId.isEmpty())
547 scope->addElementById(newId, this);
549 if (shouldRegisterAsExtraNamedItem())
550 updateExtraNamedItemRegistration(oldId, newId);
553 inline void Element::willRemoveAttribute(const QualifiedName& name, const AtomicString& value)
556 willModifyAttribute(name, value, nullAtom);
559 inline bool Element::fastHasAttribute(const QualifiedName& name) const
561 ASSERT(fastAttributeLookupAllowed(name));
562 return m_attributeMap && m_attributeMap->getAttributeItem(name);
565 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
567 ASSERT(fastAttributeLookupAllowed(name));
568 if (m_attributeMap) {
569 if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
570 return attribute->value();
575 inline const AtomicString& Element::idForStyleResolution() const
578 return attributeData()->idForStyleResolution();
581 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
583 // FIXME: This check is probably not correct for the case where the document has an id attribute
584 // with a non-null namespace, because it will return false, a false negative, if the prefixes
585 // don't match but the local name and namespace both do. However, since this has been like this
586 // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
587 return attributeName == document()->idAttributeName();
590 inline const AtomicString& Element::getIdAttribute() const
592 return fastGetAttribute(document()->idAttributeName());
595 inline void Element::setIdAttribute(const AtomicString& value)
597 setAttribute(document()->idAttributeName(), value);
600 inline Element* firstElementChild(const ContainerNode* container)
602 ASSERT_ARG(container, container);
603 Node* child = container->firstChild();
604 while (child && !child->isElementNode())
605 child = child->nextSibling();
606 return static_cast<Element*>(child);