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 "FragmentScriptingPermission.h"
30 #include "NamedNodeMap.h"
31 #include "ScrollTypes.h"
40 class ElementRareData;
43 enum SpellcheckAttributeState {
44 SpellcheckAttributeTrue,
45 SpellcheckAttributeFalse,
46 SpellcheckAttributeDefault
49 class Element : public ContainerNode {
51 static PassRefPtr<Element> create(const QualifiedName&, Document*);
54 DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
55 DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
56 DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
57 DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
58 DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
59 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
60 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
61 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
62 DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
63 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
64 DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
65 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
66 DEFINE_ATTRIBUTE_EVENT_LISTENER(formchange);
67 DEFINE_ATTRIBUTE_EVENT_LISTENER(forminput);
68 DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
69 DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
70 DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
71 DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
72 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
73 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
74 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
75 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
76 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
77 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
78 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
79 DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
80 DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
81 DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
83 // These four attribute event handler attributes are overridden by HTMLBodyElement
84 // and HTMLFrameSetElement to forward to the DOMWindow.
85 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
86 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
87 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
88 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
91 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
92 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
93 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
94 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
95 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
96 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
97 DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
98 DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
99 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
100 #if ENABLE(TOUCH_EVENTS)
101 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
102 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
103 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
104 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
106 #if ENABLE(FULLSCREEN_API)
107 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange);
110 virtual PassRefPtr<DocumentFragment> deprecatedCreateContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
112 bool hasAttribute(const QualifiedName&) const;
113 const AtomicString& getAttribute(const QualifiedName&) const;
114 void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&);
115 void removeAttribute(const QualifiedName&, ExceptionCode&);
117 // Typed getters and setters for language bindings.
118 int getIntegralAttribute(const QualifiedName& attributeName) const;
119 void setIntegralAttribute(const QualifiedName& attributeName, int value);
120 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
121 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
123 // Call this to get the value of an attribute that is known not to be the style
124 // attribute or one of the SVG animatable attributes.
125 bool fastHasAttribute(const QualifiedName&) const;
126 const AtomicString& fastGetAttribute(const QualifiedName&) const;
128 bool hasAttributes() const;
130 bool hasAttribute(const String& name) const;
131 bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
133 const AtomicString& getAttribute(const String& name) const;
134 const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
136 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
137 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
139 bool isIdAttributeName(const QualifiedName&) const;
140 const AtomicString& getIdAttribute() const;
141 void setIdAttribute(const AtomicString&);
143 // Call this to get the value of the id attribute for style resolution purposes.
144 // The value will already be lowercased if the document is in compatibility mode,
145 // so this function is not suitable for non-style uses.
146 const AtomicString& idForStyleResolution() const;
148 void scrollIntoView(bool alignToTop = true);
149 void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
151 void scrollByLines(int lines);
152 void scrollByPages(int pages);
158 Element* offsetParent();
163 virtual int scrollLeft() const;
164 virtual int scrollTop() const;
165 virtual void setScrollLeft(int);
166 virtual void setScrollTop(int);
167 virtual int scrollWidth() const;
168 virtual int scrollHeight() const;
170 IntRect boundsInWindowSpace() const;
172 PassRefPtr<ClientRectList> getClientRects() const;
173 PassRefPtr<ClientRect> getBoundingClientRect() const;
175 // Returns the absolute bounding box translated into screen coordinates:
176 IntRect screenRect() const;
178 void removeAttribute(const String& name, ExceptionCode&);
179 void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
181 PassRefPtr<Attr> getAttributeNode(const String& name);
182 PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
183 PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
184 PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
185 PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
187 virtual CSSStyleDeclaration* style();
189 const QualifiedName& tagQName() const { return m_tagName; }
190 String tagName() const { return nodeName(); }
191 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
193 // A fast function for checking the local name against another atomic string.
194 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
195 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
197 const AtomicString& localName() const { return m_tagName.localName(); }
198 const AtomicString& prefix() const { return m_tagName.prefix(); }
199 const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
201 virtual KURL baseURI() const;
203 virtual String nodeName() const;
205 PassRefPtr<Element> cloneElementWithChildren();
206 PassRefPtr<Element> cloneElementWithoutChildren();
208 void normalizeAttributes();
209 String nodeNamePreservingCase() const;
211 // convenience methods which ignore exceptions
212 void setAttribute(const QualifiedName&, const AtomicString& value);
213 void setBooleanAttribute(const QualifiedName& name, bool);
214 // Please don't use setCStringAttribute in performance-sensitive code;
215 // use a static AtomicString value instead to avoid the conversion overhead.
216 void setCStringAttribute(const QualifiedName&, const char* cStringValue);
218 NamedNodeMap* attributes(bool readonly = false) const;
220 // This method is called whenever an attribute is added, changed or removed.
221 virtual void attributeChanged(Attribute*, bool preserveDecls = false);
223 void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed);
224 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
226 virtual void copyNonAttributeProperties(const Element* /*source*/) { }
228 virtual void attach();
229 virtual void detach();
230 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
231 virtual void recalcStyle(StyleChange = NoChange);
234 void setShadowRoot(PassRefPtr<Node>);
235 virtual const AtomicString& shadowPseudoId() const;
237 RenderStyle* computedStyle(PseudoId = NOPSEUDO);
239 AtomicString computeInheritedLanguage() const;
241 void dispatchAttrRemovalEvent(Attribute*);
242 void dispatchAttrAdditionEvent(Attribute*);
244 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
246 virtual bool isURLAttribute(Attribute*) const;
248 KURL getURLAttribute(const QualifiedName&) const;
249 KURL getNonEmptyURLAttribute(const QualifiedName&) const;
251 virtual const QualifiedName& imageSourceAttributeName() const;
252 virtual String target() const { return String(); }
254 virtual void focus(bool restorePreviousSelection = true);
255 virtual void updateFocusAppearance(bool restorePreviousSelection);
258 String innerText() const;
259 String outerText() const;
261 virtual String title() const;
263 String openTagStartToString() const;
265 void updateId(const AtomicString& oldId, const AtomicString& newId);
267 IntSize minimumSizeForResizing() const;
268 void setMinimumSizeForResizing(const IntSize&);
270 // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
271 virtual void documentWillBecomeInactive() { }
272 virtual void documentDidBecomeActive() { }
274 // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
275 virtual void mediaVolumeDidChange() { }
277 // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this.
278 virtual void privateBrowsingStateDidChange() { }
280 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
281 virtual void finishParsingChildren();
282 virtual void beginParsingChildren();
284 // ElementTraversal API
285 Element* firstElementChild() const;
286 Element* lastElementChild() const;
287 Element* previousElementSibling() const;
288 Element* nextElementSibling() const;
289 unsigned childElementCount() const;
291 bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
293 DOMTokenList* classList();
294 DOMTokenList* optionalClassList() const;
296 DOMStringMap* dataset();
297 DOMStringMap* optionalDataset() const;
300 virtual bool isMathMLElement() const { return false; }
302 static bool isMathMLElement() { return false; }
305 virtual bool isFormControlElement() const { return false; }
306 virtual bool isEnabledFormControl() const { return true; }
307 virtual bool isReadOnlyFormControl() const { return false; }
308 virtual bool isSpinButtonElement() const { return false; }
309 virtual bool isTextFormControl() const { return false; }
310 virtual bool isOptionalFormControl() const { return false; }
311 virtual bool isRequiredFormControl() const { return false; }
312 virtual bool isDefaultButtonForForm() const { return false; }
313 virtual bool willValidate() const { return false; }
314 virtual bool isValidFormControlElement() { return false; }
315 virtual bool hasUnacceptableValue() const { return false; }
316 virtual bool isInRange() const { return false; }
317 virtual bool isOutOfRange() const { return false; }
319 virtual bool formControlValueMatchesRenderer() const { return false; }
320 virtual void setFormControlValueMatchesRenderer(bool) { }
322 virtual const AtomicString& formControlName() const { return nullAtom; }
323 virtual const AtomicString& formControlType() const { return nullAtom; }
325 virtual bool shouldSaveAndRestoreFormControlState() const { return true; }
326 virtual bool saveFormControlState(String&) const { return false; }
327 virtual void restoreFormControlState(const String&) { }
329 virtual bool wasChangedSinceLastFormControlChangeEvent() const;
330 virtual void setChangedSinceLastFormControlChangeEvent(bool);
331 virtual void dispatchFormControlChangeEvent() { }
334 virtual bool childShouldCreateRenderer(Node*) const;
337 #if ENABLE(FULLSCREEN_API)
339 ALLOW_KEYBOARD_INPUT = 1
342 void webkitRequestFullScreen(unsigned short flags);
345 virtual bool isSpellCheckingEnabled() const;
348 Element(const QualifiedName& tagName, Document* document, ConstructionType type)
349 : ContainerNode(document, type)
354 virtual void insertedIntoDocument();
355 virtual void removedFromDocument();
356 virtual void insertedIntoTree(bool);
357 virtual void removedFromTree(bool);
358 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
360 // The implementation of Element::attributeChanged() calls the following two functions.
361 // They are separated to allow a different flow of control in StyledElement::attributeChanged().
362 void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
363 void updateAfterAttributeChanged(Attribute*);
366 void scrollByUnits(int units, ScrollGranularity);
368 virtual void setPrefix(const AtomicString&, ExceptionCode&);
369 virtual NodeType nodeType() const;
370 virtual bool childTypeAllowed(NodeType);
372 virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
375 virtual void formatForDebugger(char* buffer, unsigned length) const;
378 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
380 void createAttributeMap() const;
382 virtual void updateStyleAttribute() const { }
385 virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
388 void cancelFocusAppearanceUpdate();
390 virtual const AtomicString& virtualPrefix() const { return prefix(); }
391 virtual const AtomicString& virtualLocalName() const { return localName(); }
392 virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
393 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
395 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
397 virtual PassRefPtr<Node> cloneNode(bool deep);
398 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const;
400 QualifiedName m_tagName;
401 virtual NodeRareData* createRareData();
403 ElementRareData* rareData() const;
404 ElementRareData* ensureRareData();
406 SpellcheckAttributeState spellcheckAttributeState() const;
407 void removeShadowRoot();
410 mutable RefPtr<NamedNodeMap> m_attributeMap;
413 inline Element* toElement(Node* node)
415 ASSERT(!node || node->isElementNode());
416 return static_cast<Element*>(node);
419 inline const Element* toElement(const Node* node)
421 ASSERT(!node || node->isElementNode());
422 return static_cast<const Element*>(node);
425 // This will catch anyone doing an unnecessary cast.
426 void toElement(const Element*);
428 inline bool Node::hasTagName(const QualifiedName& name) const
430 return isElementNode() && toElement(this)->hasTagName(name);
433 inline bool Node::hasLocalName(const AtomicString& name) const
435 return isElementNode() && toElement(this)->hasLocalName(name);
438 inline bool Node::hasAttributes() const
440 return isElementNode() && toElement(this)->hasAttributes();
443 inline NamedNodeMap* Node::attributes() const
445 return isElementNode() ? toElement(this)->attributes() : 0;
448 inline Element* Node::parentElement() const
450 ContainerNode* parent = parentNode();
451 return parent && parent->isElementNode() ? toElement(parent) : 0;
454 inline NamedNodeMap* Element::attributes(bool readonly) const
456 if (!isStyleAttributeValid())
457 updateStyleAttribute();
460 if (!areSVGAttributesValid())
461 updateAnimatedSVGAttribute(anyQName());
464 if (!readonly && !m_attributeMap)
465 createAttributeMap();
466 return m_attributeMap.get();
469 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
477 Document* doc = document();
478 if (!oldId.isEmpty())
479 doc->removeElementById(oldId, this);
480 if (!newId.isEmpty())
481 doc->addElementById(newId, this);
484 inline bool Element::fastHasAttribute(const QualifiedName& name) const
486 return m_attributeMap && m_attributeMap->getAttributeItem(name);
489 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
491 if (m_attributeMap) {
492 if (Attribute* attribute = m_attributeMap->getAttributeItem(name))
493 return attribute->value();
498 inline const AtomicString& Element::idForStyleResolution() const
501 return m_attributeMap->idForStyleResolution();
504 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
506 // FIXME: This check is probably not correct for the case where the document has an id attribute
507 // with a non-null namespace, because it will return false, a false negative, if the prefixes
508 // don't match but the local name and namespace both do. However, since this has been like this
509 // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
510 return attributeName == document()->idAttributeName();
513 inline const AtomicString& Element::getIdAttribute() const
515 return fastGetAttribute(document()->idAttributeName());
518 inline void Element::setIdAttribute(const AtomicString& value)
520 setAttribute(document()->idAttributeName(), value);
523 inline const AtomicString& Element::shadowPseudoId() const
528 inline Element* firstElementChild(const ContainerNode* container)
530 ASSERT_ARG(container, container);
531 Node* child = container->firstChild();
532 while (child && !child->isElementNode())
533 child = child->nextSibling();
534 return static_cast<Element*>(child);