a0cf7b19b64d785b7aa40ce1b7899df562bc0bdd
[WebKit-https.git] / WebCore / dom / Element.h
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  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
7  *
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.
12  *
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.
17  *
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.
22  *
23  */
24
25 #ifndef Element_h
26 #define Element_h
27
28 #include "Document.h"
29 #include "FragmentScriptingPermission.h"
30 #include "NamedNodeMap.h"
31 #include "ScrollTypes.h"
32
33 namespace WebCore {
34
35 class Attribute;
36 class ClientRect;
37 class ClientRectList;
38 class ElementRareData;
39 class IntSize;
40
41 class Element : public ContainerNode {
42 public:
43     static PassRefPtr<Element> create(const QualifiedName&, Document*);
44     virtual ~Element();
45
46     DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
47     DEFINE_ATTRIBUTE_EVENT_LISTENER(change);
48     DEFINE_ATTRIBUTE_EVENT_LISTENER(click);
49     DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu);
50     DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick);
51     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter);
52     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover);
53     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave);
54     DEFINE_ATTRIBUTE_EVENT_LISTENER(drop);
55     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart);
56     DEFINE_ATTRIBUTE_EVENT_LISTENER(drag);
57     DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend);
58     DEFINE_ATTRIBUTE_EVENT_LISTENER(input);
59     DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid);
60     DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown);
61     DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress);
62     DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup);
63     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown);
64     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove);
65     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout);
66     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover);
67     DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup);
68     DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel);
69     DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll);
70     DEFINE_ATTRIBUTE_EVENT_LISTENER(select);
71     DEFINE_ATTRIBUTE_EVENT_LISTENER(submit);
72
73     // These four attribute event handler attributes are overridden by HTMLBodyElement
74     // and HTMLFrameSetElement to forward to the DOMWindow.
75     DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur);
76     DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error);
77     DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus);
78     DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load);
79
80     // WebKit extensions
81     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut);
82     DEFINE_ATTRIBUTE_EVENT_LISTENER(cut);
83     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy);
84     DEFINE_ATTRIBUTE_EVENT_LISTENER(copy);
85     DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste);
86     DEFINE_ATTRIBUTE_EVENT_LISTENER(paste);
87     DEFINE_ATTRIBUTE_EVENT_LISTENER(reset);
88     DEFINE_ATTRIBUTE_EVENT_LISTENER(search);
89     DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
90 #if ENABLE(TOUCH_EVENTS)
91     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart);
92     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove);
93     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend);
94     DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel);
95 #endif
96
97     virtual PassRefPtr<DocumentFragment> createContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed);
98
99     bool hasAttribute(const QualifiedName&) const;
100     const AtomicString& getAttribute(const QualifiedName&) const;
101     void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&);
102     void removeAttribute(const QualifiedName&, ExceptionCode&);
103
104     // Typed getters and setters for language bindings.
105     int getIntegralAttribute(const QualifiedName& attributeName) const;
106     void setIntegralAttribute(const QualifiedName& attributeName, int value);
107     unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const;
108     void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value);
109
110     // Call this to get the value of an attribute that is known not to be the style
111     // attribute or one of the SVG animatable attributes.
112     bool fastHasAttribute(const QualifiedName&) const;
113     const AtomicString& fastGetAttribute(const QualifiedName&) const;
114
115     bool hasAttributes() const;
116
117     bool hasAttribute(const String& name) const;
118     bool hasAttributeNS(const String& namespaceURI, const String& localName) const;
119
120     const AtomicString& getAttribute(const String& name) const;
121     const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const;
122
123     void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&);
124     void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed);
125
126     bool isIdAttributeName(const QualifiedName&) const;
127     const AtomicString& getIdAttribute() const;
128     void setIdAttribute(const AtomicString&);
129
130     // Call this to get the value of the id attribute for style resolution purposes.
131     // The value will already be lowercased if the document is in compatibility mode,
132     // so this function is not suitable for non-style uses.
133     const AtomicString& idForStyleResolution() const;
134
135     void scrollIntoView(bool alignToTop = true);
136     void scrollIntoViewIfNeeded(bool centerIfNeeded = true);
137
138     void scrollByLines(int lines);
139     void scrollByPages(int pages);
140
141     int offsetLeft();
142     int offsetTop();
143     int offsetWidth();
144     int offsetHeight();
145     Element* offsetParent();
146     int clientLeft();
147     int clientTop();
148     int clientWidth();
149     int clientHeight();
150     virtual int scrollLeft() const;
151     virtual int scrollTop() const;
152     virtual void setScrollLeft(int);
153     virtual void setScrollTop(int);
154     virtual int scrollWidth() const;
155     virtual int scrollHeight() const;
156
157     PassRefPtr<ClientRectList> getClientRects() const;
158     PassRefPtr<ClientRect> getBoundingClientRect() const;
159
160     void removeAttribute(const String& name, ExceptionCode&);
161     void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&);
162
163     PassRefPtr<Attr> getAttributeNode(const String& name);
164     PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName);
165     PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&);
166     PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&);
167     PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&);
168     
169     virtual CSSStyleDeclaration* style();
170
171     const QualifiedName& tagQName() const { return m_tagName; }
172     String tagName() const { return nodeName(); }
173     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
174     
175     // A fast function for checking the local name against another atomic string.
176     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
177     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
178
179     const AtomicString& localName() const { return m_tagName.localName(); }
180     const AtomicString& prefix() const { return m_tagName.prefix(); }
181     const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); }
182
183     virtual KURL baseURI() const;
184
185     virtual String nodeName() const;
186
187     PassRefPtr<Element> cloneElementWithChildren();
188     PassRefPtr<Element> cloneElementWithoutChildren();
189
190     void normalizeAttributes();
191     String nodeNamePreservingCase() const;
192
193     // convenience methods which ignore exceptions
194     void setAttribute(const QualifiedName&, const AtomicString& value);
195     void setBooleanAttribute(const QualifiedName& name, bool);
196     // Please don't use setCStringAttribute in performance-sensitive code;
197     // use a static AtomicString value instead to avoid the conversion overhead.
198     void setCStringAttribute(const QualifiedName&, const char* cStringValue);
199
200     virtual NamedNodeMap* attributes() const;
201     NamedNodeMap* attributes(bool readonly) const;
202
203     // This method is called whenever an attribute is added, changed or removed.
204     virtual void attributeChanged(Attribute*, bool preserveDecls = false);
205
206     // not part of the DOM
207     void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed);
208     NamedNodeMap* attributeMap() const { return namedAttrMap.get(); }
209
210     virtual void copyNonAttributeProperties(const Element* /*source*/) { }
211
212     virtual void attach();
213     virtual void detach();
214     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
215     virtual void recalcStyle(StyleChange = NoChange);
216
217     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
218
219     void dispatchAttrRemovalEvent(Attribute*);
220     void dispatchAttrAdditionEvent(Attribute*);
221
222     virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
223
224     virtual bool isURLAttribute(Attribute*) const;
225     KURL getURLAttribute(const QualifiedName&) const;
226     virtual const QualifiedName& imageSourceAttributeName() const;
227     virtual String target() const { return String(); }
228
229     virtual void focus(bool restorePreviousSelection = true);
230     virtual void updateFocusAppearance(bool restorePreviousSelection);
231     void blur();
232
233     String innerText() const;
234     String outerText() const;
235  
236     virtual String title() const;
237
238     String openTagStartToString() const;
239
240     void updateId(const AtomicString& oldId, const AtomicString& newId);
241
242     IntSize minimumSizeForResizing() const;
243     void setMinimumSizeForResizing(const IntSize&);
244
245     // Use Document::registerForDocumentActivationCallbacks() to subscribe to these
246     virtual void documentWillBecomeInactive() { }
247     virtual void documentDidBecomeActive() { }
248
249     // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
250     virtual void mediaVolumeDidChange() { }
251
252     bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); }
253     virtual void finishParsingChildren();
254     virtual void beginParsingChildren() { clearIsParsingChildrenFinished(); }
255
256     // ElementTraversal API
257     Element* firstElementChild() const;
258     Element* lastElementChild() const;
259     Element* previousElementSibling() const;
260     Element* nextElementSibling() const;
261     unsigned childElementCount() const;
262
263     bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
264
265     virtual bool isFormControlElement() const { return false; }
266     virtual bool isEnabledFormControl() const { return true; }
267     virtual bool isReadOnlyFormControl() const { return false; }
268     virtual bool isSpinButtonElement() const { return false; }
269     virtual bool isTextFormControl() const { return false; }
270     virtual bool isOptionalFormControl() const { return false; }
271     virtual bool isRequiredFormControl() const { return false; }
272     virtual bool isDefaultButtonForForm() const { return false; }
273     virtual bool willValidate() const { return false; }
274     virtual bool isValidFormControlElement() { return false; }
275
276     virtual bool formControlValueMatchesRenderer() const { return false; }
277     virtual void setFormControlValueMatchesRenderer(bool) { }
278
279     virtual const AtomicString& formControlName() const { return nullAtom; }
280     virtual const AtomicString& formControlType() const { return nullAtom; }
281
282     virtual bool shouldSaveAndRestoreFormControlState() const { return true; }
283     virtual bool saveFormControlState(String&) const { return false; }
284     virtual void restoreFormControlState(const String&) { }
285
286     virtual void dispatchFormControlChangeEvent() { }
287
288 #if ENABLE(SVG)
289     virtual bool childShouldCreateRenderer(Node*) const; 
290 #endif
291
292 protected:
293     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
294         : ContainerNode(document, type)
295         , m_tagName(tagName)
296     {
297     }
298
299     virtual void insertedIntoDocument();
300     virtual void removedFromDocument();
301     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
302
303     // The implementation of Element::attributeChanged() calls the following two functions.
304     // They are separated to allow a different flow of control in StyledElement::attributeChanged().
305     void recalcStyleIfNeededAfterAttributeChanged(Attribute*);
306     void updateAfterAttributeChanged(Attribute*);
307
308 private:
309     void scrollByUnits(int units, ScrollGranularity);
310
311     virtual void setPrefix(const AtomicString&, ExceptionCode&);
312     virtual NodeType nodeType() const;
313     virtual bool childTypeAllowed(NodeType);
314
315     virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value);
316     
317 #ifndef NDEBUG
318     virtual void formatForDebugger(char* buffer, unsigned length) const;
319 #endif
320
321     bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
322
323     void createAttributeMap() const;
324
325     virtual void updateStyleAttribute() const { }
326
327 #if ENABLE(SVG)
328     virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
329 #endif
330
331     void cancelFocusAppearanceUpdate();
332
333     virtual const AtomicString& virtualPrefix() const { return prefix(); }
334     virtual const AtomicString& virtualLocalName() const { return localName(); }
335     virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); }
336     virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); }
337     
338     // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren
339     // are used instead.
340     virtual PassRefPtr<Node> cloneNode(bool deep);
341
342     QualifiedName m_tagName;
343     virtual NodeRareData* createRareData();
344
345     ElementRareData* rareData() const;
346     ElementRareData* ensureRareData();
347     
348 protected:
349     mutable RefPtr<NamedNodeMap> namedAttrMap;
350 };
351     
352 inline bool Node::hasTagName(const QualifiedName& name) const
353 {
354     return isElementNode() && static_cast<const Element*>(this)->hasTagName(name);
355 }
356
357 inline bool Node::hasAttributes() const
358 {
359     return isElementNode() && static_cast<const Element*>(this)->hasAttributes();
360 }
361
362 inline NamedNodeMap* Node::attributes() const
363 {
364     return isElementNode() ? static_cast<const Element*>(this)->attributes() : 0;
365 }
366
367 inline Element* Node::parentElement() const
368 {
369     Node* parent = parentNode();
370     return parent && parent->isElementNode() ? static_cast<Element*>(parent) : 0;
371 }
372
373 inline NamedNodeMap* Element::attributes(bool readonly) const
374 {
375     if (!isStyleAttributeValid())
376         updateStyleAttribute();
377
378 #if ENABLE(SVG)
379     if (!areSVGAttributesValid())
380         updateAnimatedSVGAttribute(anyQName());
381 #endif
382
383     if (!readonly && !namedAttrMap)
384         createAttributeMap();
385     return namedAttrMap.get();
386 }
387
388 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
389 {
390     if (!inDocument())
391         return;
392
393     if (oldId == newId)
394         return;
395
396     Document* doc = document();
397     if (!oldId.isEmpty())
398         doc->removeElementById(oldId, this);
399     if (!newId.isEmpty())
400         doc->addElementById(newId, this);
401 }
402
403 inline bool Element::fastHasAttribute(const QualifiedName& name) const
404 {
405     return namedAttrMap && namedAttrMap->getAttributeItem(name);
406 }
407
408 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const
409 {
410     if (namedAttrMap) {
411         if (Attribute* attribute = namedAttrMap->getAttributeItem(name))
412             return attribute->value();
413     }
414     return nullAtom;
415 }
416
417 inline const AtomicString& Element::idForStyleResolution() const
418 {
419     ASSERT(hasID());
420     return namedAttrMap->idForStyleResolution();
421 }
422
423 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const
424 {
425     // FIXME: This check is probably not correct for the case where the document has an id attribute
426     // with a non-null namespace, because it will return false, a false negative, if the prefixes
427     // don't match but the local name and namespace both do. However, since this has been like this
428     // for a while and the code paths may be hot, we'll have to measure performance if we fix it.
429     return attributeName == document()->idAttributeName();
430 }
431
432 inline const AtomicString& Element::getIdAttribute() const
433 {
434     return fastGetAttribute(document()->idAttributeName());
435 }
436
437 inline void Element::setIdAttribute(const AtomicString& value)
438 {
439     setAttribute(document()->idAttributeName(), value);
440 }
441
442 } // namespace
443
444 #endif