2 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include "qwebelement.h"
23 #include "CSSComputedStyleDeclaration.h"
24 #include "CSSMutableStyleDeclaration.h"
25 #include "CSSParser.h"
27 #include "CSSRuleList.h"
28 #include "CSSStyleRule.h"
31 #include "DocumentFragment.h"
32 #include "FrameView.h"
33 #include "GraphicsContext.h"
34 #include "HTMLElement.h"
35 #include "JSGlobalObject.h"
36 #include "JSHTMLElement.h"
39 #include "PropertyNameArray.h"
40 #include "RenderImage.h"
41 #include "ScriptFunctionCall.h"
42 #include "StaticNodeList.h"
43 #include "qt_runtime.h"
44 #include "qwebframe.h"
45 #include "qwebframe_p.h"
46 #include "runtime_root.h"
47 #include <parser/SourceCode.h>
48 #include <wtf/Vector.h>
52 using namespace WebCore;
54 class QWebElementPrivate {
61 \brief The QWebElement class provides convenient access to DOM elements in
65 A QWebElement object allows easy access to the document model, represented
66 by a tree-like structure of DOM elements. The root of the tree is called
67 the document element and can be accessed using
68 QWebFrame::documentElement().
70 Specific elements can be accessed using findAll() and findFirst(). These
71 elements are identified using CSS selectors. The code snippet below
72 demonstrates the use of findAll().
74 \snippet webkitsnippets/webelement/main.cpp FindAll
76 The first list contains all \c span elements in the document. The second
77 list contains \c span elements that are children of \c p, classified with
80 Using findFirst() is more efficient than calling findAll(), and extracting
81 the first element only in the list returned.
83 Alternatively you can traverse the document manually using firstChild() and
86 \snippet webkitsnippets/webelement/main.cpp Traversing with QWebElement
88 The underlying content of QWebElement is explicitly shared. Creating a copy
89 of a QWebElement does not create a copy of the content. Instead, both
90 instances point to the same element.
92 The element's attributes can be read using attribute() and modified with
95 The contents of child elements can be converted to plain text with
96 toPlainText(); to XHTML using toInnerXml(). To include the element's tag in
97 the output, use toOuterXml().
99 It is possible to replace the contents of child elements using
100 setPlainText() and setInnerXml(). To replace the element itself and its
101 contents, use setOuterXml().
105 The \l{DOM Traversal Example} shows one way to traverse documents in a running
108 The \l{Simple Selector Example} can be used to experiment with the searching
109 features of this class and provides sample code you can start working with.
113 Constructs a null web element.
115 QWebElement::QWebElement()
124 QWebElement::QWebElement(WebCore::Element* domElement)
126 , m_element(domElement)
135 QWebElement::QWebElement(WebCore::Node* node)
139 if (node && node->isHTMLElement()) {
140 m_element = static_cast<HTMLElement*>(node);
146 Constructs a copy of \a other.
148 QWebElement::QWebElement(const QWebElement &other)
150 , m_element(other.m_element)
157 Assigns \a other to this element and returns a reference to this element.
159 QWebElement &QWebElement::operator=(const QWebElement &other)
161 // ### handle "d" assignment
162 if (this != &other) {
163 Element *otherElement = other.m_element;
168 m_element = otherElement;
174 Destroys the element. However, the underlying DOM element is not destroyed.
176 QWebElement::~QWebElement()
183 bool QWebElement::operator==(const QWebElement& o) const
185 return m_element == o.m_element;
188 bool QWebElement::operator!=(const QWebElement& o) const
190 return m_element != o.m_element;
194 Returns true if the element is a null element; otherwise returns false.
196 bool QWebElement::isNull() const
202 Returns a new list of child elements matching the given CSS selector
203 \a selectorQuery. If there are no matching elements, an empty list is
206 \l{Standard CSS2 selector} syntax is used for the query.
208 \note This search is performed recursively.
212 QWebElementCollection QWebElement::findAll(const QString &selectorQuery) const
214 return QWebElementCollection(*this, selectorQuery);
218 Returns the first child element that matches the given CSS selector
221 \l{Standard CSS2 selector} syntax is used for the query.
223 \note This search is performed recursively.
227 QWebElement QWebElement::findFirst(const QString &selectorQuery) const
230 return QWebElement();
231 ExceptionCode exception = 0; // ###
232 return QWebElement(m_element->querySelector(selectorQuery, exception).get());
236 Replaces the existing content of this element with \a text.
238 This is equivalent to setting the HTML innerText property.
242 void QWebElement::setPlainText(const QString &text)
244 if (!m_element || !m_element->isHTMLElement())
246 ExceptionCode exception = 0;
247 static_cast<HTMLElement*>(m_element)->setInnerText(text, exception);
251 Returns the text between the start and the end tag of this
254 This is equivalent to reading the HTML innerText property.
258 QString QWebElement::toPlainText() const
260 if (!m_element || !m_element->isHTMLElement())
262 return static_cast<HTMLElement*>(m_element)->innerText();
266 Replaces the contents of this element as well as its own tag with
267 \a markup. The string may contain HTML or XML tags, which is parsed and
268 formatted before insertion into the document.
270 \note This is currently only implemented for (X)HTML elements.
272 \sa toOuterXml(), toInnerXml(), setInnerXml()
274 void QWebElement::setOuterXml(const QString &markup)
276 if (!m_element || !m_element->isHTMLElement())
279 ExceptionCode exception = 0;
281 static_cast<HTMLElement*>(m_element)->setOuterHTML(markup, exception);
285 Returns this element converted to XML, including the start and the end
286 tags as well as its attributes.
288 \note This is currently implemented for (X)HTML elements only.
290 \sa setOuterXml(), setInnerXml(), toInnerXml()
292 QString QWebElement::toOuterXml() const
294 if (!m_element || !m_element->isHTMLElement())
297 return static_cast<HTMLElement*>(m_element)->outerHTML();
301 Replaces the contents of this element with \a markup. The string may
302 contain HTML or XML tags, which is parsed and formatted before insertion
305 \note This is currently implemented for (X)HTML elements only.
307 \sa toInnerXml(), toOuterXml(), setOuterXml()
309 void QWebElement::setInnerXml(const QString &markup)
311 if (!m_element || !m_element->isHTMLElement())
314 ExceptionCode exception = 0;
316 static_cast<HTMLElement*>(m_element)->setInnerHTML(markup, exception);
320 Returns the XML content between the element's start and end tags.
322 \note This is currently implemented for (X)HTML elements only.
324 \sa setInnerXml(), setOuterXml(), toOuterXml()
326 QString QWebElement::toInnerXml() const
328 if (!m_element || !m_element->isHTMLElement())
331 return static_cast<HTMLElement*>(m_element)->innerHTML();
335 Adds an attribute with the given \a name and \a value. If an attribute with
336 the same name exists, its value is replaced by \a value.
338 \sa attribute(), attributeNS(), setAttributeNS()
340 void QWebElement::setAttribute(const QString &name, const QString &value)
344 ExceptionCode exception = 0;
345 m_element->setAttribute(name, value, exception);
349 Adds an attribute with the given \a name in \a namespaceUri with \a value.
350 If an attribute with the same name exists, its value is replaced by
353 \sa attributeNS(), attribute(), setAttribute()
355 void QWebElement::setAttributeNS(const QString &namespaceUri, const QString &name, const QString &value)
359 WebCore::ExceptionCode exception = 0;
360 m_element->setAttributeNS(namespaceUri, name, value, exception);
364 Returns the attribute with the given \a name. If the attribute does not
365 exist, \a defaultValue is returned.
367 \sa setAttribute(), setAttributeNS(), attributeNS()
369 QString QWebElement::attribute(const QString &name, const QString &defaultValue) const
373 if (m_element->hasAttribute(name))
374 return m_element->getAttribute(name);
380 Returns the attribute with the given \a name in \a namespaceUri. If the
381 attribute does not exist, \a defaultValue is returned.
383 \sa setAttributeNS(), setAttribute(), attribute()
385 QString QWebElement::attributeNS(const QString &namespaceUri, const QString &name, const QString &defaultValue) const
389 if (m_element->hasAttributeNS(namespaceUri, name))
390 return m_element->getAttributeNS(namespaceUri, name);
396 Returns true if this element has an attribute with the given \a name;
397 otherwise returns false.
399 \sa attribute(), setAttribute()
401 bool QWebElement::hasAttribute(const QString &name) const
405 return m_element->hasAttribute(name);
409 Returns true if this element has an attribute with the given \a name, in
410 \a namespaceUri; otherwise returns false.
412 \sa attributeNS(), setAttributeNS()
414 bool QWebElement::hasAttributeNS(const QString &namespaceUri, const QString &name) const
418 return m_element->hasAttributeNS(namespaceUri, name);
422 Removes the attribute with the given \a name from this element.
424 \sa attribute(), setAttribute(), hasAttribute()
426 void QWebElement::removeAttribute(const QString &name)
430 ExceptionCode exception = 0;
431 m_element->removeAttribute(name, exception);
435 Removes the attribute with the given \a name, in \a namespaceUri, from this
438 \sa attributeNS(), setAttributeNS(), hasAttributeNS()
440 void QWebElement::removeAttributeNS(const QString &namespaceUri, const QString &name)
444 WebCore::ExceptionCode exception = 0;
445 m_element->removeAttributeNS(namespaceUri, name, exception);
449 Returns true if the element has any attributes defined; otherwise returns
452 \sa attribute(), setAttribute()
454 bool QWebElement::hasAttributes() const
458 return m_element->hasAttributes();
462 Return the list of attributes for the namespace given as \a namespaceUri.
464 \sa attribute(), setAttribute()
466 QStringList QWebElement::attributeNames(const QString& namespaceUri) const
469 return QStringList();
471 QStringList attributeNameList;
472 const NamedNodeMap* const attrs = m_element->attributes(/* read only = */ true);
474 const String namespaceUriString(namespaceUri); // convert QString -> String once
475 const unsigned attrsCount = attrs->length();
476 for (unsigned i = 0; i < attrsCount; ++i) {
477 const Attribute* const attribute = attrs->attributeItem(i);
478 if (namespaceUriString == attribute->namespaceURI())
479 attributeNameList.append(attribute->localName());
482 return attributeNameList;
486 Returns true if the element has keyboard input focus; otherwise, returns false
490 bool QWebElement::hasFocus() const
494 if (m_element->document())
495 return m_element == m_element->document()->focusedNode();
500 Gives keyboard input focus to this element
504 void QWebElement::setFocus()
508 if (m_element->document() && m_element->isFocusable())
509 m_element->document()->setFocusedNode(m_element);
513 Returns the geometry of this element, relative to its containing frame.
517 QRect QWebElement::geometry() const
521 return m_element->getRect();
525 Returns the tag name of this element.
529 QString QWebElement::tagName() const
533 return m_element->tagName();
537 Returns the namespace prefix of the element. If the element has no\
538 namespace prefix, empty string is returned.
540 QString QWebElement::prefix() const
544 return m_element->prefix();
548 Returns the local name of the element. If the element does not use
549 namespaces, an empty string is returned.
551 QString QWebElement::localName() const
555 return m_element->localName();
559 Returns the namespace URI of this element. If the element has no namespace
560 URI, an empty string is returned.
562 QString QWebElement::namespaceUri() const
566 return m_element->namespaceURI();
570 Returns the parent element of this elemen. If this element is the root
571 document element, a null element is returned.
573 QWebElement QWebElement::parent() const
576 return QWebElement(m_element->parentElement());
577 return QWebElement();
581 Returns the element's first child.
583 \sa lastChild(), previousSibling(), nextSibling()
585 QWebElement QWebElement::firstChild() const
588 return QWebElement();
589 for (Node* child = m_element->firstChild(); child; child = child->nextSibling()) {
590 if (!child->isElementNode())
592 Element* e = static_cast<Element*>(child);
593 return QWebElement(e);
595 return QWebElement();
599 Returns the element's last child.
601 \sa firstChild(), previousSibling(), nextSibling()
603 QWebElement QWebElement::lastChild() const
606 return QWebElement();
607 for (Node* child = m_element->lastChild(); child; child = child->previousSibling()) {
608 if (!child->isElementNode())
610 Element* e = static_cast<Element*>(child);
611 return QWebElement(e);
613 return QWebElement();
617 Returns the element's next sibling.
619 \sa firstChild(), previousSibling(), lastChild()
621 QWebElement QWebElement::nextSibling() const
624 return QWebElement();
625 for (Node* sib = m_element->nextSibling(); sib; sib = sib->nextSibling()) {
626 if (!sib->isElementNode())
628 Element* e = static_cast<Element*>(sib);
629 return QWebElement(e);
631 return QWebElement();
635 Returns the element's previous sibling.
637 \sa firstChild(), nextSibling(), lastChild()
639 QWebElement QWebElement::previousSibling() const
642 return QWebElement();
643 for (Node* sib = m_element->previousSibling(); sib; sib = sib->previousSibling()) {
644 if (!sib->isElementNode())
646 Element* e = static_cast<Element*>(sib);
647 return QWebElement(e);
649 return QWebElement();
653 Returns the document which this element belongs to.
655 QWebElement QWebElement::document() const
658 return QWebElement();
659 Document* document = m_element->document();
661 return QWebElement();
662 return QWebElement(document->documentElement());
666 Returns the web frame which this element is a part of. If the element is a
667 null element, null is returned.
669 QWebFrame *QWebElement::webFrame() const
674 Document* document = m_element->document();
678 Frame* frame = document->frame();
681 return QWebFramePrivate::kit(frame);
684 static bool setupScriptContext(WebCore::Element* element, JSC::JSValue& thisValue, ScriptState*& state, ScriptController*& scriptController)
689 Document* document = element->document();
693 Frame* frame = document->frame();
697 scriptController = frame->script();
698 if (!scriptController)
701 state = scriptController->globalObject(mainThreadNormalWorld())->globalExec();
705 thisValue = toJS(state, element);
714 Executes \a scriptSource with this element as \c this object.
716 QVariant QWebElement::evaluateJavaScript(const QString& scriptSource)
718 if (scriptSource.isEmpty())
721 ScriptState* state = 0;
722 JSC::JSValue thisValue;
723 ScriptController* scriptController = 0;
725 if (!setupScriptContext(m_element, thisValue, state, scriptController))
728 JSC::ScopeChain& scopeChain = state->dynamicGlobalObject()->globalScopeChain();
729 JSC::UString script((const UChar*)scriptSource.data(), scriptSource.length());
730 JSC::Completion completion = JSC::evaluate(state, scopeChain, JSC::makeSource(script), thisValue);
731 if ((completion.complType() != JSC::ReturnValue) && (completion.complType() != JSC::Normal))
734 JSC::JSValue result = completion.value();
739 return JSC::Bindings::convertValueToQVariant(state, result, QMetaType::Void, &distance);
743 \enum QWebElement::StyleResolveStrategy
745 This enum describes how QWebElement's styleProperty resolves the given
748 \value InlineStyle Return the property value as it is defined in
749 the element, without respecting style inheritance and other CSS
751 \value CascadedStyle The property's value is determined using the
752 inheritance and importance rules defined in the document's
754 \value ComputedStyle The property's value is the absolute value
755 of the style property resolved from the environment.
759 Returns the value of the style with the given \a name using the specified
760 \a strategy. If a style with \a name does not exist, an empty string is
763 In CSS, the cascading part depends on which CSS rule has priority and is
764 thus applied. Generally, the last defined rule has priority. Thus, an
765 inline style rule has priority over an embedded block style rule, which
766 in return has priority over an external style rule.
768 If the "!important" declaration is set on one of those, the declaration
769 receives highest priority, unless other declarations also use the
770 "!important" declaration. Then, the last "!important" declaration takes
773 \sa setStyleProperty()
776 QString QWebElement::styleProperty(const QString &name, StyleResolveStrategy strategy) const
778 if (!m_element || !m_element->isStyledElement())
781 int propID = cssPropertyID(name);
786 CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style();
788 if (strategy == InlineStyle)
789 return style->getPropertyValue(propID);
791 if (strategy == CascadedStyle) {
792 if (style->getPropertyPriority(propID))
793 return style->getPropertyValue(propID);
795 // We are going to resolve the style property by walking through the
796 // list of non-inline matched CSS rules for the element, looking for
797 // the highest priority definition.
799 // Get an array of matched CSS rules for the given element sorted
800 // by importance and inheritance order. This include external CSS
801 // declarations, as well as embedded and inline style declarations.
803 DOMWindow* domWindow = m_element->document()->frame()->domWindow();
804 if (RefPtr<CSSRuleList> rules = domWindow->getMatchedCSSRules(m_element, "")) {
805 for (int i = rules->length(); i > 0; --i) {
806 CSSStyleRule* rule = static_cast<CSSStyleRule*>(rules->item(i - 1));
808 if (rule->style()->getPropertyPriority(propID))
809 return rule->style()->getPropertyValue(propID);
811 if (style->getPropertyValue(propID).isEmpty())
812 style = rule->style();
816 return style->getPropertyValue(propID);
819 if (strategy == ComputedStyle) {
820 if (!m_element || !m_element->isStyledElement())
823 int propID = cssPropertyID(name);
825 RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element);
826 if (!propID || !style)
829 return style->getPropertyValue(propID);
836 Sets the value of the inline style with the given \a name to \a value.
838 Setting a value, does not necessarily mean that it will become the applied
839 value, due to the fact that the style property's value might have been set
840 earlier with a higher priority in external or embedded style declarations.
842 In order to ensure that the value will be applied, you may have to append
843 "!important" to the value.
845 void QWebElement::setStyleProperty(const QString &name, const QString &value)
847 if (!m_element || !m_element->isStyledElement())
850 int propID = cssPropertyID(name);
851 CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style();
852 if (!propID || !style)
855 ExceptionCode exception = 0;
856 style->setProperty(name, value, exception);
860 Returns the list of classes of this element.
862 QStringList QWebElement::classes() const
864 if (!hasAttribute(QLatin1String("class")))
865 return QStringList();
867 QStringList classes = attribute(QLatin1String("class")).simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
868 #if QT_VERSION >= 0x040500
869 classes.removeDuplicates();
871 int n = classes.size();
875 for (int i = 0; i < n; ++i) {
876 const QString& s = classes.at(i);
877 if (seen.contains(s))
885 classes.erase(classes.begin() + j, classes.end());
891 Returns true if this element has a class with the given \a name; otherwise
894 bool QWebElement::hasClass(const QString &name) const
896 QStringList list = classes();
897 return list.contains(name);
901 Adds the specified class with the given \a name to the element.
903 void QWebElement::addClass(const QString &name)
905 QStringList list = classes();
906 if (!list.contains(name)) {
908 QString value = list.join(QLatin1String(" "));
909 setAttribute(QLatin1String("class"), value);
914 Removes the specified class with the given \a name from the element.
916 void QWebElement::removeClass(const QString &name)
918 QStringList list = classes();
919 if (list.contains(name)) {
920 list.removeAll(name);
921 QString value = list.join(QLatin1String(" "));
922 setAttribute(QLatin1String("class"), value);
927 Adds the specified class with the given \a name if it is not present. If
928 the class is already present, it will be removed.
930 void QWebElement::toggleClass(const QString &name)
932 QStringList list = classes();
933 if (list.contains(name))
934 list.removeAll(name);
938 QString value = list.join(QLatin1String(" "));
939 setAttribute(QLatin1String("class"), value);
943 Appends the given \a element as the element's last child.
945 If \a element is the child of another element, it is re-parented to this
946 element. If \a element is a child of this element, then its position in
947 the list of children is changed.
949 Calling this function on a null element does nothing.
951 \sa prependInside(), prependOutside(), appendOutside()
953 void QWebElement::appendInside(const QWebElement &element)
955 if (!m_element || element.isNull())
958 ExceptionCode exception = 0;
959 m_element->appendChild(element.m_element, exception);
963 Appends the result of parsing \a markup as the element's last child.
965 Calling this function on a null element does nothing.
967 \sa prependInside(), prependOutside(), appendOutside()
969 void QWebElement::appendInside(const QString &markup)
974 if (!m_element->isHTMLElement())
977 HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
978 RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
980 ExceptionCode exception = 0;
981 m_element->appendChild(fragment, exception);
985 Prepends \a element as the element's first child.
987 If \a element is the child of another element, it is re-parented to this
988 element. If \a element is a child of this element, then its position in
989 the list of children is changed.
991 Calling this function on a null element does nothing.
993 \sa appendInside(), prependOutside(), appendOutside()
995 void QWebElement::prependInside(const QWebElement &element)
997 if (!m_element || element.isNull())
1000 ExceptionCode exception = 0;
1002 if (m_element->hasChildNodes())
1003 m_element->insertBefore(element.m_element, m_element->firstChild(), exception);
1005 m_element->appendChild(element.m_element, exception);
1009 Prepends the result of parsing \a markup as the element's first child.
1011 Calling this function on a null element does nothing.
1013 \sa appendInside(), prependOutside(), appendOutside()
1015 void QWebElement::prependInside(const QString &markup)
1020 if (!m_element->isHTMLElement())
1023 HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1024 RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1026 ExceptionCode exception = 0;
1028 if (m_element->hasChildNodes())
1029 m_element->insertBefore(fragment, m_element->firstChild(), exception);
1031 m_element->appendChild(fragment, exception);
1036 Inserts the given \a element before this element.
1038 If \a element is the child of another element, it is re-parented to the
1039 parent of this element.
1041 Calling this function on a null element does nothing.
1043 \sa appendInside(), prependInside(), appendOutside()
1045 void QWebElement::prependOutside(const QWebElement &element)
1047 if (!m_element || element.isNull())
1050 if (!m_element->parent())
1053 ExceptionCode exception = 0;
1054 m_element->parent()->insertBefore(element.m_element, m_element, exception);
1058 Inserts the result of parsing \a markup before this element.
1060 Calling this function on a null element does nothing.
1062 \sa appendInside(), prependInside(), appendOutside()
1064 void QWebElement::prependOutside(const QString &markup)
1069 if (!m_element->parent())
1072 if (!m_element->isHTMLElement())
1075 HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1076 RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1078 ExceptionCode exception = 0;
1079 m_element->parent()->insertBefore(fragment, m_element, exception);
1083 Inserts the given \a element after this element.
1085 If \a element is the child of another element, it is re-parented to the
1086 parent of this element.
1088 Calling this function on a null element does nothing.
1090 \sa appendInside(), prependInside(), prependOutside()
1092 void QWebElement::appendOutside(const QWebElement &element)
1094 if (!m_element || element.isNull())
1097 if (!m_element->parent())
1100 ExceptionCode exception = 0;
1101 if (!m_element->nextSibling())
1102 m_element->parent()->appendChild(element.m_element, exception);
1104 m_element->parent()->insertBefore(element.m_element, m_element->nextSibling(), exception);
1108 Inserts the result of parsing \a markup after this element.
1110 Calling this function on a null element does nothing.
1112 \sa appendInside(), prependInside(), prependOutside()
1114 void QWebElement::appendOutside(const QString &markup)
1119 if (!m_element->parent())
1122 if (!m_element->isHTMLElement())
1125 HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1126 RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1128 ExceptionCode exception = 0;
1129 if (!m_element->nextSibling())
1130 m_element->parent()->appendChild(fragment, exception);
1132 m_element->parent()->insertBefore(fragment, m_element->nextSibling(), exception);
1136 Returns a clone of this element.
1138 The clone may be inserted at any point in the document.
1140 \sa appendInside(), prependInside(), prependOutside(), appendOutside()
1142 QWebElement QWebElement::clone() const
1145 return QWebElement();
1147 return QWebElement(m_element->cloneElementWithChildren().get());
1151 Removes this element from the document and returns a reference to it.
1153 The element is still valid after removal, and can be inserted into other
1154 parts of the document.
1156 \sa removeAllChildren(), removeFromDocument()
1158 QWebElement &QWebElement::takeFromDocument()
1163 ExceptionCode exception = 0;
1164 m_element->remove(exception);
1170 Removes this element from the document and makes it a null element.
1172 \sa removeAllChildren(), takeFromDocument()
1174 void QWebElement::removeFromDocument()
1179 ExceptionCode exception = 0;
1180 m_element->remove(exception);
1186 Removes all children from this element.
1188 \sa removeFromDocument(), takeFromDocument()
1190 void QWebElement::removeAllChildren()
1195 m_element->removeAllChildren();
1198 static RefPtr<Node> findInsertionPoint(PassRefPtr<Node> root)
1200 RefPtr<Node> node = root;
1202 // Go as far down the tree as possible.
1203 while (node->hasChildNodes() && node->firstChild()->isElementNode())
1204 node = node->firstChild();
1206 // TODO: Implement SVG support
1207 if (node->isHTMLElement()) {
1208 HTMLElement* element = static_cast<HTMLElement*>(node.get());
1210 // The insert point could be a non-enclosable tag and it can thus
1211 // never have children, so go one up. Get the parent element, and not
1212 // note as a root note will always exist.
1213 if (element->endTagRequirement() == TagStatusForbidden)
1214 node = node->parentElement();
1221 Encloses the contents of this element with \a element. This element becomes
1222 the child of the deepest descendant within \a element.
1228 void QWebElement::encloseContentsWith(const QWebElement &element)
1230 if (!m_element || element.isNull())
1233 RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element);
1235 if (!insertionPoint)
1238 ExceptionCode exception = 0;
1240 // reparent children
1241 for (RefPtr<Node> child = m_element->firstChild(); child;) {
1242 RefPtr<Node> next = child->nextSibling();
1243 insertionPoint->appendChild(child, exception);
1247 if (m_element->hasChildNodes())
1248 m_element->insertBefore(element.m_element, m_element->firstChild(), exception);
1250 m_element->appendChild(element.m_element, exception);
1254 Encloses the contents of this element with the result of parsing \a markup.
1255 This element becomes the child of the deepest descendant within \a markup.
1259 void QWebElement::encloseContentsWith(const QString &markup)
1264 if (!m_element->parent())
1267 if (!m_element->isHTMLElement())
1270 HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1271 RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1273 if (!fragment || !fragment->firstChild())
1276 RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild());
1278 if (!insertionPoint)
1281 ExceptionCode exception = 0;
1283 // reparent children
1284 for (RefPtr<Node> child = m_element->firstChild(); child;) {
1285 RefPtr<Node> next = child->nextSibling();
1286 insertionPoint->appendChild(child, exception);
1290 if (m_element->hasChildNodes())
1291 m_element->insertBefore(fragment, m_element->firstChild(), exception);
1293 m_element->appendChild(fragment, exception);
1297 Encloses this element with \a element. This element becomes the child of
1298 the deepest descendant within \a element.
1302 void QWebElement::encloseWith(const QWebElement &element)
1304 if (!m_element || element.isNull())
1307 RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element);
1309 if (!insertionPoint)
1312 // Keep reference to these two nodes before pulling out this element and
1313 // wrapping it in the fragment. The reason for doing it in this order is
1314 // that once the fragment has been added to the document it is empty, so
1315 // we no longer have access to the nodes it contained.
1316 Node* parentNode = m_element->parent();
1317 Node* siblingNode = m_element->nextSibling();
1319 ExceptionCode exception = 0;
1320 insertionPoint->appendChild(m_element, exception);
1323 parentNode->appendChild(element.m_element, exception);
1325 parentNode->insertBefore(element.m_element, siblingNode, exception);
1329 Encloses this element with the result of parsing \a markup. This element
1330 becomes the child of the deepest descendant within \a markup.
1334 void QWebElement::encloseWith(const QString &markup)
1339 if (!m_element->parent())
1342 if (!m_element->isHTMLElement())
1345 HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
1346 RefPtr<DocumentFragment> fragment = htmlElement->createContextualFragment(markup);
1348 if (!fragment || !fragment->firstChild())
1351 RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild());
1353 if (!insertionPoint)
1356 // Keep reference to these two nodes before pulling out this element and
1357 // wrapping it in the fragment. The reason for doing it in this order is
1358 // that once the fragment has been added to the document it is empty, so
1359 // we no longer have access to the nodes it contained.
1360 Node* parentNode = m_element->parent();
1361 Node* siblingNode = m_element->nextSibling();
1363 ExceptionCode exception = 0;
1364 insertionPoint->appendChild(m_element, exception);
1367 parentNode->appendChild(fragment, exception);
1369 parentNode->insertBefore(fragment, siblingNode, exception);
1373 Replaces this element with \a element.
1375 This method will not replace the <html>, <head> or <body> elements.
1379 void QWebElement::replace(const QWebElement &element)
1381 if (!m_element || element.isNull())
1384 appendOutside(element);
1389 Replaces this element with the result of parsing \a markup.
1391 This method will not replace the <html>, <head> or <body> elements.
1395 void QWebElement::replace(const QString &markup)
1400 appendOutside(markup);
1406 Walk \a node's parents until a valid QWebElement is found.
1407 For example, a WebCore::Text node is not a valid Html QWebElement, but its
1410 QWebElement QWebElement::enclosingElement(WebCore::Node* node)
1412 QWebElement element(node);
1414 while (element.isNull() && node) {
1415 node = node->parentNode();
1416 element = QWebElement(node);
1422 \fn inline bool QWebElement::operator==(const QWebElement& o) const;
1424 Returns true if this element points to the same underlying DOM object as
1425 \a o; otherwise returns false.
1429 \fn inline bool QWebElement::operator!=(const QWebElement& o) const;
1431 Returns true if this element points to a different underlying DOM object
1432 than \a o; otherwise returns false.
1437 Render the element into \a painter .
1439 void QWebElement::render(QPainter* painter)
1441 WebCore::Element* e = m_element;
1442 Document* doc = e ? e->document() : 0;
1446 Frame* frame = doc->frame();
1447 if (!frame || !frame->view() || !frame->contentRenderer())
1450 FrameView* view = frame->view();
1452 view->layoutIfNeededRecursive();
1454 IntRect rect = e->getRect();
1456 if (rect.size().isEmpty())
1459 GraphicsContext context(painter);
1462 context.translate(-rect.x(), -rect.y());
1463 view->setNodeToDraw(e);
1464 view->paintContents(&context, rect);
1465 view->setNodeToDraw(0);
1469 class QWebElementCollectionPrivate : public QSharedData
1472 static QWebElementCollectionPrivate* create(const PassRefPtr<Node> &context, const QString &query);
1474 RefPtr<NodeList> m_result;
1477 inline QWebElementCollectionPrivate() {}
1480 QWebElementCollectionPrivate* QWebElementCollectionPrivate::create(const PassRefPtr<Node> &context, const QString &query)
1485 // Let WebKit do the hard work hehehe
1486 ExceptionCode exception = 0; // ###
1487 RefPtr<NodeList> nodes = context->querySelectorAll(query, exception);
1491 QWebElementCollectionPrivate* priv = new QWebElementCollectionPrivate;
1492 priv->m_result = nodes;
1497 \class QWebElementCollection
1499 \brief The QWebElementCollection class represents a collection of web elements.
1502 Elements in a document can be selected using QWebElement::findAll() or using the
1503 QWebElement constructor. The collection is composed by choosing all elements in the
1504 document that match a specified CSS selector expression.
1506 The number of selected elements is provided through the count() property. Individual
1507 elements can be retrieved by index using at().
1509 It is also possible to iterate through all elements in the collection using Qt's foreach
1513 QWebElementCollection collection = document.findAll("p");
1514 foreach (QWebElement paraElement, collection) {
1521 Constructs an empty collection.
1523 QWebElementCollection::QWebElementCollection()
1528 Constructs a copy of \a other.
1530 QWebElementCollection::QWebElementCollection(const QWebElementCollection &other)
1536 Constructs a collection of elements from the list of child elements of \a contextElement that
1537 match the specified CSS selector \a query.
1539 QWebElementCollection::QWebElementCollection(const QWebElement &contextElement, const QString &query)
1541 d = QExplicitlySharedDataPointer<QWebElementCollectionPrivate>(QWebElementCollectionPrivate::create(contextElement.m_element, query));
1545 Assigns \a other to this collection and returns a reference to this collection.
1547 QWebElementCollection &QWebElementCollection::operator=(const QWebElementCollection &other)
1554 Destroys the collection.
1556 QWebElementCollection::~QWebElementCollection()
1560 /*! \fn QWebElementCollection &QWebElementCollection::operator+=(const QWebElementCollection &other)
1562 Appends the items of the \a other list to this list and returns a
1563 reference to this list.
1565 \sa operator+(), append()
1569 Returns a collection that contains all the elements of this collection followed
1570 by all the elements in the \a other collection. Duplicates may occur in the result.
1574 QWebElementCollection QWebElementCollection::operator+(const QWebElementCollection &other) const
1576 QWebElementCollection n = *this; n.d.detach(); n += other; return n;
1580 Extends the collection by appending all items of \a other.
1582 The resulting collection may include duplicate elements.
1586 void QWebElementCollection::append(const QWebElementCollection &other)
1594 Vector<RefPtr<Node> > nodes;
1595 RefPtr<NodeList> results[] = { d->m_result, other.d->m_result };
1596 nodes.reserveInitialCapacity(results[0]->length() + results[1]->length());
1598 for (int i = 0; i < 2; ++i) {
1600 Node* n = results[i]->item(j);
1603 n = results[i]->item(++j);
1607 d->m_result = StaticNodeList::adopt(nodes);
1611 Returns the number of elements in the collection.
1613 int QWebElementCollection::count() const
1617 return d->m_result->length();
1621 Returns the element at index position \a i in the collection.
1623 QWebElement QWebElementCollection::at(int i) const
1626 return QWebElement();
1627 Node* n = d->m_result->item(i);
1628 return QWebElement(static_cast<Element*>(n));
1632 \fn const QWebElement QWebElementCollection::operator[](int position) const
1634 Returns the element at the specified \a position in the collection.
1637 /*! \fn QWebElement QWebElementCollection::first() const
1639 Returns the first element in the collection.
1641 \sa last(), operator[](), at(), count()
1644 /*! \fn QWebElement QWebElementCollection::last() const
1646 Returns the last element in the collection.
1648 \sa first(), operator[](), at(), count()
1652 Returns a QList object with the elements contained in this collection.
1654 QList<QWebElement> QWebElementCollection::toList() const
1657 return QList<QWebElement>();
1658 QList<QWebElement> elements;
1660 Node* n = d->m_result->item(i);
1662 if (n->isElementNode())
1663 elements.append(QWebElement(static_cast<Element*>(n)));
1664 n = d->m_result->item(++i);
1670 \fn QWebElementCollection::const_iterator QWebElementCollection::begin() const
1672 Returns an STL-style iterator pointing to the first element in the collection.
1678 \fn QWebElementCollection::const_iterator QWebElementCollection::end() const
1680 Returns an STL-style iterator pointing to the imaginary element after the
1681 last element in the list.
1687 \class QWebElementCollection::const_iterator
1689 \brief The QWebElementCollection::const_iterator class provides an STL-style const iterator for QWebElementCollection.
1691 QWebElementCollection provides STL style const iterators for fast low-level access to the elements.
1693 QWebElementCollection::const_iterator allows you to iterate over a QWebElementCollection.
1697 \fn QWebElementCollection::const_iterator::const_iterator(const const_iterator &other)
1699 Constructs a copy of \a other.
1703 \fn QWebElementCollection::const_iterator::const_iterator(const QWebElementCollection *collection, int index)
1708 \fn const QWebElement QWebElementCollection::const_iterator::operator*() const
1710 Returns the current element.
1714 \fn bool QWebElementCollection::const_iterator::operator==(const const_iterator &other) const
1716 Returns true if \a other points to the same item as this iterator;
1717 otherwise returns false.
1723 \fn bool QWebElementCollection::const_iterator::operator!=(const const_iterator &other) const
1725 Returns true if \a other points to a different element than this;
1726 iterator; otherwise returns false.
1732 \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator++()
1734 The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection
1735 and returns an iterator to the new current element.
1737 Calling this function on QWebElementCollection::end() leads to undefined results.
1743 \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator++(int)
1747 The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection
1748 and returns an iterator to the previously current element.
1750 Calling this function on QWebElementCollection::end() leads to undefined results.
1754 \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator--()
1756 The prefix -- operator (\c{--it}) makes the preceding element current and returns an
1757 iterator to the new current element.
1759 Calling this function on QWebElementCollection::begin() leads to undefined results.
1765 \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator--(int)
1769 The postfix -- operator (\c{it--}) makes the preceding element current and returns
1770 an iterator to the previously current element.
1774 \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator+=(int j)
1776 Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward.
1778 \sa operator-=(), operator+()
1782 \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator-=(int j)
1784 Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward.
1786 \sa operator+=(), operator-()
1790 \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator+(int j) const
1792 Returns an iterator to the element at \a j positions forward from this iterator. If \a j
1793 is negative, the iterator goes backward.
1795 \sa operator-(), operator+=()
1799 \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator-(int j) const
1801 Returns an iterator to the element at \a j positiosn backward from this iterator.
1802 If \a j is negative, the iterator goes forward.
1804 \sa operator+(), operator-=()
1808 \fn int QWebElementCollection::const_iterator::operator-(const_iterator other) const
1810 Returns the number of elements between the item point to by \a other
1811 and the element pointed to by this iterator.
1815 \fn bool QWebElementCollection::const_iterator::operator<(const const_iterator &other) const
1817 Returns true if the element pointed to by this iterator is less than the element pointed to
1818 by the \a other iterator.
1822 \fn bool QWebElementCollection::const_iterator::operator<=(const const_iterator &other) const
1824 Returns true if the element pointed to by this iterator is less than or equal to the
1825 element pointed to by the \a other iterator.
1829 \fn bool QWebElementCollection::const_iterator::operator>(const const_iterator &other) const
1831 Returns true if the element pointed to by this iterator is greater than the element pointed to
1832 by the \a other iterator.
1836 \fn bool QWebElementCollection::const_iterator::operator>=(const const_iterator &other) const
1838 Returns true if the element pointed to by this iterator is greater than or equal to the
1839 element pointed to by the \a other iterator.
1843 \fn QWebElementCollection::iterator QWebElementCollection::begin()
1845 Returns an STL-style iterator pointing to the first element in the collection.
1851 \fn QWebElementCollection::iterator QWebElementCollection::end()
1853 Returns an STL-style iterator pointing to the imaginary element after the
1854 last element in the list.
1860 \fn QWebElementCollection::const_iterator QWebElementCollection::constBegin() const
1862 Returns an STL-style iterator pointing to the first element in the collection.
1868 \fn QWebElementCollection::const_iterator QWebElementCollection::constEnd() const
1870 Returns an STL-style iterator pointing to the imaginary element after the
1871 last element in the list.
1877 \class QWebElementCollection::iterator
1879 \brief The QWebElementCollection::iterator class provides an STL-style iterator for QWebElementCollection.
1881 QWebElementCollection provides STL style iterators for fast low-level access to the elements.
1883 QWebElementCollection::iterator allows you to iterate over a QWebElementCollection.
1887 \fn QWebElementCollection::iterator::iterator(const iterator &other)
1889 Constructs a copy of \a other.
1893 \fn QWebElementCollection::iterator::iterator(const QWebElementCollection *collection, int index)
1898 \fn const QWebElement QWebElementCollection::iterator::operator*() const
1900 Returns the current element.
1904 \fn bool QWebElementCollection::iterator::operator==(const iterator &other) const
1906 Returns true if \a other points to the same item as this iterator;
1907 otherwise returns false.
1913 \fn bool QWebElementCollection::iterator::operator!=(const iterator &other) const
1915 Returns true if \a other points to a different element than this;
1916 iterator; otherwise returns false.
1922 \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator++()
1924 The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection
1925 and returns an iterator to the new current element.
1927 Calling this function on QWebElementCollection::end() leads to undefined results.
1933 \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator++(int)
1937 The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection
1938 and returns an iterator to the previously current element.
1940 Calling this function on QWebElementCollection::end() leads to undefined results.
1944 \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator--()
1946 The prefix -- operator (\c{--it}) makes the preceding element current and returns an
1947 iterator to the new current element.
1949 Calling this function on QWebElementCollection::begin() leads to undefined results.
1955 \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator--(int)
1959 The postfix -- operator (\c{it--}) makes the preceding element current and returns
1960 an iterator to the previously current element.
1964 \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator+=(int j)
1966 Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward.
1968 \sa operator-=(), operator+()
1972 \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator-=(int j)
1974 Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward.
1976 \sa operator+=(), operator-()
1980 \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator+(int j) const
1982 Returns an iterator to the element at \a j positions forward from this iterator. If \a j
1983 is negative, the iterator goes backward.
1985 \sa operator-(), operator+=()
1989 \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator-(int j) const
1991 Returns an iterator to the element at \a j positiosn backward from this iterator.
1992 If \a j is negative, the iterator goes forward.
1994 \sa operator+(), operator-=()
1998 \fn int QWebElementCollection::iterator::operator-(iterator other) const
2000 Returns the number of elements between the item point to by \a other
2001 and the element pointed to by this iterator.
2005 \fn bool QWebElementCollection::iterator::operator<(const iterator &other) const
2007 Returns true if the element pointed to by this iterator is less than the element pointed to
2008 by the \a other iterator.
2012 \fn bool QWebElementCollection::iterator::operator<=(const iterator &other) const
2014 Returns true if the element pointed to by this iterator is less than or equal to the
2015 element pointed to by the \a other iterator.
2019 \fn bool QWebElementCollection::iterator::operator>(const iterator &other) const
2021 Returns true if the element pointed to by this iterator is greater than the element pointed to
2022 by the \a other iterator.
2026 \fn bool QWebElementCollection::iterator::operator>=(const iterator &other) const
2028 Returns true if the element pointed to by this iterator is greater than or equal to the
2029 element pointed to by the \a other iterator.