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