/* | |
* Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
* (C) 1999 Antti Koivisto (koivisto@kde.org) | |
* (C) 2001 Peter Kelly (pmk@post.com) | |
* (C) 2001 Dirk Mueller (mueller@kde.org) | |
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | |
* | |
* This library is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Library General Public | |
* License as published by the Free Software Foundation; either | |
* version 2 of the License, or (at your option) any later version. | |
* | |
* This library is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Library General Public License for more details. | |
* | |
* You should have received a copy of the GNU Library General Public License | |
* along with this library; see the file COPYING.LIB. If not, write to | |
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
* Boston, MA 02110-1301, USA. | |
* | |
*/ | |
#ifndef Element_h | |
#define Element_h | |
#include "ContainerNode.h" | |
#include "Document.h" | |
#include "HTMLNames.h" | |
#include "MappedAttributeEntry.h" | |
#include "QualifiedName.h" | |
#include "ScrollTypes.h" | |
namespace WebCore { | |
class Attr; | |
class Attribute; | |
class CSSStyleDeclaration; | |
class ClientRect; | |
class ClientRectList; | |
class ElementRareData; | |
class IntSize; | |
class Element : public ContainerNode { | |
public: | |
static PassRefPtr<Element> create(const QualifiedName&, Document*); | |
virtual ~Element(); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(change); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(click); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragenter); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragleave); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(drop); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(drag); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(input); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseover); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseup); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(mousewheel); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(select); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(submit); | |
// These four attribute event handler attributes are overridden by HTMLBodyElement | |
// and HTMLFrameSetElement to forward to the DOMWindow. | |
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(blur); | |
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(error); | |
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(focus); | |
DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(load); | |
// WebKit extensions | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecut); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(cut); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(beforecopy); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(copy); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(beforepaste); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(paste); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(reset); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(search); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart); | |
#if ENABLE(TOUCH_EVENTS) | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); | |
DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); | |
#endif | |
virtual PassRefPtr<DocumentFragment> createContextualFragment(const String&, FragmentScriptingPermission = FragmentScriptingAllowed); | |
const AtomicString& getIDAttribute() const; | |
bool hasAttribute(const QualifiedName&) const; | |
const AtomicString& getAttribute(const QualifiedName&) const; | |
void setAttribute(const QualifiedName&, const AtomicString& value, ExceptionCode&); | |
void removeAttribute(const QualifiedName&, ExceptionCode&); | |
bool hasAttributes() const; | |
bool hasAttribute(const String& name) const; | |
bool hasAttributeNS(const String& namespaceURI, const String& localName) const; | |
const AtomicString& getAttribute(const String& name) const; | |
const AtomicString& getAttributeNS(const String& namespaceURI, const String& localName) const; | |
void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionCode&); | |
void setAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& value, ExceptionCode&, FragmentScriptingPermission = FragmentScriptingAllowed); | |
const QualifiedName& idAttributeName() const; | |
void scrollIntoView(bool alignToTop = true); | |
void scrollIntoViewIfNeeded(bool centerIfNeeded = true); | |
void scrollByLines(int lines); | |
void scrollByPages(int pages); | |
int offsetLeft(); | |
int offsetTop(); | |
int offsetWidth(); | |
int offsetHeight(); | |
Element* offsetParent(); | |
int clientLeft(); | |
int clientTop(); | |
int clientWidth(); | |
int clientHeight(); | |
virtual int scrollLeft() const; | |
virtual int scrollTop() const; | |
virtual void setScrollLeft(int); | |
virtual void setScrollTop(int); | |
virtual int scrollWidth() const; | |
virtual int scrollHeight() const; | |
PassRefPtr<ClientRectList> getClientRects() const; | |
PassRefPtr<ClientRect> getBoundingClientRect() const; | |
void removeAttribute(const String& name, ExceptionCode&); | |
void removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode&); | |
PassRefPtr<Attr> getAttributeNode(const String& name); | |
PassRefPtr<Attr> getAttributeNodeNS(const String& namespaceURI, const String& localName); | |
PassRefPtr<Attr> setAttributeNode(Attr*, ExceptionCode&); | |
PassRefPtr<Attr> setAttributeNodeNS(Attr*, ExceptionCode&); | |
PassRefPtr<Attr> removeAttributeNode(Attr*, ExceptionCode&); | |
virtual CSSStyleDeclaration* style(); | |
const QualifiedName& tagQName() const { return m_tagName; } | |
String tagName() const { return nodeName(); } | |
bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); } | |
// A fast function for checking the local name against another atomic string. | |
bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; } | |
bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); } | |
const AtomicString& localName() const { return m_tagName.localName(); } | |
const AtomicString& prefix() const { return m_tagName.prefix(); } | |
const AtomicString& namespaceURI() const { return m_tagName.namespaceURI(); } | |
virtual KURL baseURI() const; | |
virtual String nodeName() const; | |
PassRefPtr<Element> cloneElementWithChildren(); | |
PassRefPtr<Element> cloneElementWithoutChildren(); | |
void normalizeAttributes(); | |
String nodeNamePreservingCase() const; | |
// convenience methods which ignore exceptions | |
void setAttribute(const QualifiedName&, const AtomicString& value); | |
void setBooleanAttribute(const QualifiedName& name, bool); | |
// Please don't use setCStringAttribute in performance-sensitive code; | |
// use a static AtomicString value instead to avoid the conversion overhead. | |
void setCStringAttribute(const QualifiedName&, const char* cStringValue); | |
virtual NamedNodeMap* attributes() const; | |
NamedNodeMap* attributes(bool readonly) const; | |
// This method is called whenever an attribute is added, changed or removed. | |
virtual void attributeChanged(Attribute*, bool preserveDecls = false); | |
// not part of the DOM | |
void setAttributeMap(PassRefPtr<NamedNodeMap>, FragmentScriptingPermission = FragmentScriptingAllowed); | |
NamedNodeMap* attributeMap() const { return namedAttrMap.get(); } | |
virtual void copyNonAttributeProperties(const Element* /*source*/) { } | |
virtual void attach(); | |
virtual void detach(); | |
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); | |
virtual void recalcStyle(StyleChange = NoChange); | |
virtual RenderStyle* computedStyle(); | |
void dispatchAttrRemovalEvent(Attribute*); | |
void dispatchAttrAdditionEvent(Attribute*); | |
virtual void accessKeyAction(bool /*sendToAnyEvent*/) { } | |
virtual bool isURLAttribute(Attribute*) const; | |
KURL getURLAttribute(const QualifiedName&) const; | |
virtual const QualifiedName& imageSourceAttributeName() const; | |
virtual String target() const { return String(); } | |
virtual void focus(bool restorePreviousSelection = true); | |
virtual void updateFocusAppearance(bool restorePreviousSelection); | |
void blur(); | |
String innerText() const; | |
String outerText() const; | |
virtual String title() const; | |
String openTagStartToString() const; | |
void updateId(const AtomicString& oldId, const AtomicString& newId); | |
IntSize minimumSizeForResizing() const; | |
void setMinimumSizeForResizing(const IntSize&); | |
// Use Document::registerForDocumentActivationCallbacks() to subscribe to these | |
virtual void documentWillBecomeInactive() { } | |
virtual void documentDidBecomeActive() { } | |
// Use Document::registerForMediaVolumeCallbacks() to subscribe to this | |
virtual void mediaVolumeDidChange() { } | |
bool isFinishedParsingChildren() const { return m_parsingChildrenFinished; } | |
virtual void finishParsingChildren(); | |
virtual void beginParsingChildren() { m_parsingChildrenFinished = false; } | |
// ElementTraversal API | |
Element* firstElementChild() const; | |
Element* lastElementChild() const; | |
Element* previousElementSibling() const; | |
Element* nextElementSibling() const; | |
unsigned childElementCount() const; | |
bool webkitMatchesSelector(const String& selectors, ExceptionCode&); | |
virtual bool isFormControlElement() const { return false; } | |
virtual bool isEnabledFormControl() const { return true; } | |
virtual bool isReadOnlyFormControl() const { return false; } | |
virtual bool isTextFormControl() const { return false; } | |
virtual bool isOptionalFormControl() const { return false; } | |
virtual bool isRequiredFormControl() const { return false; } | |
virtual bool isDefaultButtonForForm() const { return false; } | |
virtual bool willValidate() const { return false; } | |
virtual bool isValidFormControlElement() { return false; } | |
virtual bool formControlValueMatchesRenderer() const { return false; } | |
virtual void setFormControlValueMatchesRenderer(bool) { } | |
virtual const AtomicString& formControlName() const { return nullAtom; } | |
virtual const AtomicString& formControlType() const { return nullAtom; } | |
virtual bool saveFormControlState(String&) const { return false; } | |
virtual void restoreFormControlState(const String&) { } | |
virtual void dispatchFormControlChangeEvent() { } | |
#if ENABLE(SVG) | |
virtual bool childShouldCreateRenderer(Node*) const; | |
#endif | |
protected: | |
Element(const QualifiedName&, Document*, ConstructionType); | |
virtual void insertedIntoDocument(); | |
virtual void removedFromDocument(); | |
virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); | |
// The implementation of Element::attributeChanged() calls the following two functions. | |
// They are separated to allow a different flow of control in StyledElement::attributeChanged(). | |
void recalcStyleIfNeededAfterAttributeChanged(Attribute*); | |
void updateAfterAttributeChanged(Attribute*); | |
private: | |
void scrollByUnits(int units, ScrollGranularity); | |
virtual void setPrefix(const AtomicString&, ExceptionCode&); | |
virtual NodeType nodeType() const; | |
virtual bool childTypeAllowed(NodeType); | |
virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value); | |
const QualifiedName& rareIDAttributeName() const; | |
#ifndef NDEBUG | |
virtual void formatForDebugger(char* buffer, unsigned length) const; | |
#endif | |
bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); | |
virtual void createAttributeMap() const; | |
virtual void updateStyleAttribute() const { } | |
#if ENABLE(SVG) | |
virtual void updateAnimatedSVGAttribute(const QualifiedName&) const { } | |
#endif | |
void cancelFocusAppearanceUpdate(); | |
virtual const AtomicString& virtualPrefix() const { return prefix(); } | |
virtual const AtomicString& virtualLocalName() const { return localName(); } | |
virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); } | |
// cloneNode is private so that non-virtual cloneElementWithChildren and cloneElementWithoutChildren | |
// are used instead. | |
virtual PassRefPtr<Node> cloneNode(bool deep); | |
QualifiedName m_tagName; | |
virtual NodeRareData* createRareData(); | |
ElementRareData* rareData() const; | |
ElementRareData* ensureRareData(); | |
protected: | |
mutable RefPtr<NamedNodeMap> namedAttrMap; | |
}; | |
inline bool Node::hasTagName(const QualifiedName& name) const | |
{ | |
return isElementNode() && static_cast<const Element*>(this)->hasTagName(name); | |
} | |
inline bool Node::hasAttributes() const | |
{ | |
return isElementNode() && static_cast<const Element*>(this)->hasAttributes(); | |
} | |
inline NamedNodeMap* Node::attributes() const | |
{ | |
return isElementNode() ? static_cast<const Element*>(this)->attributes() : 0; | |
} | |
inline Element* Node::parentElement() const | |
{ | |
Node* parent = parentNode(); | |
return parent && parent->isElementNode() ? static_cast<Element*>(parent) : 0; | |
} | |
inline const QualifiedName& Element::idAttributeName() const | |
{ | |
return hasRareData() ? rareIDAttributeName() : HTMLNames::idAttr; | |
} | |
inline NamedNodeMap* Element::attributes(bool readonly) const | |
{ | |
if (!m_isStyleAttributeValid) | |
updateStyleAttribute(); | |
#if ENABLE(SVG) | |
if (!m_areSVGAttributesValid) | |
updateAnimatedSVGAttribute(anyQName()); | |
#endif | |
if (!readonly && !namedAttrMap) | |
createAttributeMap(); | |
return namedAttrMap.get(); | |
} | |
inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId) | |
{ | |
if (!inDocument()) | |
return; | |
if (oldId == newId) | |
return; | |
Document* doc = document(); | |
if (!oldId.isEmpty()) | |
doc->removeElementById(oldId, this); | |
if (!newId.isEmpty()) | |
doc->addElementById(newId, this); | |
} | |
} //namespace | |
#endif |