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
35 namespace WebCore {
36
37 class Attr;
38 class Attribute;
39 class CSSStyleDeclaration;
40 class ClientRect;
41 class ClientRectList;
42 class ElementRareData;
43 class IntSize;
44
45 class Element : public ContainerNode {
46 public:
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
tagQName()156 const QualifiedName& tagQName() const { return m_tagName; }
tagName()157 String tagName() const { return nodeName(); }
hasTagName(const QualifiedName & tagName)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.
hasLocalName(const AtomicString & other)161 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
hasLocalName(const QualifiedName & other)162 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
163
localName()164 const AtomicString& localName() const { return m_tagName.localName(); }
prefix()165 const AtomicString& prefix() const { return m_tagName.prefix(); }
namespaceURI()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);
attributeMap()193 NamedNodeMap* attributeMap() const { return namedAttrMap.get(); }
194
copyNonAttributeProperties(const Element *)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
accessKeyAction(bool)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;
target()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
documentWillBecomeInactive()231 virtual void documentWillBecomeInactive() { }
documentDidBecomeActive()232 virtual void documentDidBecomeActive() { }
233
234 // Use Document::registerForMediaVolumeCallbacks() to subscribe to this
mediaVolumeDidChange()235 virtual void mediaVolumeDidChange() { }
236
isFinishedParsingChildren()237 bool isFinishedParsingChildren() const { return m_parsingChildrenFinished; }
238 virtual void finishParsingChildren();
beginParsingChildren()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
isFormControlElement()250 virtual bool isFormControlElement() const { return false; }
isEnabledFormControl()251 virtual bool isEnabledFormControl() const { return true; }
isReadOnlyFormControl()252 virtual bool isReadOnlyFormControl() const { return false; }
isTextFormControl()253 virtual bool isTextFormControl() const { return false; }
isOptionalFormControl()254 virtual bool isOptionalFormControl() const { return false; }
isRequiredFormControl()255 virtual bool isRequiredFormControl() const { return false; }
isDefaultButtonForForm()256 virtual bool isDefaultButtonForForm() const { return false; }
willValidate()257 virtual bool willValidate() const { return false; }
isValidFormControlElement()258 virtual bool isValidFormControlElement() { return false; }
259
formControlValueMatchesRenderer()260 virtual bool formControlValueMatchesRenderer() const { return false; }
setFormControlValueMatchesRenderer(bool)261 virtual void setFormControlValueMatchesRenderer(bool) { }
262
formControlName()263 virtual const AtomicString& formControlName() const { return nullAtom; }
formControlType()264 virtual const AtomicString& formControlType() const { return nullAtom; }
265
saveFormControlState(String &)266 virtual bool saveFormControlState(String&) const { return false; }
restoreFormControlState(const String &)267 virtual void restoreFormControlState(const String&) { }
268
dispatchFormControlChangeEvent()269 virtual void dispatchFormControlChangeEvent() { }
270
271 protected:
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
283 private:
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
updateStyleAttribute()301 virtual void updateStyleAttribute() const { }
302
303 #if ENABLE(SVG)
updateAnimatedSVGAttribute(const QualifiedName &)304 virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { }
305 #endif
306
307 void cancelFocusAppearanceUpdate();
308
virtualPrefix()309 virtual const AtomicString& virtualPrefix() const { return prefix(); }
virtualLocalName()310 virtual const AtomicString& virtualLocalName() const { return localName(); }
virtualNamespaceURI()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
323 protected:
324 mutable RefPtr<NamedNodeMap> namedAttrMap;
325 };
326
hasTagName(const QualifiedName & name)327 inline bool Node::hasTagName(const QualifiedName& name) const
328 {
329 return isElementNode() && static_cast<const Element*>(this)->hasTagName(name);
330 }
331
hasAttributes()332 inline bool Node::hasAttributes() const
333 {
334 return isElementNode() && static_cast<const Element*>(this)->hasAttributes();
335 }
336
attributes()337 inline NamedNodeMap* Node::attributes() const
338 {
339 return isElementNode() ? static_cast<const Element*>(this)->attributes() : 0;
340 }
341
parentElement()342 inline Element* Node::parentElement() const
343 {
344 Node* parent = parentNode();
345 return parent && parent->isElementNode() ? static_cast<Element*>(parent) : 0;
346 }
347
idAttributeName()348 inline const QualifiedName& Element::idAttributeName() const
349 {
350 return hasRareData() ? rareIDAttributeName() : HTMLNames::idAttr;
351 }
352
attributes(bool readonly)353 inline 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
updateId(const AtomicString & oldId,const AtomicString & newId)368 inline 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