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