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, 2013 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 "CSSPropertyNames.h" 29 #include "HTMLNames.h" 30 #include "core/css/CSSPrimitiveValue.h" 31 #include "core/dom/Attribute.h" 32 #include "core/dom/Document.h" 33 #include "core/dom/ElementData.h" 34 #include "core/dom/SpaceSplitString.h" 35 #include "core/html/CollectionType.h" 36 #include "core/page/FocusDirection.h" 37 #include "core/rendering/RegionOversetState.h" 38 #include "platform/scroll/ScrollTypes.h" 39 40 namespace WebCore { 41 42 class ActiveAnimations; 43 class Attr; 44 class Attribute; 45 class ClientRect; 46 class ClientRectList; 47 class DOMStringMap; 48 class DOMTokenList; 49 class ElementRareData; 50 class ElementShadow; 51 class ExceptionState; 52 class Image; 53 class InputMethodContext; 54 class IntSize; 55 class Locale; 56 class MutableStylePropertySet; 57 class PropertySetCSSStyleDeclaration; 58 class PseudoElement; 59 class RenderRegion; 60 class ShadowRoot; 61 class StylePropertySet; 62 63 enum AffectedSelectorType { 64 AffectedSelectorChecked = 1, 65 AffectedSelectorEnabled = 1 << 1, 66 AffectedSelectorDisabled = 1 << 2, 67 AffectedSelectorIndeterminate = 1 << 3, 68 AffectedSelectorLink = 1 << 4, 69 AffectedSelectorTarget = 1 << 5, 70 AffectedSelectorVisited = 1 << 6 71 }; 72 typedef int AffectedSelectorMask; 73 74 enum SpellcheckAttributeState { 75 SpellcheckAttributeTrue, 76 SpellcheckAttributeFalse, 77 SpellcheckAttributeDefault 78 }; 79 80 class Element : public ContainerNode { 81 public: 82 static PassRefPtr<Element> create(const QualifiedName&, Document*); 83 virtual ~Element(); 84 85 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); 86 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); 87 DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); 88 DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); 89 DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); 90 DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); 91 DEFINE_ATTRIBUTE_EVENT_LISTENER(search); 92 DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); 93 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); 94 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); 95 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); 96 DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); 97 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenchange); 98 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitfullscreenerror); 99 DEFINE_ATTRIBUTE_EVENT_LISTENER(wheel); 100 101 bool hasAttribute(const QualifiedName&) const; 102 const AtomicString& getAttribute(const QualifiedName&) const; 103 void setAttribute(const QualifiedName&, const AtomicString& value); 104 void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value); 105 void removeAttribute(const QualifiedName&); 106 107 // Typed getters and setters for language bindings. 108 int getIntegralAttribute(const QualifiedName& attributeName) const; 109 void setIntegralAttribute(const QualifiedName& attributeName, int value); 110 unsigned getUnsignedIntegralAttribute(const QualifiedName& attributeName) const; 111 void setUnsignedIntegralAttribute(const QualifiedName& attributeName, unsigned value); 112 double getFloatingPointAttribute(const QualifiedName& attributeName, double fallbackValue = std::numeric_limits<double>::quiet_NaN()) const; 113 void setFloatingPointAttribute(const QualifiedName& attributeName, double value); 114 115 // Call this to get the value of an attribute that is known not to be the style 116 // attribute or one of the SVG animatable attributes. 117 bool fastHasAttribute(const QualifiedName&) const; 118 const AtomicString& fastGetAttribute(const QualifiedName&) const; 119 #ifndef NDEBUG 120 bool fastAttributeLookupAllowed(const QualifiedName&) const; 121 #endif 122 123 #ifdef DUMP_NODE_STATISTICS 124 bool hasNamedNodeMap() const; 125 #endif 126 bool hasAttributes() const; 127 // This variant will not update the potentially invalid attributes. To be used when not interested 128 // in style attribute or one of the SVG animation attributes. 129 bool hasAttributesWithoutUpdate() const; 130 131 bool hasAttribute(const AtomicString& name) const; 132 bool hasAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const; 133 134 const AtomicString& getAttribute(const AtomicString& name) const; 135 const AtomicString& getAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName) const; 136 137 void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionState&); 138 static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState&); 139 void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionState&); 140 141 bool isIdAttributeName(const QualifiedName&) const; 142 const AtomicString& getIdAttribute() const; 143 void setIdAttribute(const AtomicString&); 144 145 const AtomicString& getNameAttribute() const; 146 const AtomicString& getClassAttribute() const; 147 148 bool shouldIgnoreAttributeCase() const; 149 150 // Call this to get the value of the id attribute for style resolution purposes. 151 // The value will already be lowercased if the document is in compatibility mode, 152 // so this function is not suitable for non-style uses. 153 const AtomicString& idForStyleResolution() const; 154 155 // Internal methods that assume the existence of attribute storage, one should use hasAttributes() 156 // before calling them. 157 size_t attributeCount() const; 158 const Attribute* attributeItem(unsigned index) const; 159 const Attribute* getAttributeItem(const QualifiedName&) const; 160 size_t getAttributeItemIndex(const QualifiedName& name) const { return elementData()->getAttributeItemIndex(name); } 161 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return elementData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); } 162 163 void scrollIntoView(bool alignToTop = true); 164 void scrollIntoViewIfNeeded(bool centerIfNeeded = true); 165 166 void scrollByLines(int lines); 167 void scrollByPages(int pages); 168 169 int offsetLeft(); 170 int offsetTop(); 171 int offsetWidth(); 172 int offsetHeight(); 173 174 // FIXME: Replace uses of offsetParent in the platform with calls 175 // to the render layer and merge bindingsOffsetParent and offsetParent. 176 Element* bindingsOffsetParent(); 177 178 Element* offsetParent(); 179 int clientLeft(); 180 int clientTop(); 181 int clientWidth(); 182 int clientHeight(); 183 virtual int scrollLeft(); 184 virtual int scrollTop(); 185 virtual void setScrollLeft(int); 186 virtual void setScrollTop(int); 187 virtual int scrollWidth(); 188 virtual int scrollHeight(); 189 190 IntRect boundsInRootViewSpace(); 191 192 PassRefPtr<ClientRectList> getClientRects(); 193 PassRefPtr<ClientRect> getBoundingClientRect(); 194 195 // Returns the absolute bounding box translated into screen coordinates: 196 IntRect screenRect() const; 197 198 virtual void didMoveToNewDocument(Document&) OVERRIDE; 199 200 void removeAttribute(const AtomicString& name); 201 void removeAttributeNS(const AtomicString& namespaceURI, const AtomicString& localName); 202 203 PassRefPtr<Attr> detachAttribute(size_t index); 204 205 PassRefPtr<Attr> getAttributeNode(const AtomicString& name); 206 PassRefPtr<Attr> getAttributeNodeNS(const AtomicString& namespaceURI, const AtomicString& localName); 207 PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionState&); 208 PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionState&); 209 PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionState&); 210 211 PassRefPtr<Attr> attrIfExists(const QualifiedName&); 212 PassRefPtr<Attr> ensureAttr(const QualifiedName&); 213 214 const Vector<RefPtr<Attr> >& attrNodeList(); 215 216 CSSStyleDeclaration* style(); 217 218 const QualifiedName& tagQName() const { return m_tagName; } 219 String tagName() const { return nodeName(); } 220 bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); } 221 222 // Should be called only by Document::createElementNS to fix up m_tagName immediately after construction. 223 void setTagNameForCreateElementNS(const QualifiedName&); 224 225 // A fast function for checking the local name against another atomic string. 226 bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; } 227 bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); } 228 229 virtual const AtomicString& localName() const OVERRIDE { return m_tagName.localName(); } 230 virtual const AtomicString& prefix() const OVERRIDE { return m_tagName.prefix(); } 231 virtual const AtomicString& namespaceURI() const OVERRIDE { return m_tagName.namespaceURI(); } 232 233 virtual KURL baseURI() const OVERRIDE FINAL; 234 235 virtual String nodeName() const; 236 237 PassRefPtr<Element> cloneElementWithChildren(); 238 PassRefPtr<Element> cloneElementWithoutChildren(); 239 240 void scheduleLayerUpdate(); 241 242 void normalizeAttributes(); 243 String nodeNamePreservingCase() const; 244 245 void setBooleanAttribute(const QualifiedName& name, bool); 246 247 virtual const StylePropertySet* additionalPresentationAttributeStyle() { return 0; } 248 void invalidateStyleAttribute(); 249 250 const StylePropertySet* inlineStyle() const { return elementData() ? elementData()->m_inlineStyle.get() : 0; } 251 252 bool setInlineStyleProperty(CSSPropertyID, CSSValueID identifier, bool important = false); 253 bool setInlineStyleProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false); 254 bool setInlineStyleProperty(CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes, bool important = false); 255 bool setInlineStyleProperty(CSSPropertyID, const String& value, bool important = false); 256 bool removeInlineStyleProperty(CSSPropertyID); 257 void removeAllInlineStyleProperties(); 258 259 void synchronizeStyleAttributeInternal() const; 260 261 const StylePropertySet* presentationAttributeStyle(); 262 virtual bool isPresentationAttribute(const QualifiedName&) const { return false; } 263 virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) { } 264 265 // For exposing to DOM only. 266 NamedNodeMap* attributes() const; 267 268 enum AttributeModificationReason { 269 ModifiedDirectly, 270 ModifiedByCloning 271 }; 272 273 // This method is called whenever an attribute is added, changed or removed. 274 virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly); 275 virtual void parseAttribute(const QualifiedName&, const AtomicString&) { } 276 277 // Only called by the parser immediately after element construction. 278 void parserSetAttributes(const Vector<Attribute>&); 279 280 // Remove attributes that might introduce scripting from the vector leaving the element unchanged. 281 void stripScriptingAttributes(Vector<Attribute>&) const; 282 283 const ElementData* elementData() const { return m_elementData.get(); } 284 UniqueElementData* ensureUniqueElementData(); 285 286 void synchronizeAllAttributes() const; 287 288 // Clones attributes only. 289 void cloneAttributesFromElement(const Element&); 290 291 // Clones all attribute-derived data, including subclass specifics (through copyNonAttributeProperties.) 292 void cloneDataFromElement(const Element&); 293 294 bool hasEquivalentAttributes(const Element* other) const; 295 296 virtual void copyNonAttributePropertiesFromElement(const Element&) { } 297 298 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; 299 virtual void detach(const AttachContext& = AttachContext()) OVERRIDE; 300 virtual RenderObject* createRenderer(RenderStyle*); 301 virtual bool rendererIsNeeded(const RenderStyle&); 302 void recalcStyle(StyleRecalcChange, Text* nextTextSibling = 0); 303 void didAffectSelector(AffectedSelectorMask); 304 void setAnimationStyleChange(bool); 305 void setNeedsAnimationStyleRecalc(); 306 307 bool supportsStyleSharing() const; 308 309 ElementShadow* shadow() const; 310 ElementShadow& ensureShadow(); 311 PassRefPtr<ShadowRoot> createShadowRoot(ExceptionState&); 312 ShadowRoot* shadowRoot() const; 313 ShadowRoot* youngestShadowRoot() const; 314 315 bool hasAuthorShadowRoot() const { return shadowRoot(); } 316 virtual void didAddShadowRoot(ShadowRoot&); 317 ShadowRoot* userAgentShadowRoot() const; 318 ShadowRoot& ensureUserAgentShadowRoot(); 319 const AtomicString& shadowPseudoId() const; 320 bool isInDescendantTreeOf(const Element* shadowHost) const; 321 322 RenderStyle* computedStyle(PseudoId = NOPSEUDO); 323 324 // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.) 325 bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); } 326 bool childrenAffectedByFocus() const { return hasRareData() && rareDataChildrenAffectedByFocus(); } 327 bool childrenAffectedByHover() const { return hasRareData() && rareDataChildrenAffectedByHover(); } 328 bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); } 329 bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); } 330 bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); } 331 bool childrenAffectedByFirstChildRules() const { return hasRareData() && rareDataChildrenAffectedByFirstChildRules(); } 332 bool childrenAffectedByLastChildRules() const { return hasRareData() && rareDataChildrenAffectedByLastChildRules(); } 333 bool childrenAffectedByDirectAdjacentRules() const { return hasRareData() && rareDataChildrenAffectedByDirectAdjacentRules(); } 334 bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); } 335 bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); } 336 unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; } 337 338 bool childrenSupportStyleSharing() const; 339 340 void setStyleAffectedByEmpty(); 341 void setChildrenAffectedByFocus(); 342 void setChildrenAffectedByHover(); 343 void setChildrenAffectedByActive(); 344 void setChildrenAffectedByDrag(); 345 void setChildrenAffectedByFirstChildRules(); 346 void setChildrenAffectedByLastChildRules(); 347 void setChildrenAffectedByDirectAdjacentRules(); 348 void setChildrenAffectedByForwardPositionalRules(); 349 void setChildrenAffectedByBackwardPositionalRules(); 350 void setChildIndex(unsigned); 351 352 void setIsInCanvasSubtree(bool); 353 bool isInCanvasSubtree() const; 354 355 bool isUpgradedCustomElement() { return customElementState() == Upgraded; } 356 bool isUnresolvedCustomElement() { return customElementState() == WaitingForUpgrade; } 357 358 void setIsInsideRegion(bool); 359 bool isInsideRegion() const; 360 361 void setRegionOversetState(RegionOversetState); 362 RegionOversetState regionOversetState() const; 363 364 AtomicString computeInheritedLanguage() const; 365 Locale& locale() const; 366 367 virtual void accessKeyAction(bool /*sendToAnyEvent*/) { } 368 369 virtual bool isURLAttribute(const Attribute&) const { return false; } 370 virtual bool isHTMLContentAttribute(const Attribute&) const { return false; } 371 372 KURL getURLAttribute(const QualifiedName&) const; 373 KURL getNonEmptyURLAttribute(const QualifiedName&) const; 374 375 virtual const AtomicString imageSourceURL() const; 376 virtual String target() const { return String(); } 377 virtual Image* imageContents() { return 0; } 378 379 virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone); 380 virtual void updateFocusAppearance(bool restorePreviousSelection); 381 virtual void blur(); 382 // Whether this element can receive focus at all. Most elements are not 383 // focusable but some elements, such as form controls and links, are. Unlike 384 // rendererIsFocusable(), this method may be called when layout is not up to 385 // date, so it must not use the renderer to determine focusability. 386 virtual bool supportsFocus() const; 387 // Whether the node can actually be focused. 388 bool isFocusable() const; 389 virtual bool isKeyboardFocusable() const; 390 virtual bool isMouseFocusable() const; 391 virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection); 392 virtual void dispatchBlurEvent(Element* newFocusedElement); 393 void dispatchFocusInEvent(const AtomicString& eventType, Element* oldFocusedElement); 394 void dispatchFocusOutEvent(const AtomicString& eventType, Element* newFocusedElement); 395 396 String innerText(); 397 String outerText(); 398 String innerHTML() const; 399 String outerHTML() const; 400 void setInnerHTML(const String&, ExceptionState&); 401 void setOuterHTML(const String&, ExceptionState&); 402 void insertAdjacentHTML(const String& where, const String& html, ExceptionState&); 403 404 String textFromChildren(); 405 406 virtual String title() const { return String(); } 407 408 virtual const AtomicString& pseudo() const; 409 void setPseudo(const AtomicString&); 410 411 LayoutSize minimumSizeForResizing() const; 412 void setMinimumSizeForResizing(const LayoutSize&); 413 414 virtual void didBecomeFullscreenElement() { } 415 virtual void willStopBeingFullscreenElement() { } 416 417 bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); } 418 virtual void finishParsingChildren(); 419 virtual void beginParsingChildren() OVERRIDE FINAL; 420 421 PseudoElement* pseudoElement(PseudoId) const; 422 RenderObject* pseudoElementRenderer(PseudoId) const; 423 424 virtual bool matchesReadOnlyPseudoClass() const { return false; } 425 virtual bool matchesReadWritePseudoClass() const { return false; } 426 bool webkitMatchesSelector(const String& selectors, ExceptionState&); 427 virtual bool shouldAppearIndeterminate() const { return false; } 428 429 DOMTokenList* classList(); 430 431 DOMStringMap* dataset(); 432 433 virtual bool isMediaElement() const { return false; } 434 435 #if ENABLE(INPUT_SPEECH) 436 virtual bool isInputFieldSpeechButtonElement() const { return false; } 437 #endif 438 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 439 virtual bool isDateTimeEditElement() const { return false; } 440 virtual bool isDateTimeFieldElement() const { return false; } 441 virtual bool isPickerIndicatorElement() const { return false; } 442 #endif 443 444 virtual bool isFormControlElement() const { return false; } 445 virtual bool isSpinButtonElement() const { return false; } 446 virtual bool isTextFormControl() const { return false; } 447 virtual bool isOptionalFormControl() const { return false; } 448 virtual bool isRequiredFormControl() const { return false; } 449 virtual bool isDefaultButtonForForm() const { return false; } 450 virtual bool willValidate() const { return false; } 451 virtual bool isValidFormControlElement() { return false; } 452 virtual bool isInRange() const { return false; } 453 virtual bool isOutOfRange() const { return false; } 454 virtual bool isFrameElementBase() const { return false; } 455 virtual bool isPasswordGeneratorButtonElement() const { return false; } 456 virtual bool isClearButtonElement() const { return false; } 457 458 virtual bool canContainRangeEndPoint() const { return true; } 459 460 virtual const AtomicString& formControlType() const { return nullAtom; } 461 462 // FIXME: Only HTMLInputElement uses these, they don't need to be virtual. 463 virtual bool wasChangedSinceLastFormControlChangeEvent() const { return false; } 464 virtual void setChangedSinceLastFormControlChangeEvent(bool) { } 465 virtual void dispatchFormControlChangeEvent() { } 466 467 // Used for disabled form elements; if true, prevents mouse events from being dispatched 468 // to event listeners, and prevents DOMActivate events from being sent at all. 469 virtual bool isDisabledFormControl() const { return false; } 470 471 virtual bool shouldBeReparentedUnderRenderView(const RenderStyle*) const { return isInTopLayer(); } 472 473 virtual bool childShouldCreateRenderer(const Node& child) const; 474 bool hasPendingResources() const; 475 void setHasPendingResources(); 476 void clearHasPendingResources(); 477 virtual void buildPendingResource() { }; 478 479 enum { 480 ALLOW_KEYBOARD_INPUT = 1 << 0, 481 LEGACY_MOZILLA_REQUEST = 1 << 1, 482 }; 483 484 void webkitRequestFullScreen(unsigned short flags); 485 bool containsFullScreenElement() const; 486 void setContainsFullScreenElement(bool); 487 void setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(bool); 488 489 // W3C API 490 void webkitRequestFullscreen(); 491 492 bool isInTopLayer() const; 493 void setIsInTopLayer(bool); 494 495 void webkitRequestPointerLock(); 496 497 bool isSpellCheckingEnabled() const; 498 499 // FIXME: public for NodeRenderingContext, we shouldn't expose this though. 500 PassRefPtr<RenderStyle> styleForRenderer(); 501 502 RenderRegion* renderRegion() const; 503 virtual bool shouldMoveToFlowThread(RenderStyle*) const; 504 const AtomicString& webkitRegionOverset() const; 505 Vector<RefPtr<Range> > webkitGetRegionFlowRanges() const; 506 507 bool hasID() const; 508 bool hasClass() const; 509 const SpaceSplitString& classNames() const; 510 511 IntSize savedLayerScrollOffset() const; 512 void setSavedLayerScrollOffset(const IntSize&); 513 514 ActiveAnimations* activeAnimations() const; 515 ActiveAnimations* ensureActiveAnimations(); 516 bool hasActiveAnimations() const; 517 518 InputMethodContext* inputMethodContext(); 519 bool hasInputMethodContext() const; 520 521 virtual void setPrefix(const AtomicString&, ExceptionState&) OVERRIDE FINAL; 522 523 void synchronizeAttribute(const AtomicString& localName) const; 524 525 bool needsPseudoElement(PseudoId, const RenderStyle&) const; 526 527 protected: 528 Element(const QualifiedName& tagName, Document* document, ConstructionType type) 529 : ContainerNode(document, type) 530 , m_tagName(tagName) 531 { 532 ScriptWrappable::init(this); 533 } 534 535 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, CSSValueID identifier); 536 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, double value, CSSPrimitiveValue::UnitTypes); 537 void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const String& value); 538 539 virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; 540 541 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 542 virtual void removedFrom(ContainerNode*) OVERRIDE; 543 virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0) OVERRIDE; 544 virtual void removeAllEventListeners() OVERRIDE; 545 546 virtual void willRecalcStyle(StyleRecalcChange); 547 virtual void didRecalcStyle(StyleRecalcChange); 548 virtual PassRefPtr<RenderStyle> customStyleForRenderer(); 549 550 virtual bool shouldRegisterAsNamedItem() const { return false; } 551 virtual bool shouldRegisterAsExtraNamedItem() const { return false; } 552 553 void clearTabIndexExplicitlyIfNeeded(); 554 void setTabIndexExplicitly(short); 555 virtual short tabIndex() const OVERRIDE; 556 // Subclasses may override this method to affect focusability. Unlike 557 // supportsFocus, this method must be called on an up-to-date layout, so it 558 // may use the renderer to reason about focusability. This method cannot be 559 // moved to RenderObject because some focusable nodes don't have renderers, 560 // e.g., HTMLOptionElement. 561 virtual bool rendererIsFocusable() const; 562 PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType); 563 HTMLCollection* cachedHTMLCollection(CollectionType); 564 565 // classAttributeChanged() exists to share code between 566 // parseAttribute (called via setAttribute()) and 567 // svgAttributeChanged (called when element.className.baseValue is set) 568 void classAttributeChanged(const AtomicString& newClassString); 569 570 PassRefPtr<RenderStyle> originalStyleForRenderer(); 571 572 Node* insertAdjacent(const String& where, Node* newChild, ExceptionState&); 573 574 private: 575 void styleAttributeChanged(const AtomicString& newStyleString, AttributeModificationReason); 576 577 void updatePresentationAttributeStyle(); 578 579 void inlineStyleChanged(); 580 PropertySetCSSStyleDeclaration* inlineStyleCSSOMWrapper(); 581 void setInlineStyleFromString(const AtomicString&); 582 MutableStylePropertySet* ensureMutableInlineStyle(); 583 584 StyleRecalcChange recalcOwnStyle(StyleRecalcChange); 585 void recalcChildStyle(StyleRecalcChange); 586 587 // FIXME: These methods should all be renamed to something better than "check", 588 // since it's not clear that they alter the style bits of siblings and children. 589 void checkForChildrenAdjacentRuleChanges(); 590 void checkForSiblingStyleChanges(bool finishedParsingCallback, Node* beforeChange, Node* afterChange, int childCountDelta); 591 inline void checkForEmptyStyleChange(RenderStyle*); 592 593 void updatePseudoElement(PseudoId, StyleRecalcChange); 594 595 inline void createPseudoElementIfNeeded(PseudoId); 596 597 // FIXME: Everyone should allow author shadows. 598 virtual bool areAuthorShadowsAllowed() const { return true; } 599 virtual void didAddUserAgentShadowRoot(ShadowRoot&) { } 600 virtual bool alwaysCreateUserAgentShadowRoot() const { return false; } 601 602 // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute. 603 friend class Attr; 604 605 enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute = 0, InSynchronizationOfLazyAttribute }; 606 607 void didAddAttribute(const QualifiedName&, const AtomicString&); 608 void willModifyAttribute(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue); 609 void didModifyAttribute(const QualifiedName&, const AtomicString&); 610 void didRemoveAttribute(const QualifiedName&); 611 612 void synchronizeAttribute(const QualifiedName&) const; 613 614 void updateId(const AtomicString& oldId, const AtomicString& newId); 615 void updateId(TreeScope&, const AtomicString& oldId, const AtomicString& newId); 616 void updateName(const AtomicString& oldName, const AtomicString& newName); 617 void updateLabel(TreeScope&, const AtomicString& oldForAttributeValue, const AtomicString& newForAttributeValue); 618 619 void scrollByUnits(int units, ScrollGranularity); 620 621 virtual NodeType nodeType() const OVERRIDE FINAL; 622 virtual bool childTypeAllowed(NodeType) const OVERRIDE FINAL; 623 624 void setAttributeInternal(size_t index, const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute); 625 void addAttributeInternal(const QualifiedName&, const AtomicString& value, SynchronizationOfLazyAttribute); 626 void removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute); 627 void attributeChangedFromParserOrByCloning(const QualifiedName&, const AtomicString&, AttributeModificationReason); 628 629 #ifndef NDEBUG 630 virtual void formatForDebugger(char* buffer, unsigned length) const; 631 #endif 632 633 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); 634 635 void cancelFocusAppearanceUpdate(); 636 637 virtual RenderStyle* virtualComputedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return computedStyle(pseudoElementSpecifier); } 638 639 inline void updateCallbackSelectors(RenderStyle* oldStyle, RenderStyle* newStyle); 640 inline void removeCallbackSelectors(); 641 inline void addCallbackSelectors(); 642 643 // cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren 644 // are used instead. 645 virtual PassRefPtr<Node> cloneNode(bool deep) OVERRIDE; 646 virtual PassRefPtr<Element> cloneElementWithoutAttributesAndChildren(); 647 648 QualifiedName m_tagName; 649 bool rareDataStyleAffectedByEmpty() const; 650 bool rareDataChildrenAffectedByFocus() const; 651 bool rareDataChildrenAffectedByHover() const; 652 bool rareDataChildrenAffectedByActive() const; 653 bool rareDataChildrenAffectedByDrag() const; 654 bool rareDataChildrenAffectedByFirstChildRules() const; 655 bool rareDataChildrenAffectedByLastChildRules() const; 656 bool rareDataChildrenAffectedByDirectAdjacentRules() const; 657 bool rareDataChildrenAffectedByForwardPositionalRules() const; 658 bool rareDataChildrenAffectedByBackwardPositionalRules() const; 659 unsigned rareDataChildIndex() const; 660 661 SpellcheckAttributeState spellcheckAttributeState() const; 662 663 void updateNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName); 664 void updateExtraNamedItemRegistration(const AtomicString& oldName, const AtomicString& newName); 665 666 void unregisterNamedFlowContentNode(); 667 668 void createUniqueElementData(); 669 670 bool shouldInvalidateDistributionWhenAttributeChanged(ElementShadow*, const QualifiedName&, const AtomicString&); 671 672 ElementRareData* elementRareData() const; 673 ElementRareData& ensureElementRareData(); 674 675 void detachAllAttrNodesFromElement(); 676 void detachAttrNodeFromElementWithValue(Attr*, const AtomicString& value); 677 void detachAttrNodeAtIndex(Attr*, size_t index); 678 679 bool isJavaScriptURLAttribute(const Attribute&) const; 680 681 RefPtr<ElementData> m_elementData; 682 }; 683 684 DEFINE_NODE_TYPE_CASTS(Element, isElementNode()); 685 686 inline bool isDisabledFormControl(const Node* node) 687 { 688 return node->isElementNode() && toElement(node)->isDisabledFormControl(); 689 } 690 691 inline bool Node::hasTagName(const QualifiedName& name) const 692 { 693 return isElementNode() && toElement(this)->hasTagName(name); 694 } 695 696 inline Element* Node::parentElement() const 697 { 698 ContainerNode* parent = parentNode(); 699 return parent && parent->isElementNode() ? toElement(parent) : 0; 700 } 701 702 inline Element* Node::previousElementSibling() const 703 { 704 Node* n = previousSibling(); 705 while (n && !n->isElementNode()) 706 n = n->previousSibling(); 707 return toElement(n); 708 } 709 710 inline Element* Node::nextElementSibling() const 711 { 712 Node* n = nextSibling(); 713 while (n && !n->isElementNode()) 714 n = n->nextSibling(); 715 return toElement(n); 716 } 717 718 inline bool Element::fastHasAttribute(const QualifiedName& name) const 719 { 720 ASSERT(fastAttributeLookupAllowed(name)); 721 return elementData() && getAttributeItem(name); 722 } 723 724 inline const AtomicString& Element::fastGetAttribute(const QualifiedName& name) const 725 { 726 ASSERT(fastAttributeLookupAllowed(name)); 727 if (elementData()) { 728 if (const Attribute* attribute = getAttributeItem(name)) 729 return attribute->value(); 730 } 731 return nullAtom; 732 } 733 734 inline bool Element::hasAttributesWithoutUpdate() const 735 { 736 return elementData() && !elementData()->isEmpty(); 737 } 738 739 inline const AtomicString& Element::idForStyleResolution() const 740 { 741 ASSERT(hasID()); 742 return elementData()->idForStyleResolution(); 743 } 744 745 inline const AtomicString& Element::shadowPseudoId() const 746 { 747 return pseudo(); 748 } 749 750 inline bool Element::isIdAttributeName(const QualifiedName& attributeName) const 751 { 752 // FIXME: This check is probably not correct for the case where the document has an id attribute 753 // with a non-null namespace, because it will return false, a false negative, if the prefixes 754 // don't match but the local name and namespace both do. However, since this has been like this 755 // for a while and the code paths may be hot, we'll have to measure performance if we fix it. 756 return attributeName == document().idAttributeName(); 757 } 758 759 inline const AtomicString& Element::getIdAttribute() const 760 { 761 return hasID() ? fastGetAttribute(document().idAttributeName()) : nullAtom; 762 } 763 764 inline const AtomicString& Element::getNameAttribute() const 765 { 766 return hasName() ? fastGetAttribute(HTMLNames::nameAttr) : nullAtom; 767 } 768 769 inline const AtomicString& Element::getClassAttribute() const 770 { 771 if (!hasClass()) 772 return nullAtom; 773 if (isSVGElement()) 774 return getAttribute(HTMLNames::classAttr); 775 return fastGetAttribute(HTMLNames::classAttr); 776 } 777 778 inline bool Element::shouldIgnoreAttributeCase() const 779 { 780 return isHTMLElement() && document().isHTMLDocument(); 781 } 782 783 inline void Element::setIdAttribute(const AtomicString& value) 784 { 785 setAttribute(document().idAttributeName(), value); 786 } 787 788 inline const SpaceSplitString& Element::classNames() const 789 { 790 ASSERT(hasClass()); 791 ASSERT(elementData()); 792 return elementData()->classNames(); 793 } 794 795 inline size_t Element::attributeCount() const 796 { 797 ASSERT(elementData()); 798 return elementData()->length(); 799 } 800 801 inline const Attribute* Element::attributeItem(unsigned index) const 802 { 803 ASSERT(elementData()); 804 return elementData()->attributeItem(index); 805 } 806 807 inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const 808 { 809 ASSERT(elementData()); 810 return elementData()->getAttributeItem(name); 811 } 812 813 inline bool Element::hasID() const 814 { 815 return elementData() && elementData()->hasID(); 816 } 817 818 inline bool Element::hasClass() const 819 { 820 return elementData() && elementData()->hasClass(); 821 } 822 823 inline UniqueElementData* Element::ensureUniqueElementData() 824 { 825 if (!elementData() || !elementData()->isUnique()) 826 createUniqueElementData(); 827 return static_cast<UniqueElementData*>(m_elementData.get()); 828 } 829 830 // Put here to make them inline. 831 inline bool Node::hasID() const 832 { 833 return isElementNode() && toElement(this)->hasID(); 834 } 835 836 inline bool Node::hasClass() const 837 { 838 return isElementNode() && toElement(this)->hasClass(); 839 } 840 841 inline Node::InsertionNotificationRequest Node::insertedInto(ContainerNode* insertionPoint) 842 { 843 ASSERT(insertionPoint->inDocument() || isContainerNode()); 844 if (insertionPoint->inDocument()) 845 setFlag(InDocumentFlag); 846 if (parentOrShadowHostNode()->isInShadowTree()) 847 setFlag(IsInShadowTreeFlag); 848 if (childNeedsDistributionRecalc() && !insertionPoint->childNeedsDistributionRecalc()) 849 insertionPoint->markAncestorsWithChildNeedsDistributionRecalc(); 850 return InsertionDone; 851 } 852 853 inline void Node::removedFrom(ContainerNode* insertionPoint) 854 { 855 ASSERT(insertionPoint->inDocument() || isContainerNode()); 856 if (insertionPoint->inDocument()) 857 clearFlag(InDocumentFlag); 858 if (isInShadowTree() && !treeScope().rootNode()->isShadowRoot()) 859 clearFlag(IsInShadowTreeFlag); 860 } 861 862 inline void Element::invalidateStyleAttribute() 863 { 864 ASSERT(elementData()); 865 elementData()->m_styleAttributeIsDirty = true; 866 } 867 868 inline const StylePropertySet* Element::presentationAttributeStyle() 869 { 870 if (!elementData()) 871 return 0; 872 if (elementData()->m_presentationAttributeStyleIsDirty) 873 updatePresentationAttributeStyle(); 874 // Need to call elementData() again since updatePresentationAttributeStyle() 875 // might swap it with a UniqueElementData. 876 return elementData()->presentationAttributeStyle(); 877 } 878 879 inline void Element::setTagNameForCreateElementNS(const QualifiedName& tagName) 880 { 881 // We expect this method to be called only to reset the prefix. 882 ASSERT(tagName.localName() == m_tagName.localName()); 883 ASSERT(tagName.namespaceURI() == m_tagName.namespaceURI()); 884 m_tagName = tagName; 885 } 886 887 inline bool isShadowHost(const Node* node) 888 { 889 return node && node->isElementNode() && toElement(node)->shadow(); 890 } 891 892 inline bool isShadowHost(const Element* element) 893 { 894 return element && element->shadow(); 895 } 896 897 } // namespace 898 899 #endif 900