1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Peter Kelly (pmk (at) post.com) 5 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 6 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 DOMStringMap; 39 class DOMTokenList; 40 class ElementRareData; 41 class IntSize; 42 class WebKitAnimationList; 43 44 enum SpellcheckAttributeState { 45 SpellcheckAttributeTrue, 46 SpellcheckAttributeFalse, 47 SpellcheckAttributeDefault 48 }; 49 50 class Element : public ContainerNode { 51 public: 52 static PassRefPtr<Element> create(const QualifiedName&, Document*); 53 virtual ~Element(); 54 55 DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); 56 DEFINE_ATTRIBUTE_EVENT_LISTENER(change); 57 DEFINE_ATTRIBUTE_EVENT_LISTENER(click); 58 DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); 59 DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick); 60 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter); 61 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover); 62 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave); 63 DEFINE_ATTRIBUTE_EVENT_LISTENER(drop); 64 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart); 65 DEFINE_ATTRIBUTE_EVENT_LISTENER(drag); 66 DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend); 67 DEFINE_ATTRIBUTE_EVENT_LISTENER(input); 68 DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); 69 DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown); 70 DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress); 71 DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); 72 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); 73 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); 74 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); 75 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover); 76 DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup); 77 DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel); 78 DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll); 79 DEFINE_ATTRIBUTE_EVENT_LISTENER(select); 80 DEFINE_ATTRIBUTE_EVENT_LISTENER(submit); 81 82 // These four attribute event handler attributes are overridden by HTMLBodyElement 83 // and HTMLFrameSetElement to forward to the DOMWindow. 84 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur); 85 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error); 86 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus); 87 DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load); 88 89 // WebKit extensions 90 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); 91 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); 92 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); 93 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); 94 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); 95 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); 96 DEFINE_ATTRIBUTE_EVENT_LISTENER(reset); 97 DEFINE_ATTRIBUTE_EVENT_LISTENER(search); 98 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); 99 #if ENABLE(TOUCH_EVENTS) 100 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); 101 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); 102 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); 103 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); 104 #endif 105 #if ENABLE(FULLSCREEN_API) 106 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange); 107 #endif 108 109 virtual PassRefPtr<DocumentFragment> deprecatedCreateContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed); 110 111 bool hasAttribute(const QualifiedName&) const; 112 const AtomicString& getAttribute(const QualifiedName&) const; 113 void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&); 114 void removeAttribute(const QualifiedName&, ExceptionCode&); 115 116 // Typed getters and setters for language bindings. 117 int getIntegralAttribute(const QualifiedName& attributeName) const; 118 void setIntegralAttribute(const QualifiedName& attributeName, int value); 119 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const; 120 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value); 121 122 // Call this to get the value of an attribute that is known not to be the style 123 // attribute or one of the SVG animatable attributes. 124 bool fastHasAttribute(const QualifiedName&) const; 125 const AtomicString& fastGetAttribute(const QualifiedName&) const; 126 127 bool hasAttributes() const; 128 129 bool hasAttribute(const String& name) const; 130 bool hasAttributeNS(const String& namespaceURI, const String& localName) const; 131 132 const AtomicString& getAttribute(const String& name) const; 133 const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const; 134 135 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&); 136 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed); 137 138 bool isIdAttributeName(const QualifiedName&) const; 139 const AtomicString& getIdAttribute() const; 140 void setIdAttribute(const AtomicString&); 141 142 // Call this to get the value of the id attribute for style resolution purposes. 143 // The value will already be lowercased if the document is in compatibility mode, 144 // so this function is not suitable for non-style uses. 145 const AtomicString& idForStyleResolution() const; 146 147 void scrollIntoView(bool alignToTop = true); 148 void scrollIntoViewIfNeeded(bool centerIfNeeded = true); 149 150 void scrollByLines(int lines); 151 void scrollByPages(int pages); 152 153 int offsetLeft(); 154 int offsetTop(); 155 int offsetWidth(); 156 int offsetHeight(); 157 Element* offsetParent(); 158 int clientLeft(); 159 int clientTop(); 160 int clientWidth(); 161 int clientHeight(); 162 virtual int scrollLeft() const; 163 virtual int scrollTop() const; 164 virtual void setScrollLeft(int); 165 virtual void setScrollTop(int); 166 virtual int scrollWidth() const; 167 virtual int scrollHeight() const; 168 169 IntRect boundsInWindowSpace() const; 170 171 PassRefPtr<ClientRectList> getClientRects() const; 172 PassRefPtr<ClientRect> getBoundingClientRect() const; 173 174 // Returns the absolute bounding box translated into screen coordinates: 175 IntRect screenRect() const; 176 177 void removeAttribute(const String& name, ExceptionCode&); 178 void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&); 179 180 PassRefPtr<Attr> getAttributeNode(const String& name); 181 PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName); 182 PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&); 183 PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&); 184 PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&); 185 186 virtual CSSStyleDeclaration* style(); 187 188 const QualifiedName& tagQName() const { return m_tagName; } 189 String tagName() const { return nodeName(); } 190 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); } 191 192 // A fast function for checking the local name against another atomic string. 193 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; } 194 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); } 195 196 const AtomicString& localName() const { return m_tagName.localName(); } 197 const AtomicString& prefix() const { return m_tagName.prefix(); } 198 const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); } 199 200 virtual KURL baseURI() const; 201 202 virtual String nodeName() const; 203 204 PassRefPtr<Element> cloneElementWithChildren(); 205 PassRefPtr<Element> cloneElementWithoutChildren(); 206 207 void normalizeAttributes(); 208 String nodeNamePreservingCase() const; 209 210 // convenience methods which ignore exceptions 211 void setAttribute(const QualifiedName&, const AtomicString& value); 212 void setBooleanAttribute(const QualifiedName& name, bool); 213 // Please don't use setCStringAttribute in performance-sensitive code; 214 // use a static AtomicString value instead to avoid the conversion overhead. 215 void setCStringAttribute(const QualifiedName&, const char* cStringValue); 216 217 NamedNodeMap* attributes(bool readonly = false) const; 218 219 // This method is called whenever an attribute is added, changed or removed. 220 virtual void attributeChanged(Attribute*, bool preserveDecls = false); 221 222 void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed); 223 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); } 224 225 virtual void copyNonAttributeProperties(const Element* /*source*/) { } 226 227 virtual void attach(); 228 virtual void detach(); 229 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); 230 virtual void recalcStyle(StyleChange = NoChange); 231 232 ContainerNode* shadowRoot() const; 233 ContainerNode* ensureShadowRoot(); 234 void removeShadowRoot(); 235 236 virtual const AtomicString& shadowPseudoId() const; 237 238 RenderStyle* computedStyle(PseudoId = NOPSEUDO); 239 240 AtomicString computeInheritedLanguage() const; 241 242 void dispatchAttrRemovalEvent(Attribute*); 243 void dispatchAttrAdditionEvent(Attribute*); 244 245 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { } 246 247 virtual bool isURLAttribute(Attribute*) const; 248 249 KURL getURLAttribute(const QualifiedName&) const; 250 KURL getNonEmptyURLAttribute(const QualifiedName&) const; 251 252 virtual const QualifiedName& imageSourceAttributeName() const; 253 virtual String target() const { return String(); } 254 255 virtual void focus(bool restorePreviousSelection = true); 256 virtual void updateFocusAppearance(bool restorePreviousSelection); 257 void blur(); 258 259 String innerText() const; 260 String outerText() const; 261 262 virtual String title() const; 263 264 String openTagStartToString() const; 265 266 void updateId(const AtomicString& oldId, const AtomicString& newId); 267 268 IntSize minimumSizeForResizing() const; 269 void setMinimumSizeForResizing(const IntSize&); 270 271 // Use Document::registerForDocumentActivationCallbacks() to subscribe to these 272 virtual void documentWillBecomeInactive() { } 273 virtual void documentDidBecomeActive() { } 274 275 // Use Document::registerForMediaVolumeCallbacks() to subscribe to this 276 virtual void mediaVolumeDidChange() { } 277 278 // Use Document::registerForPrivateBrowsingStateChangedCallbacks() to subscribe to this. 279 virtual void privateBrowsingStateDidChange() { } 280 281 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); } 282 virtual void finishParsingChildren(); 283 virtual void beginParsingChildren(); 284 285 // ElementTraversal API 286 Element* firstElementChild() const; 287 Element* lastElementChild() const; 288 Element* previousElementSibling() const; 289 Element* nextElementSibling() const; 290 unsigned childElementCount() const; 291 292 bool webkitMatchesSelector(const String& selectors, ExceptionCode&); 293 294 DOMTokenList* classList(); 295 DOMTokenList* optionalClassList() const; 296 297 DOMStringMap* dataset(); 298 DOMStringMap* optionalDataset() const; 299 300 #if ENABLE(MATHML) 301 virtual bool isMathMLElement() const { return false; } 302 #else 303 static bool isMathMLElement() { return false; } 304 #endif 305 306 #if ENABLE(INPUT_SPEECH) 307 virtual bool isInputFieldSpeechButtonElement() const { return false; } 308 #endif 309 310 virtual bool isFormControlElement() const { return false; } 311 virtual bool isEnabledFormControl() const { return true; } 312 virtual bool isReadOnlyFormControl() const { return false; } 313 virtual bool isSpinButtonElement() const { return false; } 314 virtual bool isTextFormControl() const { return false; } 315 virtual bool isOptionalFormControl() const { return false; } 316 virtual bool isRequiredFormControl() const { return false; } 317 virtual bool isDefaultButtonForForm() const { return false; } 318 virtual bool willValidate() const { return false; } 319 virtual bool isValidFormControlElement() { return false; } 320 virtual bool hasUnacceptableValue() const { return false; } 321 virtual bool isInRange() const { return false; } 322 virtual bool isOutOfRange() const { return false; } 323 324 virtual bool formControlValueMatchesRenderer() const { return false; } 325 virtual void setFormControlValueMatchesRenderer(bool) { } 326 327 virtual const AtomicString& formControlName() const { return nullAtom; } 328 virtual const AtomicString& formControlType() const { return nullAtom; } 329 330 virtual bool shouldSaveAndRestoreFormControlState() const { return true; } 331 virtual bool saveFormControlState(String&) const { return false; } 332 virtual void restoreFormControlState(const String&) { } 333 334 virtual bool wasChangedSinceLastFormControlChangeEvent() const; 335 virtual void setChangedSinceLastFormControlChangeEvent(bool); 336 virtual void dispatchFormControlChangeEvent() { } 337 338 #if ENABLE(SVG) 339 virtual bool childShouldCreateRenderer(Node*) const; 340 #endif 341 342 #if ENABLE(FULLSCREEN_API) 343 enum { 344 ALLOW_KEYBOARD_INPUT = 1 345 }; 346 347 void webkitRequestFullScreen(unsigned short flags); 348 #endif 349 350 virtual bool isSpellCheckingEnabled() const; 351 352 PassRefPtr<WebKitAnimationList> webkitGetAnimations() const; 353 354 protected: 355 Element(const QualifiedName& tagName, Document* document, ConstructionType type) 356 : ContainerNode(document, type) 357 , m_tagName(tagName) 358 { 359 } 360 361 virtual void insertedIntoDocument(); 362 virtual void removedFromDocument(); 363 virtual void insertedIntoTree(bool); 364 virtual void removedFromTree(bool); 365 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); 366 367 // The implementation of Element::attributeChanged() calls the following two functions. 368 // They are separated to allow a different flow of control in StyledElement::attributeChanged(). 369 void recalcStyleIfNeededAfterAttributeChanged(Attribute*); 370 void updateAfterAttributeChanged(Attribute*); 371 372 void idAttributeChanged(Attribute*); 373 374 private: 375 void scrollByUnits(int units, ScrollGranularity); 376 377 virtual void setPrefix(const AtomicString&, ExceptionCode&); 378 virtual NodeType nodeType() const; 379 virtual bool childTypeAllowed(NodeType) const; 380 381 virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value); 382 383 #ifndef NDEBUG 384 virtual void formatForDebugger(char* buffer, unsigned length) const; 385 #endif 386 387 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); 388 389 void createAttributeMap() const; 390 391 virtual void updateStyleAttribute() const { } 392 393 #if ENABLE(SVG) 394 virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { } 395 #endif 396 397 void cancelFocusAppearanceUpdate(); 398 399 virtual const AtomicString& virtualPrefix() const { return prefix(); } 400 virtual const AtomicString& virtualLocalName() const { return localName(); } 401 virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); } 402 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); } 403 404 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren 405 // are used instead. 406 virtual PassRefPtr<Node> cloneNode(bool deep); 407 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren() const; 408 409 QualifiedName m_tagName; 410 virtual NodeRareData* createRareData(); 411 412 ElementRareData* rareData() const; 413 ElementRareData* ensureRareData(); 414 415 SpellcheckAttributeState spellcheckAttributeState() const; 416 417 private: 418 mutable RefPtr<NamedNodeMap> m_attributeMap; 419 }; 420 421 inline Element* toElement(Node* node) 422 { 423 ASSERT(!node || node->isElementNode()); 424 return static_cast<Element*>(node); 425 } 426 427 inline const Element* toElement(const Node* node) 428 { 429 ASSERT(!node || node->isElementNode()); 430 return static_cast<const Element*>(node); 431 } 432 433 // This will catch anyone doing an unnecessary cast. 434 void toElement(const Element*); 435 436 inline bool Node::hasTagName(const QualifiedName& name) const 437 { 438 return isElementNode() && toElement(this)->hasTagName(name); 439 } 440 441 inline bool Node::hasLocalName(const AtomicString& name) const 442 { 443 return isElementNode() && toElement(this)->hasLocalName(name); 444 } 445 446 inline bool Node::hasAttributes() const 447 { 448 return isElementNode() && toElement(this)->hasAttributes(); 449 } 450 451 inline NamedNodeMap* Node::attributes() const 452 { 453 return isElementNode() ? toElement(this)->attributes() : 0; 454 } 455 456 inline Element* Node::parentElement() const 457 { 458 ContainerNode* parent = parentNode(); 459 return parent && parent->isElementNode() ? toElement(parent) : 0; 460 } 461 462 inline NamedNodeMap* Element::attributes(bool readonly) const 463 { 464 if (!isStyleAttributeValid()) 465 updateStyleAttribute(); 466 467 #if ENABLE(SVG) 468 if (!areSVGAttributesValid()) 469 updateAnimatedSVGAttribute(anyQName()); 470 #endif 471 472 if (!readonly && !m_attributeMap) 473 createAttributeMap(); 474 return m_attributeMap.get(); 475 } 476 477 inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId) 478 { 479 if (!inDocument()) 480 return; 481 482 if (oldId == newId) 483 return; 484 485 Document* doc = document(); 486 if (!oldId.isEmpty()) 487 doc->removeElementById(oldId, this); 488 if (!newId.isEmpty()) 489 doc->addElementById(newId, this); 490 } 491 492 inline bool Element::fastHasAttribute(const QualifiedName& name) const 493 { 494 return m_attributeMap && m_attributeMap->getAttributeItem(name); 495 } 496 497 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const 498 { 499 if (m_attributeMap) { 500 if (Attribute* attribute = m_attributeMap->getAttributeItem(name)) 501 return attribute->value(); 502 } 503 return nullAtom; 504 } 505 506 inline const AtomicString& Element::idForStyleResolution() const 507 { 508 ASSERT(hasID()); 509 return m_attributeMap->idForStyleResolution(); 510 } 511 512 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const 513 { 514 // FIXME: This check is probably not correct for the case where the document has an id attribute 515 // with a non-null namespace, because it will return false, a false negative, if the prefixes 516 // don't match but the local name and namespace both do. However, since this has been like this 517 // for a while and the code paths may be hot, we'll have to measure performance if we fix it. 518 return attributeName == document()->idAttributeName(); 519 } 520 521 inline const AtomicString& Element::getIdAttribute() const 522 { 523 return fastGetAttribute(document()->idAttributeName()); 524 } 525 526 inline void Element::setIdAttribute(const AtomicString& value) 527 { 528 setAttribute(document()->idAttributeName(), value); 529 } 530 531 inline const AtomicString& Element::shadowPseudoId() const 532 { 533 return nullAtom; 534 } 535 536 inline Element* firstElementChild(const ContainerNode* container) 537 { 538 ASSERT_ARG(container, container); 539 Node* child = container->firstChild(); 540 while (child && !child->isElementNode()) 541 child = child->nextSibling(); 542 return static_cast<Element*>(child); 543 } 544 545 } // namespace 546 547 #endif 548