Home | History | Annotate | Download | only in Api
      1 /*
      2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
      3 
      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.
      8 
      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.
     13 
     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.
     18 */
     19 
     20 #include "config.h"
     21 #include "qwebelement.h"
     22 
     23 #include "CSSComputedStyleDeclaration.h"
     24 #include "CSSMutableStyleDeclaration.h"
     25 #include "CSSParser.h"
     26 #include "CSSRule.h"
     27 #include "CSSRuleList.h"
     28 #include "CSSStyleRule.h"
     29 #include "CSSStyleSelector.h"
     30 #include "Document.h"
     31 #include "DocumentFragment.h"
     32 #include "FrameView.h"
     33 #include "GraphicsContext.h"
     34 #include "HTMLElement.h"
     35 #if USE(JSC)
     36 #include "JSGlobalObject.h"
     37 #include "JSHTMLElement.h"
     38 #include "JSObject.h"
     39 #include "PropertyNameArray.h"
     40 #include <parser/SourceCode.h>
     41 #include "qt_runtime.h"
     42 #elif USE(V8)
     43 #include "V8DOMWindow.h"
     44 #include "V8Binding.h"
     45 #include "NotImplemented.h"
     46 #endif
     47 #include "NodeList.h"
     48 #include "RenderImage.h"
     49 #include "StaticNodeList.h"
     50 #include "qwebframe.h"
     51 #include "qwebframe_p.h"
     52 #if USE(JSC)
     53 #include "runtime_root.h"
     54 #endif
     55 #include <wtf/Vector.h>
     56 #include <wtf/text/CString.h>
     57 
     58 #include <QPainter>
     59 
     60 #if USE(V8)
     61 using namespace V8::Bindings;
     62 #endif
     63 
     64 using namespace WebCore;
     65 
     66 class QWebElementPrivate {
     67 public:
     68 };
     69 
     70 /*!
     71     \class QWebElement
     72     \since 4.6
     73     \brief The QWebElement class provides convenient access to DOM elements in
     74     a QWebFrame.
     75     \inmodule QtWebKit
     76 
     77     A QWebElement object allows easy access to the document model, represented
     78     by a tree-like structure of DOM elements. The root of the tree is called
     79     the document element and can be accessed using
     80     QWebFrame::documentElement().
     81 
     82     Specific elements can be accessed using findAll() and findFirst(). These
     83     elements are identified using CSS selectors. The code snippet below
     84     demonstrates the use of findAll().
     85 
     86     \snippet webkitsnippets/webelement/main.cpp FindAll
     87 
     88     The first list contains all \c span elements in the document. The second
     89     list contains \c span elements that are children of \c p, classified with
     90     \c intro.
     91 
     92     Using findFirst() is more efficient than calling findAll(), and extracting
     93     the first element only in the list returned.
     94 
     95     Alternatively you can traverse the document manually using firstChild() and
     96     nextSibling():
     97 
     98     \snippet webkitsnippets/webelement/main.cpp Traversing with QWebElement
     99 
    100     Individual elements can be inspected or changed using methods such as attribute()
    101     or setAttribute(). For examle, to capture the user's input in a text field for later
    102     use (auto-completion), a browser could do something like this:
    103 
    104     \snippet webkitsnippets/webelement/main.cpp autocomplete1
    105 
    106     When the same page is later revisited, the browser can fill in the text field automatically
    107     by modifying the value attribute of the input element:
    108 
    109     \snippet webkitsnippets/webelement/main.cpp autocomplete2
    110 
    111     Another use case is to emulate a click event on an element. The following
    112     code snippet demonstrates how to call the JavaScript DOM method click() of
    113     a submit button:
    114 
    115     \snippet webkitsnippets/webelement/main.cpp Calling a DOM element method
    116 
    117     The underlying content of QWebElement is explicitly shared. Creating a copy
    118     of a QWebElement does not create a copy of the content. Instead, both
    119     instances point to the same element.
    120 
    121     The contents of child elements can be converted to plain text with
    122     toPlainText(); to XHTML using toInnerXml(). To include the element's tag in
    123     the output, use toOuterXml().
    124 
    125     It is possible to replace the contents of child elements using
    126     setPlainText() and setInnerXml(). To replace the element itself and its
    127     contents, use setOuterXml().
    128 
    129     \section1 Examples
    130 
    131     The \l{DOM Traversal Example} shows one way to traverse documents in a running
    132     example.
    133 
    134     The \l{Simple Selector Example} can be used to experiment with the searching
    135     features of this class and provides sample code you can start working with.
    136 */
    137 
    138 /*!
    139     Constructs a null web element.
    140 */
    141 QWebElement::QWebElement()
    142     : d(0)
    143     , m_element(0)
    144 {
    145 }
    146 
    147 /*!
    148     \internal
    149 */
    150 QWebElement::QWebElement(WebCore::Element* domElement)
    151     : d(0)
    152     , m_element(domElement)
    153 {
    154     if (m_element)
    155         m_element->ref();
    156 }
    157 
    158 /*!
    159     \internal
    160 */
    161 QWebElement::QWebElement(WebCore::Node* node)
    162     : d(0)
    163     , m_element(0)
    164 {
    165     if (node && node->isHTMLElement()) {
    166         m_element = static_cast<HTMLElement*>(node);
    167         m_element->ref();
    168     }
    169 }
    170 
    171 /*!
    172     Constructs a copy of \a other.
    173 */
    174 QWebElement::QWebElement(const QWebElement &other)
    175     : d(0)
    176     , m_element(other.m_element)
    177 {
    178     if (m_element)
    179         m_element->ref();
    180 }
    181 
    182 /*!
    183     Assigns \a other to this element and returns a reference to this element.
    184 */
    185 QWebElement &QWebElement::operator=(const QWebElement &other)
    186 {
    187     // ### handle "d" assignment
    188     if (this != &other) {
    189         Element *otherElement = other.m_element;
    190         if (otherElement)
    191             otherElement->ref();
    192         if (m_element)
    193             m_element->deref();
    194         m_element = otherElement;
    195     }
    196     return *this;
    197 }
    198 
    199 /*!
    200     Destroys the element. However, the underlying DOM element is not destroyed.
    201 */
    202 QWebElement::~QWebElement()
    203 {
    204     delete d;
    205     if (m_element)
    206         m_element->deref();
    207 }
    208 
    209 bool QWebElement::operator==(const QWebElement& o) const
    210 {
    211     return m_element == o.m_element;
    212 }
    213 
    214 bool QWebElement::operator!=(const QWebElement& o) const
    215 {
    216     return m_element != o.m_element;
    217 }
    218 
    219 /*!
    220     Returns true if the element is a null element; otherwise returns false.
    221 */
    222 bool QWebElement::isNull() const
    223 {
    224     return !m_element;
    225 }
    226 
    227 /*!
    228     Returns a new list of child elements matching the given CSS selector
    229     \a selectorQuery. If there are no matching elements, an empty list is
    230     returned.
    231 
    232     \l{Standard CSS2 selector} syntax is used for the query.
    233 
    234     \note This search is performed recursively.
    235 
    236     \sa findFirst()
    237 */
    238 QWebElementCollection QWebElement::findAll(const QString &selectorQuery) const
    239 {
    240     return QWebElementCollection(*this, selectorQuery);
    241 }
    242 
    243 /*!
    244     Returns the first child element that matches the given CSS selector
    245     \a selectorQuery.
    246 
    247     \l{Standard CSS2 selector} syntax is used for the query.
    248 
    249     \note This search is performed recursively.
    250 
    251     \sa findAll()
    252 */
    253 QWebElement QWebElement::findFirst(const QString &selectorQuery) const
    254 {
    255     if (!m_element)
    256         return QWebElement();
    257     ExceptionCode exception = 0; // ###
    258     return QWebElement(m_element->querySelector(selectorQuery, exception).get());
    259 }
    260 
    261 /*!
    262     Replaces the existing content of this element with \a text.
    263 
    264     This is equivalent to setting the HTML innerText property.
    265 
    266     \sa toPlainText()
    267 */
    268 void QWebElement::setPlainText(const QString &text)
    269 {
    270     if (!m_element || !m_element->isHTMLElement())
    271         return;
    272     ExceptionCode exception = 0;
    273     static_cast<HTMLElement*>(m_element)->setInnerText(text, exception);
    274 }
    275 
    276 /*!
    277     Returns the text between the start and the end tag of this
    278     element.
    279 
    280     This is equivalent to reading the HTML innerText property.
    281 
    282     \sa setPlainText()
    283 */
    284 QString QWebElement::toPlainText() const
    285 {
    286     if (!m_element || !m_element->isHTMLElement())
    287         return QString();
    288     return static_cast<HTMLElement*>(m_element)->innerText();
    289 }
    290 
    291 /*!
    292     Replaces the contents of this element as well as its own tag with
    293     \a markup. The string may contain HTML or XML tags, which is parsed and
    294     formatted before insertion into the document.
    295 
    296     \note This is currently only implemented for (X)HTML elements.
    297 
    298     \sa toOuterXml(), toInnerXml(), setInnerXml()
    299 */
    300 void QWebElement::setOuterXml(const QString &markup)
    301 {
    302     if (!m_element || !m_element->isHTMLElement())
    303         return;
    304 
    305     ExceptionCode exception = 0;
    306 
    307     static_cast<HTMLElement*>(m_element)->setOuterHTML(markup, exception);
    308 }
    309 
    310 /*!
    311     Returns this element converted to XML, including the start and the end
    312     tags as well as its attributes.
    313 
    314     \note This is currently implemented for (X)HTML elements only.
    315 
    316     \note The format of the markup returned will obey the namespace of the
    317     document containing the element. This means the return value will obey XML
    318     formatting rules, such as self-closing tags, only if the document is
    319     'text/xhtml+xml'.
    320 
    321     \sa setOuterXml(), setInnerXml(), toInnerXml()
    322 */
    323 QString QWebElement::toOuterXml() const
    324 {
    325     if (!m_element || !m_element->isHTMLElement())
    326         return QString();
    327 
    328     return static_cast<HTMLElement*>(m_element)->outerHTML();
    329 }
    330 
    331 /*!
    332     Replaces the contents of this element with \a markup. The string may
    333     contain HTML or XML tags, which is parsed and formatted before insertion
    334     into the document.
    335 
    336     \note This is currently implemented for (X)HTML elements only.
    337 
    338     \sa toInnerXml(), toOuterXml(), setOuterXml()
    339 */
    340 void QWebElement::setInnerXml(const QString &markup)
    341 {
    342     if (!m_element || !m_element->isHTMLElement())
    343         return;
    344 
    345     ExceptionCode exception = 0;
    346 
    347     static_cast<HTMLElement*>(m_element)->setInnerHTML(markup, exception);
    348 }
    349 
    350 /*!
    351     Returns the XML content between the element's start and end tags.
    352 
    353     \note This is currently implemented for (X)HTML elements only.
    354 
    355     \note The format of the markup returned will obey the namespace of the
    356     document containing the element. This means the return value will obey XML
    357     formatting rules, such as self-closing tags, only if the document is
    358     'text/xhtml+xml'.
    359 
    360     \sa setInnerXml(), setOuterXml(), toOuterXml()
    361 */
    362 QString QWebElement::toInnerXml() const
    363 {
    364     if (!m_element || !m_element->isHTMLElement())
    365         return QString();
    366 
    367     return static_cast<HTMLElement*>(m_element)->innerHTML();
    368 }
    369 
    370 /*!
    371     Adds an attribute with the given \a name and \a value. If an attribute with
    372     the same name exists, its value is replaced by \a value.
    373 
    374     \sa attribute(), attributeNS(), setAttributeNS()
    375 */
    376 void QWebElement::setAttribute(const QString &name, const QString &value)
    377 {
    378     if (!m_element)
    379         return;
    380     ExceptionCode exception = 0;
    381     m_element->setAttribute(name, value, exception);
    382 }
    383 
    384 /*!
    385     Adds an attribute with the given \a name in \a namespaceUri with \a value.
    386     If an attribute with the same name exists, its value is replaced by
    387     \a value.
    388 
    389     \sa attributeNS(), attribute(), setAttribute()
    390 */
    391 void QWebElement::setAttributeNS(const QString &namespaceUri, const QString &name, const QString &value)
    392 {
    393     if (!m_element)
    394         return;
    395     WebCore::ExceptionCode exception = 0;
    396     m_element->setAttributeNS(namespaceUri, name, value, exception);
    397 }
    398 
    399 /*!
    400     Returns the attribute with the given \a name. If the attribute does not
    401     exist, \a defaultValue is returned.
    402 
    403     \sa setAttribute(), setAttributeNS(), attributeNS()
    404 */
    405 QString QWebElement::attribute(const QString &name, const QString &defaultValue) const
    406 {
    407     if (!m_element)
    408         return QString();
    409     if (m_element->hasAttribute(name))
    410         return m_element->getAttribute(name);
    411     else
    412         return defaultValue;
    413 }
    414 
    415 /*!
    416     Returns the attribute with the given \a name in \a namespaceUri. If the
    417     attribute does not exist, \a defaultValue is returned.
    418 
    419     \sa setAttributeNS(), setAttribute(), attribute()
    420 */
    421 QString QWebElement::attributeNS(const QString &namespaceUri, const QString &name, const QString &defaultValue) const
    422 {
    423     if (!m_element)
    424         return QString();
    425     if (m_element->hasAttributeNS(namespaceUri, name))
    426         return m_element->getAttributeNS(namespaceUri, name);
    427     else
    428         return defaultValue;
    429 }
    430 
    431 /*!
    432     Returns true if this element has an attribute with the given \a name;
    433     otherwise returns false.
    434 
    435     \sa attribute(), setAttribute()
    436 */
    437 bool QWebElement::hasAttribute(const QString &name) const
    438 {
    439     if (!m_element)
    440         return false;
    441     return m_element->hasAttribute(name);
    442 }
    443 
    444 /*!
    445     Returns true if this element has an attribute with the given \a name, in
    446     \a namespaceUri; otherwise returns false.
    447 
    448     \sa attributeNS(), setAttributeNS()
    449 */
    450 bool QWebElement::hasAttributeNS(const QString &namespaceUri, const QString &name) const
    451 {
    452     if (!m_element)
    453         return false;
    454     return m_element->hasAttributeNS(namespaceUri, name);
    455 }
    456 
    457 /*!
    458     Removes the attribute with the given \a name from this element.
    459 
    460     \sa attribute(), setAttribute(), hasAttribute()
    461 */
    462 void QWebElement::removeAttribute(const QString &name)
    463 {
    464     if (!m_element)
    465         return;
    466     ExceptionCode exception = 0;
    467     m_element->removeAttribute(name, exception);
    468 }
    469 
    470 /*!
    471     Removes the attribute with the given \a name, in \a namespaceUri, from this
    472     element.
    473 
    474     \sa attributeNS(), setAttributeNS(), hasAttributeNS()
    475 */
    476 void QWebElement::removeAttributeNS(const QString &namespaceUri, const QString &name)
    477 {
    478     if (!m_element)
    479         return;
    480     WebCore::ExceptionCode exception = 0;
    481     m_element->removeAttributeNS(namespaceUri, name, exception);
    482 }
    483 
    484 /*!
    485     Returns true if the element has any attributes defined; otherwise returns
    486     false;
    487 
    488     \sa attribute(), setAttribute()
    489 */
    490 bool QWebElement::hasAttributes() const
    491 {
    492     if (!m_element)
    493         return false;
    494     return m_element->hasAttributes();
    495 }
    496 
    497 /*!
    498     Return the list of attributes for the namespace given as \a namespaceUri.
    499 
    500     \sa attribute(), setAttribute()
    501 */
    502 QStringList QWebElement::attributeNames(const QString& namespaceUri) const
    503 {
    504     if (!m_element)
    505         return QStringList();
    506 
    507     QStringList attributeNameList;
    508     const NamedNodeMap* const attrs = m_element->attributes(/* read only = */ true);
    509     if (attrs) {
    510         const String namespaceUriString(namespaceUri); // convert QString -> String once
    511         const unsigned attrsCount = attrs->length();
    512         for (unsigned i = 0; i < attrsCount; ++i) {
    513             const Attribute* const attribute = attrs->attributeItem(i);
    514             if (namespaceUriString == attribute->namespaceURI())
    515                 attributeNameList.append(attribute->localName());
    516         }
    517     }
    518     return attributeNameList;
    519 }
    520 
    521 /*!
    522     Returns true if the element has keyboard input focus; otherwise, returns false
    523 
    524     \sa setFocus()
    525 */
    526 bool QWebElement::hasFocus() const
    527 {
    528     if (!m_element)
    529         return false;
    530     if (m_element->document())
    531         return m_element == m_element->document()->focusedNode();
    532     return false;
    533 }
    534 
    535 /*!
    536     Gives keyboard input focus to this element
    537 
    538     \sa hasFocus()
    539 */
    540 void QWebElement::setFocus()
    541 {
    542     if (!m_element)
    543         return;
    544     if (m_element->document() && m_element->isFocusable())
    545         m_element->document()->setFocusedNode(m_element);
    546 }
    547 
    548 /*!
    549     Returns the geometry of this element, relative to its containing frame.
    550 
    551     \sa tagName()
    552 */
    553 QRect QWebElement::geometry() const
    554 {
    555     if (!m_element)
    556         return QRect();
    557     return m_element->getRect();
    558 }
    559 
    560 /*!
    561     Returns the tag name of this element.
    562 
    563     \sa geometry()
    564 */
    565 QString QWebElement::tagName() const
    566 {
    567     if (!m_element)
    568         return QString();
    569     return m_element->tagName();
    570 }
    571 
    572 /*!
    573     Returns the namespace prefix of the element. If the element has no\
    574     namespace prefix, empty string is returned.
    575 */
    576 QString QWebElement::prefix() const
    577 {
    578     if (!m_element)
    579         return QString();
    580     return m_element->prefix();
    581 }
    582 
    583 /*!
    584     Returns the local name of the element. If the element does not use
    585     namespaces, an empty string is returned.
    586 */
    587 QString QWebElement::localName() const
    588 {
    589     if (!m_element)
    590         return QString();
    591     return m_element->localName();
    592 }
    593 
    594 /*!
    595     Returns the namespace URI of this element. If the element has no namespace
    596     URI, an empty string is returned.
    597 */
    598 QString QWebElement::namespaceUri() const
    599 {
    600     if (!m_element)
    601         return QString();
    602     return m_element->namespaceURI();
    603 }
    604 
    605 /*!
    606     Returns the parent element of this elemen. If this element is the root
    607     document element, a null element is returned.
    608 */
    609 QWebElement QWebElement::parent() const
    610 {
    611     if (m_element)
    612         return QWebElement(m_element->parentElement());
    613     return QWebElement();
    614 }
    615 
    616 /*!
    617     Returns the element's first child.
    618 
    619     \sa lastChild(), previousSibling(), nextSibling()
    620 */
    621 QWebElement QWebElement::firstChild() const
    622 {
    623     if (!m_element)
    624         return QWebElement();
    625     for (Node* child = m_element->firstChild(); child; child = child->nextSibling()) {
    626         if (!child->isElementNode())
    627             continue;
    628         Element* e = static_cast<Element*>(child);
    629         return QWebElement(e);
    630     }
    631     return QWebElement();
    632 }
    633 
    634 /*!
    635     Returns the element's last child.
    636 
    637     \sa firstChild(), previousSibling(), nextSibling()
    638 */
    639 QWebElement QWebElement::lastChild() const
    640 {
    641     if (!m_element)
    642         return QWebElement();
    643     for (Node* child = m_element->lastChild(); child; child = child->previousSibling()) {
    644         if (!child->isElementNode())
    645             continue;
    646         Element* e = static_cast<Element*>(child);
    647         return QWebElement(e);
    648     }
    649     return QWebElement();
    650 }
    651 
    652 /*!
    653     Returns the element's next sibling.
    654 
    655     \sa firstChild(), previousSibling(), lastChild()
    656 */
    657 QWebElement QWebElement::nextSibling() const
    658 {
    659     if (!m_element)
    660         return QWebElement();
    661     for (Node* sib = m_element->nextSibling(); sib; sib = sib->nextSibling()) {
    662         if (!sib->isElementNode())
    663             continue;
    664         Element* e = static_cast<Element*>(sib);
    665         return QWebElement(e);
    666     }
    667     return QWebElement();
    668 }
    669 
    670 /*!
    671     Returns the element's previous sibling.
    672 
    673     \sa firstChild(), nextSibling(), lastChild()
    674 */
    675 QWebElement QWebElement::previousSibling() const
    676 {
    677     if (!m_element)
    678         return QWebElement();
    679     for (Node* sib = m_element->previousSibling(); sib; sib = sib->previousSibling()) {
    680         if (!sib->isElementNode())
    681             continue;
    682         Element* e = static_cast<Element*>(sib);
    683         return QWebElement(e);
    684     }
    685     return QWebElement();
    686 }
    687 
    688 /*!
    689     Returns the document which this element belongs to.
    690 */
    691 QWebElement QWebElement::document() const
    692 {
    693     if (!m_element)
    694         return QWebElement();
    695     Document* document = m_element->document();
    696     if (!document)
    697         return QWebElement();
    698     return QWebElement(document->documentElement());
    699 }
    700 
    701 /*!
    702     Returns the web frame which this element is a part of. If the element is a
    703     null element, null is returned.
    704 */
    705 QWebFrame *QWebElement::webFrame() const
    706 {
    707     if (!m_element)
    708         return 0;
    709 
    710     Document* document = m_element->document();
    711     if (!document)
    712         return 0;
    713 
    714     Frame* frame = document->frame();
    715     if (!frame)
    716         return 0;
    717     return QWebFramePrivate::kit(frame);
    718 }
    719 
    720 #if USE(JSC)
    721 static bool setupScriptContext(WebCore::Element* element, JSC::JSValue& thisValue, ScriptState*& state, ScriptController*& scriptController)
    722 {
    723     if (!element)
    724         return false;
    725 
    726     Document* document = element->document();
    727     if (!document)
    728         return false;
    729 
    730     Frame* frame = document->frame();
    731     if (!frame)
    732         return false;
    733 
    734     scriptController = frame->script();
    735     if (!scriptController)
    736         return false;
    737 
    738     state = scriptController->globalObject(mainThreadNormalWorld())->globalExec();
    739     if (!state)
    740         return false;
    741 
    742     thisValue = toJS(state, element);
    743     if (!thisValue)
    744         return false;
    745 
    746     return true;
    747 }
    748 #elif USE(V8)
    749 static bool setupScriptContext(WebCore::Element* element, v8::Handle<v8::Value>& thisValue, ScriptState*& state, ScriptController*& scriptController)
    750 {
    751     if (!element)
    752         return false;
    753 
    754     Document* document = element->document();
    755     if (!document)
    756         return false;
    757 
    758     Frame* frame = document->frame();
    759     if (!frame)
    760         return false;
    761 
    762     state = mainWorldScriptState(frame);
    763     // Get V8 wrapper for DOM element
    764     thisValue = toV8(frame->domWindow());
    765     return true;
    766 }
    767 #endif
    768 
    769 
    770 /*!
    771     Executes \a scriptSource with this element as \c this object.
    772 */
    773 QVariant QWebElement::evaluateJavaScript(const QString& scriptSource)
    774 {
    775     if (scriptSource.isEmpty())
    776         return QVariant();
    777 
    778     ScriptState* state = 0;
    779 #if USE(JSC)
    780     JSC::JSValue thisValue;
    781 #elif USE(V8)
    782     v8::Handle<v8::Value> thisValue;
    783 #endif
    784     ScriptController* scriptController = 0;
    785 
    786     if (!setupScriptContext(m_element, thisValue, state, scriptController))
    787         return QVariant();
    788 #if USE(JSC)
    789     JSC::ScopeChainNode* scopeChain = state->dynamicGlobalObject()->globalScopeChain();
    790     JSC::UString script(reinterpret_cast_ptr<const UChar*>(scriptSource.data()), scriptSource.length());
    791     JSC::Completion completion = JSC::evaluate(state, scopeChain, JSC::makeSource(script), thisValue);
    792     if ((completion.complType() != JSC::ReturnValue) && (completion.complType() != JSC::Normal))
    793         return QVariant();
    794 
    795     JSC::JSValue result = completion.value();
    796     if (!result)
    797         return QVariant();
    798 
    799     int distance = 0;
    800     return JSC::Bindings::convertValueToQVariant(state, result, QMetaType::Void, &distance);
    801 #elif USE(V8)
    802     notImplemented();
    803     return QVariant();
    804 #endif
    805 }
    806 
    807 /*!
    808     \enum QWebElement::StyleResolveStrategy
    809 
    810     This enum describes how QWebElement's styleProperty resolves the given
    811     property name.
    812 
    813     \value InlineStyle Return the property value as it is defined in
    814            the element, without respecting style inheritance and other CSS
    815            rules.
    816     \value CascadedStyle The property's value is determined using the
    817            inheritance and importance rules defined in the document's
    818            stylesheet.
    819     \value ComputedStyle The property's value is the absolute value
    820            of the style property resolved from the environment.
    821 */
    822 
    823 /*!
    824     Returns the value of the style with the given \a name using the specified
    825     \a strategy. If a style with \a name does not exist, an empty string is
    826     returned.
    827 
    828     In CSS, the cascading part depends on which CSS rule has priority and is
    829     thus applied. Generally, the last defined rule has priority. Thus, an
    830     inline style rule has priority over an embedded block style rule, which
    831     in return has priority over an external style rule.
    832 
    833     If the "!important" declaration is set on one of those, the declaration
    834     receives highest priority, unless other declarations also use the
    835     "!important" declaration. Then, the last "!important" declaration takes
    836     predecence.
    837 
    838     \sa setStyleProperty()
    839 */
    840 
    841 QString QWebElement::styleProperty(const QString &name, StyleResolveStrategy strategy) const
    842 {
    843     if (!m_element || !m_element->isStyledElement())
    844         return QString();
    845 
    846     int propID = cssPropertyID(name);
    847 
    848     if (!propID)
    849         return QString();
    850 
    851     CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style();
    852 
    853     if (strategy == InlineStyle)
    854         return style->getPropertyValue(propID);
    855 
    856     if (strategy == CascadedStyle) {
    857         if (style->getPropertyPriority(propID))
    858             return style->getPropertyValue(propID);
    859 
    860         // We are going to resolve the style property by walking through the
    861         // list of non-inline matched CSS rules for the element, looking for
    862         // the highest priority definition.
    863 
    864         // Get an array of matched CSS rules for the given element sorted
    865         // by importance and inheritance order. This include external CSS
    866         // declarations, as well as embedded and inline style declarations.
    867 
    868         Document* doc = m_element->document();
    869         if (RefPtr<CSSRuleList> rules = doc->styleSelector()->styleRulesForElement(m_element, /*authorOnly*/ true)) {
    870             for (int i = rules->length(); i > 0; --i) {
    871                 CSSStyleRule* rule = static_cast<CSSStyleRule*>(rules->item(i - 1));
    872 
    873                 if (rule->style()->getPropertyPriority(propID))
    874                     return rule->style()->getPropertyValue(propID);
    875 
    876                 if (style->getPropertyValue(propID).isEmpty())
    877                     style = rule->style();
    878             }
    879         }
    880 
    881         return style->getPropertyValue(propID);
    882     }
    883 
    884     if (strategy == ComputedStyle) {
    885         if (!m_element || !m_element->isStyledElement())
    886             return QString();
    887 
    888         int propID = cssPropertyID(name);
    889 
    890         RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element, true);
    891         if (!propID || !style)
    892             return QString();
    893 
    894         return style->getPropertyValue(propID);
    895     }
    896 
    897     return QString();
    898 }
    899 
    900 /*!
    901     Sets the value of the inline style with the given \a name to \a value.
    902 
    903     Setting a value, does not necessarily mean that it will become the applied
    904     value, due to the fact that the style property's value might have been set
    905     earlier with a higher priority in external or embedded style declarations.
    906 
    907     In order to ensure that the value will be applied, you may have to append
    908     "!important" to the value.
    909 */
    910 void QWebElement::setStyleProperty(const QString &name, const QString &value)
    911 {
    912     if (!m_element || !m_element->isStyledElement())
    913         return;
    914 
    915     int propID = cssPropertyID(name);
    916     CSSStyleDeclaration* style = static_cast<StyledElement*>(m_element)->style();
    917     if (!propID || !style)
    918         return;
    919 
    920     ExceptionCode exception = 0;
    921     style->setProperty(name, value, exception);
    922 }
    923 
    924 /*!
    925     Returns the list of classes of this element.
    926 */
    927 QStringList QWebElement::classes() const
    928 {
    929     if (!hasAttribute(QLatin1String("class")))
    930         return QStringList();
    931 
    932     QStringList classes =  attribute(QLatin1String("class")).simplified().split(QLatin1Char(' '), QString::SkipEmptyParts);
    933     classes.removeDuplicates();
    934     return classes;
    935 }
    936 
    937 /*!
    938     Returns true if this element has a class with the given \a name; otherwise
    939     returns false.
    940 */
    941 bool QWebElement::hasClass(const QString &name) const
    942 {
    943     QStringList list = classes();
    944     return list.contains(name);
    945 }
    946 
    947 /*!
    948     Adds the specified class with the given \a name to the element.
    949 */
    950 void QWebElement::addClass(const QString &name)
    951 {
    952     QStringList list = classes();
    953     if (!list.contains(name)) {
    954         list.append(name);
    955         QString value = list.join(QLatin1String(" "));
    956         setAttribute(QLatin1String("class"), value);
    957     }
    958 }
    959 
    960 /*!
    961     Removes the specified class with the given \a name from the element.
    962 */
    963 void QWebElement::removeClass(const QString &name)
    964 {
    965     QStringList list = classes();
    966     if (list.contains(name)) {
    967         list.removeAll(name);
    968         QString value = list.join(QLatin1String(" "));
    969         setAttribute(QLatin1String("class"), value);
    970     }
    971 }
    972 
    973 /*!
    974     Adds the specified class with the given \a name if it is not present. If
    975     the class is already present, it will be removed.
    976 */
    977 void QWebElement::toggleClass(const QString &name)
    978 {
    979     QStringList list = classes();
    980     if (list.contains(name))
    981         list.removeAll(name);
    982     else
    983         list.append(name);
    984 
    985     QString value = list.join(QLatin1String(" "));
    986     setAttribute(QLatin1String("class"), value);
    987 }
    988 
    989 /*!
    990     Appends the given \a element as the element's last child.
    991 
    992     If \a element is the child of another element, it is re-parented to this
    993     element. If \a element is a child of this element, then its position in
    994     the list of children is changed.
    995 
    996     Calling this function on a null element does nothing.
    997 
    998     \sa prependInside(), prependOutside(), appendOutside()
    999 */
   1000 void QWebElement::appendInside(const QWebElement &element)
   1001 {
   1002     if (!m_element || element.isNull())
   1003         return;
   1004 
   1005     ExceptionCode exception = 0;
   1006     m_element->appendChild(element.m_element, exception);
   1007 }
   1008 
   1009 /*!
   1010     Appends the result of parsing \a markup as the element's last child.
   1011 
   1012     Calling this function on a null element does nothing.
   1013 
   1014     \sa prependInside(), prependOutside(), appendOutside()
   1015 */
   1016 void QWebElement::appendInside(const QString &markup)
   1017 {
   1018     if (!m_element)
   1019         return;
   1020 
   1021     if (!m_element->isHTMLElement())
   1022         return;
   1023 
   1024     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
   1025     RefPtr<DocumentFragment> fragment = htmlElement->Element::deprecatedCreateContextualFragment(markup);
   1026 
   1027     ExceptionCode exception = 0;
   1028     m_element->appendChild(fragment, exception);
   1029 }
   1030 
   1031 /*!
   1032     Prepends \a element as the element's first child.
   1033 
   1034     If \a element is the child of another element, it is re-parented to this
   1035     element. If \a element is a child of this element, then its position in
   1036     the list of children is changed.
   1037 
   1038     Calling this function on a null element does nothing.
   1039 
   1040     \sa appendInside(), prependOutside(), appendOutside()
   1041 */
   1042 void QWebElement::prependInside(const QWebElement &element)
   1043 {
   1044     if (!m_element || element.isNull())
   1045         return;
   1046 
   1047     ExceptionCode exception = 0;
   1048 
   1049     if (m_element->hasChildNodes())
   1050         m_element->insertBefore(element.m_element, m_element->firstChild(), exception);
   1051     else
   1052         m_element->appendChild(element.m_element, exception);
   1053 }
   1054 
   1055 /*!
   1056     Prepends the result of parsing \a markup as the element's first child.
   1057 
   1058     Calling this function on a null element does nothing.
   1059 
   1060     \sa appendInside(), prependOutside(), appendOutside()
   1061 */
   1062 void QWebElement::prependInside(const QString &markup)
   1063 {
   1064     if (!m_element)
   1065         return;
   1066 
   1067     if (!m_element->isHTMLElement())
   1068         return;
   1069 
   1070     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
   1071     RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup);
   1072 
   1073     ExceptionCode exception = 0;
   1074 
   1075     if (m_element->hasChildNodes())
   1076         m_element->insertBefore(fragment, m_element->firstChild(), exception);
   1077     else
   1078         m_element->appendChild(fragment, exception);
   1079 }
   1080 
   1081 
   1082 /*!
   1083     Inserts the given \a element before this element.
   1084 
   1085     If \a element is the child of another element, it is re-parented to the
   1086     parent of this element.
   1087 
   1088     Calling this function on a null element does nothing.
   1089 
   1090     \sa appendInside(), prependInside(), appendOutside()
   1091 */
   1092 void QWebElement::prependOutside(const QWebElement &element)
   1093 {
   1094     if (!m_element || element.isNull())
   1095         return;
   1096 
   1097     if (!m_element->parentNode())
   1098         return;
   1099 
   1100     ExceptionCode exception = 0;
   1101     m_element->parentNode()->insertBefore(element.m_element, m_element, exception);
   1102 }
   1103 
   1104 /*!
   1105     Inserts the result of parsing \a markup before this element.
   1106 
   1107     Calling this function on a null element does nothing.
   1108 
   1109     \sa appendInside(), prependInside(), appendOutside()
   1110 */
   1111 void QWebElement::prependOutside(const QString &markup)
   1112 {
   1113     if (!m_element)
   1114         return;
   1115 
   1116     if (!m_element->parentNode())
   1117         return;
   1118 
   1119     if (!m_element->isHTMLElement())
   1120         return;
   1121 
   1122     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
   1123     RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup);
   1124 
   1125     ExceptionCode exception = 0;
   1126     m_element->parentNode()->insertBefore(fragment, m_element, exception);
   1127 }
   1128 
   1129 /*!
   1130     Inserts the given \a element after this element.
   1131 
   1132     If \a element is the child of another element, it is re-parented to the
   1133     parent of this element.
   1134 
   1135     Calling this function on a null element does nothing.
   1136 
   1137     \sa appendInside(), prependInside(), prependOutside()
   1138 */
   1139 void QWebElement::appendOutside(const QWebElement &element)
   1140 {
   1141     if (!m_element || element.isNull())
   1142         return;
   1143 
   1144     if (!m_element->parentNode())
   1145         return;
   1146 
   1147     ExceptionCode exception = 0;
   1148     if (!m_element->nextSibling())
   1149         m_element->parentNode()->appendChild(element.m_element, exception);
   1150     else
   1151         m_element->parentNode()->insertBefore(element.m_element, m_element->nextSibling(), exception);
   1152 }
   1153 
   1154 /*!
   1155     Inserts the result of parsing \a markup after this element.
   1156 
   1157     Calling this function on a null element does nothing.
   1158 
   1159     \sa appendInside(), prependInside(), prependOutside()
   1160 */
   1161 void QWebElement::appendOutside(const QString &markup)
   1162 {
   1163     if (!m_element)
   1164         return;
   1165 
   1166     if (!m_element->parentNode())
   1167         return;
   1168 
   1169     if (!m_element->isHTMLElement())
   1170         return;
   1171 
   1172     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
   1173     RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup);
   1174 
   1175     ExceptionCode exception = 0;
   1176     if (!m_element->nextSibling())
   1177         m_element->parentNode()->appendChild(fragment, exception);
   1178     else
   1179         m_element->parentNode()->insertBefore(fragment, m_element->nextSibling(), exception);
   1180 }
   1181 
   1182 /*!
   1183     Returns a clone of this element.
   1184 
   1185     The clone may be inserted at any point in the document.
   1186 
   1187     \sa appendInside(), prependInside(), prependOutside(), appendOutside()
   1188 */
   1189 QWebElement QWebElement::clone() const
   1190 {
   1191     if (!m_element)
   1192         return QWebElement();
   1193 
   1194     return QWebElement(m_element->cloneElementWithChildren().get());
   1195 }
   1196 
   1197 /*!
   1198     Removes this element from the document and returns a reference to it.
   1199 
   1200     The element is still valid after removal, and can be inserted into other
   1201     parts of the document.
   1202 
   1203     \sa removeAllChildren(), removeFromDocument()
   1204 */
   1205 QWebElement &QWebElement::takeFromDocument()
   1206 {
   1207     if (!m_element)
   1208         return *this;
   1209 
   1210     ExceptionCode exception = 0;
   1211     m_element->remove(exception);
   1212 
   1213     return *this;
   1214 }
   1215 
   1216 /*!
   1217     Removes this element from the document and makes it a null element.
   1218 
   1219     \sa removeAllChildren(), takeFromDocument()
   1220 */
   1221 void QWebElement::removeFromDocument()
   1222 {
   1223     if (!m_element)
   1224         return;
   1225 
   1226     ExceptionCode exception = 0;
   1227     m_element->remove(exception);
   1228     m_element->deref();
   1229     m_element = 0;
   1230 }
   1231 
   1232 /*!
   1233     Removes all children from this element.
   1234 
   1235     \sa removeFromDocument(), takeFromDocument()
   1236 */
   1237 void QWebElement::removeAllChildren()
   1238 {
   1239     if (!m_element)
   1240         return;
   1241 
   1242     m_element->removeAllChildren();
   1243 }
   1244 
   1245 // FIXME: This code, and all callers are wrong, and have no place in a
   1246 // WebKit implementation.  These should be replaced with WebCore implementations.
   1247 static RefPtr<Node> findInsertionPoint(PassRefPtr<Node> root)
   1248 {
   1249     RefPtr<Node> node = root;
   1250 
   1251     // Go as far down the tree as possible.
   1252     while (node->hasChildNodes() && node->firstChild()->isElementNode())
   1253         node = node->firstChild();
   1254 
   1255     // TODO: Implement SVG support
   1256     if (node->isHTMLElement()) {
   1257         HTMLElement* element = static_cast<HTMLElement*>(node.get());
   1258 
   1259         // The insert point could be a non-enclosable tag and it can thus
   1260         // never have children, so go one up. Get the parent element, and not
   1261         // note as a root note will always exist.
   1262         if (element->ieForbidsInsertHTML())
   1263             node = node->parentElement();
   1264     }
   1265 
   1266     return node;
   1267 }
   1268 
   1269 /*!
   1270     Encloses the contents of this element with \a element. This element becomes
   1271     the child of the deepest descendant within \a element.
   1272 
   1273     ### illustration
   1274 
   1275     \sa encloseWith()
   1276 */
   1277 void QWebElement::encloseContentsWith(const QWebElement &element)
   1278 {
   1279     if (!m_element || element.isNull())
   1280         return;
   1281 
   1282     RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element);
   1283 
   1284     if (!insertionPoint)
   1285         return;
   1286 
   1287     ExceptionCode exception = 0;
   1288 
   1289     // reparent children
   1290     for (RefPtr<Node> child = m_element->firstChild(); child;) {
   1291         RefPtr<Node> next = child->nextSibling();
   1292         insertionPoint->appendChild(child, exception);
   1293         child = next;
   1294     }
   1295 
   1296     if (m_element->hasChildNodes())
   1297         m_element->insertBefore(element.m_element, m_element->firstChild(), exception);
   1298     else
   1299         m_element->appendChild(element.m_element, exception);
   1300 }
   1301 
   1302 /*!
   1303     Encloses the contents of this element with the result of parsing \a markup.
   1304     This element becomes the child of the deepest descendant within \a markup.
   1305 
   1306     \sa encloseWith()
   1307 */
   1308 void QWebElement::encloseContentsWith(const QString &markup)
   1309 {
   1310     if (!m_element)
   1311         return;
   1312 
   1313     if (!m_element->parentNode())
   1314         return;
   1315 
   1316     if (!m_element->isHTMLElement())
   1317         return;
   1318 
   1319     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
   1320     RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup);
   1321 
   1322     if (!fragment || !fragment->firstChild())
   1323         return;
   1324 
   1325     RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild());
   1326 
   1327     if (!insertionPoint)
   1328         return;
   1329 
   1330     ExceptionCode exception = 0;
   1331 
   1332     // reparent children
   1333     for (RefPtr<Node> child = m_element->firstChild(); child;) {
   1334         RefPtr<Node> next = child->nextSibling();
   1335         insertionPoint->appendChild(child, exception);
   1336         child = next;
   1337     }
   1338 
   1339     if (m_element->hasChildNodes())
   1340         m_element->insertBefore(fragment, m_element->firstChild(), exception);
   1341     else
   1342         m_element->appendChild(fragment, exception);
   1343 }
   1344 
   1345 /*!
   1346     Encloses this element with \a element. This element becomes the child of
   1347     the deepest descendant within \a element.
   1348 
   1349     \sa replace()
   1350 */
   1351 void QWebElement::encloseWith(const QWebElement &element)
   1352 {
   1353     if (!m_element || element.isNull())
   1354         return;
   1355 
   1356     RefPtr<Node> insertionPoint = findInsertionPoint(element.m_element);
   1357 
   1358     if (!insertionPoint)
   1359         return;
   1360 
   1361     // Keep reference to these two nodes before pulling out this element and
   1362     // wrapping it in the fragment. The reason for doing it in this order is
   1363     // that once the fragment has been added to the document it is empty, so
   1364     // we no longer have access to the nodes it contained.
   1365     Node* parent = m_element->parentNode();
   1366     Node* siblingNode = m_element->nextSibling();
   1367 
   1368     ExceptionCode exception = 0;
   1369     insertionPoint->appendChild(m_element, exception);
   1370 
   1371     if (!siblingNode)
   1372         parent->appendChild(element.m_element, exception);
   1373     else
   1374         parent->insertBefore(element.m_element, siblingNode, exception);
   1375 }
   1376 
   1377 /*!
   1378     Encloses this element with the result of parsing \a markup. This element
   1379     becomes the child of the deepest descendant within \a markup.
   1380 
   1381     \sa replace()
   1382 */
   1383 void QWebElement::encloseWith(const QString &markup)
   1384 {
   1385     if (!m_element)
   1386         return;
   1387 
   1388     if (!m_element->parentNode())
   1389         return;
   1390 
   1391     if (!m_element->isHTMLElement())
   1392         return;
   1393 
   1394     HTMLElement* htmlElement = static_cast<HTMLElement*>(m_element);
   1395     RefPtr<DocumentFragment> fragment = htmlElement->deprecatedCreateContextualFragment(markup);
   1396 
   1397     if (!fragment || !fragment->firstChild())
   1398         return;
   1399 
   1400     RefPtr<Node> insertionPoint = findInsertionPoint(fragment->firstChild());
   1401 
   1402     if (!insertionPoint)
   1403         return;
   1404 
   1405     // Keep reference to these two nodes before pulling out this element and
   1406     // wrapping it in the fragment. The reason for doing it in this order is
   1407     // that once the fragment has been added to the document it is empty, so
   1408     // we no longer have access to the nodes it contained.
   1409     Node* parent = m_element->parentNode();
   1410     Node* siblingNode = m_element->nextSibling();
   1411 
   1412     ExceptionCode exception = 0;
   1413     insertionPoint->appendChild(m_element, exception);
   1414 
   1415     if (!siblingNode)
   1416         parent->appendChild(fragment, exception);
   1417     else
   1418         parent->insertBefore(fragment, siblingNode, exception);
   1419 }
   1420 
   1421 /*!
   1422     Replaces this element with \a element.
   1423 
   1424     This method will not replace the <html>, <head> or <body> elements.
   1425 
   1426     \sa encloseWith()
   1427 */
   1428 void QWebElement::replace(const QWebElement &element)
   1429 {
   1430     if (!m_element || element.isNull())
   1431         return;
   1432 
   1433     appendOutside(element);
   1434     takeFromDocument();
   1435 }
   1436 
   1437 /*!
   1438     Replaces this element with the result of parsing \a markup.
   1439 
   1440     This method will not replace the <html>, <head> or <body> elements.
   1441 
   1442     \sa encloseWith()
   1443 */
   1444 void QWebElement::replace(const QString &markup)
   1445 {
   1446     if (!m_element)
   1447         return;
   1448 
   1449     appendOutside(markup);
   1450     takeFromDocument();
   1451 }
   1452 
   1453 /*!
   1454     \internal
   1455     Walk \a node's parents until a valid QWebElement is found.
   1456     For example, a WebCore::Text node is not a valid Html QWebElement, but its
   1457     enclosing p tag is.
   1458 */
   1459 QWebElement QWebElement::enclosingElement(WebCore::Node* node)
   1460 {
   1461     QWebElement element(node);
   1462 
   1463     while (element.isNull() && node) {
   1464         node = node->parentNode();
   1465         element = QWebElement(node);
   1466     }
   1467     return element;
   1468 }
   1469 
   1470 /*!
   1471     \fn inline bool QWebElement::operator==(const QWebElement& o) const;
   1472 
   1473     Returns true if this element points to the same underlying DOM object as
   1474     \a o; otherwise returns false.
   1475 */
   1476 
   1477 /*!
   1478     \fn inline bool QWebElement::operator!=(const QWebElement& o) const;
   1479 
   1480     Returns true if this element points to a different underlying DOM object
   1481     than \a o; otherwise returns false.
   1482 */
   1483 
   1484 
   1485 /*!
   1486   Render the element into \a painter .
   1487 */
   1488 void QWebElement::render(QPainter* painter)
   1489 {
   1490     render(painter, QRect());
   1491 }
   1492 
   1493 /*!
   1494   Render the element into \a painter clipping to \a clip.
   1495 */
   1496 void QWebElement::render(QPainter* painter, const QRect& clip)
   1497 {
   1498     WebCore::Element* e = m_element;
   1499     Document* doc = e ? e->document() : 0;
   1500     if (!doc)
   1501         return;
   1502 
   1503     Frame* frame = doc->frame();
   1504     if (!frame || !frame->view() || !frame->contentRenderer())
   1505         return;
   1506 
   1507     FrameView* view = frame->view();
   1508 
   1509     view->updateLayoutAndStyleIfNeededRecursive();
   1510 
   1511     IntRect rect = e->getRect();
   1512 
   1513     if (rect.size().isEmpty())
   1514         return;
   1515 
   1516     QRect finalClipRect = rect;
   1517     if (!clip.isEmpty())
   1518         rect.intersect(clip.translated(rect.location()));
   1519 
   1520     GraphicsContext context(painter);
   1521 
   1522     context.save();
   1523     context.translate(-rect.x(), -rect.y());
   1524     painter->setClipRect(finalClipRect, Qt::IntersectClip);
   1525     view->setNodeToDraw(e);
   1526     view->paintContents(&context, finalClipRect);
   1527     view->setNodeToDraw(0);
   1528     context.restore();
   1529 }
   1530 
   1531 class QWebElementCollectionPrivate : public QSharedData
   1532 {
   1533 public:
   1534     static QWebElementCollectionPrivate* create(const PassRefPtr<Node> &context, const QString &query);
   1535 
   1536     RefPtr<NodeList> m_result;
   1537 
   1538 private:
   1539     inline QWebElementCollectionPrivate() {}
   1540 };
   1541 
   1542 QWebElementCollectionPrivate* QWebElementCollectionPrivate::create(const PassRefPtr<Node> &context, const QString &query)
   1543 {
   1544     if (!context)
   1545         return 0;
   1546 
   1547     // Let WebKit do the hard work hehehe
   1548     ExceptionCode exception = 0; // ###
   1549     RefPtr<NodeList> nodes = context->querySelectorAll(query, exception);
   1550     if (!nodes)
   1551         return 0;
   1552 
   1553     QWebElementCollectionPrivate* priv = new QWebElementCollectionPrivate;
   1554     priv->m_result = nodes;
   1555     return priv;
   1556 }
   1557 
   1558 /*!
   1559     \class QWebElementCollection
   1560     \since 4.6
   1561     \brief The QWebElementCollection class represents a collection of web elements.
   1562     \preliminary
   1563 
   1564     Elements in a document can be selected using QWebElement::findAll() or using the
   1565     QWebElement constructor. The collection is composed by choosing all elements in the
   1566     document that match a specified CSS selector expression.
   1567 
   1568     The number of selected elements is provided through the count() property. Individual
   1569     elements can be retrieved by index using at().
   1570 
   1571     It is also possible to iterate through all elements in the collection using Qt's foreach
   1572     macro:
   1573 
   1574     \code
   1575         QWebElementCollection collection = document.findAll("p");
   1576         foreach (QWebElement paraElement, collection) {
   1577             ...
   1578         }
   1579     \endcode
   1580 */
   1581 
   1582 /*!
   1583     Constructs an empty collection.
   1584 */
   1585 QWebElementCollection::QWebElementCollection()
   1586 {
   1587 }
   1588 
   1589 /*!
   1590     Constructs a copy of \a other.
   1591 */
   1592 QWebElementCollection::QWebElementCollection(const QWebElementCollection &other)
   1593     : d(other.d)
   1594 {
   1595 }
   1596 
   1597 /*!
   1598     Constructs a collection of elements from the list of child elements of \a contextElement that
   1599     match the specified CSS selector \a query.
   1600 */
   1601 QWebElementCollection::QWebElementCollection(const QWebElement &contextElement, const QString &query)
   1602 {
   1603     d = QExplicitlySharedDataPointer<QWebElementCollectionPrivate>(QWebElementCollectionPrivate::create(contextElement.m_element, query));
   1604 }
   1605 
   1606 /*!
   1607     Assigns \a other to this collection and returns a reference to this collection.
   1608 */
   1609 QWebElementCollection &QWebElementCollection::operator=(const QWebElementCollection &other)
   1610 {
   1611     d = other.d;
   1612     return *this;
   1613 }
   1614 
   1615 /*!
   1616     Destroys the collection.
   1617 */
   1618 QWebElementCollection::~QWebElementCollection()
   1619 {
   1620 }
   1621 
   1622 /*! \fn QWebElementCollection &QWebElementCollection::operator+=(const QWebElementCollection &other)
   1623 
   1624     Appends the items of the \a other list to this list and returns a
   1625     reference to this list.
   1626 
   1627     \sa operator+(), append()
   1628 */
   1629 
   1630 /*!
   1631     Returns a collection that contains all the elements of this collection followed
   1632     by all the elements in the \a other collection. Duplicates may occur in the result.
   1633 
   1634     \sa operator+=()
   1635 */
   1636 QWebElementCollection QWebElementCollection::operator+(const QWebElementCollection &other) const
   1637 {
   1638     QWebElementCollection n = *this; n.d.detach(); n += other; return n;
   1639 }
   1640 
   1641 /*!
   1642     Extends the collection by appending all items of \a other.
   1643 
   1644     The resulting collection may include duplicate elements.
   1645 
   1646     \sa operator+=()
   1647 */
   1648 void QWebElementCollection::append(const QWebElementCollection &other)
   1649 {
   1650     if (!d) {
   1651         *this = other;
   1652         return;
   1653     }
   1654     if (!other.d)
   1655         return;
   1656     Vector<RefPtr<Node> > nodes;
   1657     RefPtr<NodeList> results[] = { d->m_result, other.d->m_result };
   1658     nodes.reserveInitialCapacity(results[0]->length() + results[1]->length());
   1659 
   1660     for (int i = 0; i < 2; ++i) {
   1661         int j = 0;
   1662         Node* n = results[i]->item(j);
   1663         while (n) {
   1664             nodes.append(n);
   1665             n = results[i]->item(++j);
   1666         }
   1667     }
   1668 
   1669     d->m_result = StaticNodeList::adopt(nodes);
   1670 }
   1671 
   1672 /*!
   1673     Returns the number of elements in the collection.
   1674 */
   1675 int QWebElementCollection::count() const
   1676 {
   1677     if (!d)
   1678         return 0;
   1679     return d->m_result->length();
   1680 }
   1681 
   1682 /*!
   1683     Returns the element at index position \a i in the collection.
   1684 */
   1685 QWebElement QWebElementCollection::at(int i) const
   1686 {
   1687     if (!d)
   1688         return QWebElement();
   1689     Node* n = d->m_result->item(i);
   1690     return QWebElement(static_cast<Element*>(n));
   1691 }
   1692 
   1693 /*!
   1694     \fn const QWebElement QWebElementCollection::operator[](int position) const
   1695 
   1696     Returns the element at the specified \a position in the collection.
   1697 */
   1698 
   1699 /*! \fn QWebElement QWebElementCollection::first() const
   1700 
   1701     Returns the first element in the collection.
   1702 
   1703     \sa last(), operator[](), at(), count()
   1704 */
   1705 
   1706 /*! \fn QWebElement QWebElementCollection::last() const
   1707 
   1708     Returns the last element in the collection.
   1709 
   1710     \sa first(), operator[](), at(), count()
   1711 */
   1712 
   1713 /*!
   1714     Returns a QList object with the elements contained in this collection.
   1715 */
   1716 QList<QWebElement> QWebElementCollection::toList() const
   1717 {
   1718     if (!d)
   1719         return QList<QWebElement>();
   1720     QList<QWebElement> elements;
   1721     int i = 0;
   1722     Node* n = d->m_result->item(i);
   1723     while (n) {
   1724         if (n->isElementNode())
   1725             elements.append(QWebElement(static_cast<Element*>(n)));
   1726         n = d->m_result->item(++i);
   1727     }
   1728     return elements;
   1729 }
   1730 
   1731 /*!
   1732     \fn QWebElementCollection::const_iterator QWebElementCollection::begin() const
   1733 
   1734     Returns an STL-style iterator pointing to the first element in the collection.
   1735 
   1736     \sa end()
   1737 */
   1738 
   1739 /*!
   1740     \fn QWebElementCollection::const_iterator QWebElementCollection::end() const
   1741 
   1742     Returns an STL-style iterator pointing to the imaginary element after the
   1743     last element in the list.
   1744 
   1745     \sa begin()
   1746 */
   1747 
   1748 /*!
   1749     \class QWebElementCollection::const_iterator
   1750     \since 4.6
   1751     \brief The QWebElementCollection::const_iterator class provides an STL-style const iterator for QWebElementCollection.
   1752 
   1753     QWebElementCollection provides STL style const iterators for fast low-level access to the elements.
   1754 
   1755     QWebElementCollection::const_iterator allows you to iterate over a QWebElementCollection.
   1756 */
   1757 
   1758 /*!
   1759     \fn QWebElementCollection::const_iterator::const_iterator(const const_iterator &other)
   1760 
   1761     Constructs a copy of \a other.
   1762 */
   1763 
   1764 /*!
   1765     \fn QWebElementCollection::const_iterator::const_iterator(const QWebElementCollection *collection, int index)
   1766     \internal
   1767 */
   1768 
   1769 /*!
   1770     \fn const QWebElement QWebElementCollection::const_iterator::operator*() const
   1771 
   1772     Returns the current element.
   1773 */
   1774 
   1775 /*!
   1776     \fn bool QWebElementCollection::const_iterator::operator==(const const_iterator &other) const
   1777 
   1778     Returns true if \a other points to the same item as this iterator;
   1779     otherwise returns false.
   1780 
   1781     \sa operator!=()
   1782 */
   1783 
   1784 /*!
   1785     \fn bool QWebElementCollection::const_iterator::operator!=(const const_iterator &other) const
   1786 
   1787     Returns true if \a other points to a different element than this;
   1788     iterator; otherwise returns false.
   1789 
   1790     \sa operator==()
   1791 */
   1792 
   1793 /*!
   1794     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator++()
   1795 
   1796     The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection
   1797     and returns an iterator to the new current element.
   1798 
   1799     Calling this function on QWebElementCollection::end() leads to undefined results.
   1800 
   1801     \sa operator--()
   1802 */
   1803 
   1804 /*!
   1805     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator++(int)
   1806 
   1807     \overload
   1808 
   1809     The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection
   1810     and returns an iterator to the previously current element.
   1811 
   1812     Calling this function on QWebElementCollection::end() leads to undefined results.
   1813 */
   1814 
   1815 /*!
   1816     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator--()
   1817 
   1818     The prefix -- operator (\c{--it}) makes the preceding element current and returns an
   1819     iterator to the new current element.
   1820 
   1821     Calling this function on QWebElementCollection::begin() leads to undefined results.
   1822 
   1823     \sa operator++()
   1824 */
   1825 
   1826 /*!
   1827     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator--(int)
   1828 
   1829     \overload
   1830 
   1831     The postfix -- operator (\c{it--}) makes the preceding element current and returns
   1832     an iterator to the previously current element.
   1833 */
   1834 
   1835 /*!
   1836     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator+=(int j)
   1837 
   1838     Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward.
   1839 
   1840     \sa operator-=(), operator+()
   1841 */
   1842 
   1843 /*!
   1844     \fn QWebElementCollection::const_iterator &QWebElementCollection::const_iterator::operator-=(int j)
   1845 
   1846     Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward.
   1847 
   1848     \sa operator+=(), operator-()
   1849 */
   1850 
   1851 /*!
   1852     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator+(int j) const
   1853 
   1854     Returns an iterator to the element at \a j positions forward from this iterator. If \a j
   1855     is negative, the iterator goes backward.
   1856 
   1857     \sa operator-(), operator+=()
   1858 */
   1859 
   1860 /*!
   1861     \fn QWebElementCollection::const_iterator QWebElementCollection::const_iterator::operator-(int j) const
   1862 
   1863     Returns an iterator to the element at \a j positiosn backward from this iterator.
   1864     If \a j is negative, the iterator goes forward.
   1865 
   1866     \sa operator+(), operator-=()
   1867 */
   1868 
   1869 /*!
   1870     \fn int QWebElementCollection::const_iterator::operator-(const_iterator other) const
   1871 
   1872     Returns the number of elements between the item point to by \a other
   1873     and the element pointed to by this iterator.
   1874 */
   1875 
   1876 /*!
   1877     \fn bool QWebElementCollection::const_iterator::operator<(const const_iterator &other) const
   1878 
   1879     Returns true if the element pointed to by this iterator is less than the element pointed to
   1880     by the \a other iterator.
   1881 */
   1882 
   1883 /*!
   1884     \fn bool QWebElementCollection::const_iterator::operator<=(const const_iterator &other) const
   1885 
   1886     Returns true if the element pointed to by this iterator is less than or equal to the
   1887     element pointed to by the \a other iterator.
   1888 */
   1889 
   1890 /*!
   1891     \fn bool QWebElementCollection::const_iterator::operator>(const const_iterator &other) const
   1892 
   1893     Returns true if the element pointed to by this iterator is greater than the element pointed to
   1894     by the \a other iterator.
   1895 */
   1896 
   1897 /*!
   1898     \fn bool QWebElementCollection::const_iterator::operator>=(const const_iterator &other) const
   1899 
   1900     Returns true if the element pointed to by this iterator is greater than or equal to the
   1901     element pointed to by the \a other iterator.
   1902 */
   1903 
   1904 /*!
   1905     \fn QWebElementCollection::iterator QWebElementCollection::begin()
   1906 
   1907     Returns an STL-style iterator pointing to the first element in the collection.
   1908 
   1909     \sa end()
   1910 */
   1911 
   1912 /*!
   1913     \fn QWebElementCollection::iterator QWebElementCollection::end()
   1914 
   1915     Returns an STL-style iterator pointing to the imaginary element after the
   1916     last element in the list.
   1917 
   1918     \sa begin()
   1919 */
   1920 
   1921 /*!
   1922     \fn QWebElementCollection::const_iterator QWebElementCollection::constBegin() const
   1923 
   1924     Returns an STL-style iterator pointing to the first element in the collection.
   1925 
   1926     \sa end()
   1927 */
   1928 
   1929 /*!
   1930     \fn QWebElementCollection::const_iterator QWebElementCollection::constEnd() const
   1931 
   1932     Returns an STL-style iterator pointing to the imaginary element after the
   1933     last element in the list.
   1934 
   1935     \sa begin()
   1936 */
   1937 
   1938 /*!
   1939     \class QWebElementCollection::iterator
   1940     \since 4.6
   1941     \brief The QWebElementCollection::iterator class provides an STL-style iterator for QWebElementCollection.
   1942 
   1943     QWebElementCollection provides STL style iterators for fast low-level access to the elements.
   1944 
   1945     QWebElementCollection::iterator allows you to iterate over a QWebElementCollection.
   1946 */
   1947 
   1948 /*!
   1949     \fn QWebElementCollection::iterator::iterator(const iterator &other)
   1950 
   1951     Constructs a copy of \a other.
   1952 */
   1953 
   1954 /*!
   1955     \fn QWebElementCollection::iterator::iterator(const QWebElementCollection *collection, int index)
   1956     \internal
   1957 */
   1958 
   1959 /*!
   1960     \fn const QWebElement QWebElementCollection::iterator::operator*() const
   1961 
   1962     Returns the current element.
   1963 */
   1964 
   1965 /*!
   1966     \fn bool QWebElementCollection::iterator::operator==(const iterator &other) const
   1967 
   1968     Returns true if \a other points to the same item as this iterator;
   1969     otherwise returns false.
   1970 
   1971     \sa operator!=()
   1972 */
   1973 
   1974 /*!
   1975     \fn bool QWebElementCollection::iterator::operator!=(const iterator &other) const
   1976 
   1977     Returns true if \a other points to a different element than this;
   1978     iterator; otherwise returns false.
   1979 
   1980     \sa operator==()
   1981 */
   1982 
   1983 /*!
   1984     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator++()
   1985 
   1986     The prefix ++ operator (\c{++it}) advances the iterator to the next element in the collection
   1987     and returns an iterator to the new current element.
   1988 
   1989     Calling this function on QWebElementCollection::end() leads to undefined results.
   1990 
   1991     \sa operator--()
   1992 */
   1993 
   1994 /*!
   1995     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator++(int)
   1996 
   1997     \overload
   1998 
   1999     The postfix ++ operator (\c{it++}) advances the iterator to the next element in the collection
   2000     and returns an iterator to the previously current element.
   2001 
   2002     Calling this function on QWebElementCollection::end() leads to undefined results.
   2003 */
   2004 
   2005 /*!
   2006     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator--()
   2007 
   2008     The prefix -- operator (\c{--it}) makes the preceding element current and returns an
   2009     iterator to the new current element.
   2010 
   2011     Calling this function on QWebElementCollection::begin() leads to undefined results.
   2012 
   2013     \sa operator++()
   2014 */
   2015 
   2016 /*!
   2017     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator--(int)
   2018 
   2019     \overload
   2020 
   2021     The postfix -- operator (\c{it--}) makes the preceding element current and returns
   2022     an iterator to the previously current element.
   2023 */
   2024 
   2025 /*!
   2026     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator+=(int j)
   2027 
   2028     Advances the iterator by \a j elements. If \a j is negative, the iterator goes backward.
   2029 
   2030     \sa operator-=(), operator+()
   2031 */
   2032 
   2033 /*!
   2034     \fn QWebElementCollection::iterator &QWebElementCollection::iterator::operator-=(int j)
   2035 
   2036     Makes the iterator go back by \a j elements. If \a j is negative, the iterator goes forward.
   2037 
   2038     \sa operator+=(), operator-()
   2039 */
   2040 
   2041 /*!
   2042     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator+(int j) const
   2043 
   2044     Returns an iterator to the element at \a j positions forward from this iterator. If \a j
   2045     is negative, the iterator goes backward.
   2046 
   2047     \sa operator-(), operator+=()
   2048 */
   2049 
   2050 /*!
   2051     \fn QWebElementCollection::iterator QWebElementCollection::iterator::operator-(int j) const
   2052 
   2053     Returns an iterator to the element at \a j positiosn backward from this iterator.
   2054     If \a j is negative, the iterator goes forward.
   2055 
   2056     \sa operator+(), operator-=()
   2057 */
   2058 
   2059 /*!
   2060     \fn int QWebElementCollection::iterator::operator-(iterator other) const
   2061 
   2062     Returns the number of elements between the item point to by \a other
   2063     and the element pointed to by this iterator.
   2064 */
   2065 
   2066 /*!
   2067     \fn bool QWebElementCollection::iterator::operator<(const iterator &other) const
   2068 
   2069     Returns true if the element pointed to by this iterator is less than the element pointed to
   2070     by the \a other iterator.
   2071 */
   2072 
   2073 /*!
   2074     \fn bool QWebElementCollection::iterator::operator<=(const iterator &other) const
   2075 
   2076     Returns true if the element pointed to by this iterator is less than or equal to the
   2077     element pointed to by the \a other iterator.
   2078 */
   2079 
   2080 /*!
   2081     \fn bool QWebElementCollection::iterator::operator>(const iterator &other) const
   2082 
   2083     Returns true if the element pointed to by this iterator is greater than the element pointed to
   2084     by the \a other iterator.
   2085 */
   2086 
   2087 /*!
   2088     \fn bool QWebElementCollection::iterator::operator>=(const iterator &other) const
   2089 
   2090     Returns true if the element pointed to by this iterator is greater than or equal to the
   2091     element pointed to by the \a other iterator.
   2092 */
   2093