Title: [118720] trunk
Revision
118720
Author
[email protected]
Date
2012-05-28 20:57:17 -0700 (Mon, 28 May 2012)

Log Message

[Forms] HTMLFieldSetElement.idl doesn't have elements attribute.
https://bugs.webkit.org/show_bug.cgi?id=80110

Patch by Rakesh KN <[email protected]> on 2012-05-28
Reviewed by Kent Tamura.

Source/WebCore:

Implemented elements attribute for HTMLFieldSetElement. This is spec'ed at
http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#dom-fieldset-elements

Tests: fast/forms/fieldset/fieldset-elements.html
       fast/forms/fieldset/fieldset-form-collection-radionode-list.html

* dom/Node.cpp:
(WebCore::Node::radioNodeList):
Extended ASSERT to assert if not HTMLFieldSetElement or HTMLFormElement.
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::elements):
Elements attribute implementation.
(WebCore::HTMLFieldSetElement::refreshElementsIfNeeded):
Update the formcontrol elements collections if dom tree got modified.
(WebCore::HTMLFieldSetElement::associatedElements):
FormControl elements collection accessor.
(WebCore::HTMLFieldSetElement::length):
Number of elements in the fieldset group.
* html/HTMLFieldSetElement.h:
Added elements collection member and form control collection members.
* html/HTMLFieldSetElement.idl:
Added elements attribute.
* html/HTMLFormCollection.cpp:
(WebCore::HTMLFormCollection::formControlElements):
Added support for HTMLFieldSetElement, based on base element type gets its associated elements.
(WebCore::HTMLFormCollection::numberOfFormControlElements): Ditto
(WebCore::HTMLFormCollection::getNamedFormItem): Process image elements only for form element.
(WebCore::HTMLFormCollection::updateNameCache): Ditto
* html/RadioNodeList.cpp:
(WebCore::RadioNodeList::RadioNodeList):
DynamicSubTree root element is decided based on the type whether base element is form or fieldset element.
Renamed m_formElement to m_baseElement.
(WebCore::RadioNodeList::~RadioNodeList):
Renamed m_formElement to m_baseElement.
(WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter):
Form element specific changes moved under form element check.
* html/RadioNodeList.h:
(WebCore::RadioNodeList::create):
(RadioNodeList):
Renamed m_formElement to m_baseElement.

LayoutTests:

* fast/forms/fieldset/fieldset-elements-expected.txt: Added.
* fast/forms/fieldset/fieldset-elements.html: Added.
* fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt: Added.
* fast/forms/fieldset/fieldset-form-collection-radionode-list.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (118719 => 118720)


--- trunk/LayoutTests/ChangeLog	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/LayoutTests/ChangeLog	2012-05-29 03:57:17 UTC (rev 118720)
@@ -1,3 +1,15 @@
+2012-05-28  Rakesh KN  <[email protected]>
+
+        [Forms] HTMLFieldSetElement.idl doesn't have elements attribute.
+        https://bugs.webkit.org/show_bug.cgi?id=80110
+
+        Reviewed by Kent Tamura.
+
+        * fast/forms/fieldset/fieldset-elements-expected.txt: Added.
+        * fast/forms/fieldset/fieldset-elements.html: Added.
+        * fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt: Added.
+        * fast/forms/fieldset/fieldset-form-collection-radionode-list.html: Added.
+
 2012-05-28  David Barton  <[email protected]>
 
         mathml/presentation/mo-stretch.html and mroot-pref-width.html tests fail on Mac

Added: trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-expected.txt (0 => 118720)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-elements-expected.txt	2012-05-29 03:57:17 UTC (rev 118720)
@@ -0,0 +1,49 @@
+This test the elements attibute of HTMLFieldSet element.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS owner.elements.length is 23
+PASS owner.elements[0].id is 'button1'
+PASS owner.elements[1].id is 'fieldset1'
+PASS owner.elements[2].id is 'inputhidden'
+PASS owner.elements[3].id is 'inputtext'
+PASS owner.elements[4].id is 'inputsearch'
+PASS owner.elements[5].id is 'inputurl'
+PASS owner.elements[6].id is 'inputemail'
+PASS owner.elements[7].id is 'inputpassword'
+PASS owner.elements[8].id is 'inputdate'
+PASS owner.elements[9].id is 'inputnumber'
+PASS owner.elements[10].id is 'inputrange'
+PASS owner.elements[11].id is 'inputcolor'
+PASS owner.elements[12].id is 'inputcheckbox'
+PASS owner.elements[13].id is 'inputradio'
+PASS owner.elements[14].id is 'inputfile'
+PASS owner.elements[15].id is 'inputsubmit'
+PASS owner.elements[16].id is 'inputreset'
+PASS owner.elements[17].id is 'inputbutton'
+PASS owner.elements[18].id is 'keygen1'
+PASS owner.elements[19].id is 'object1'
+PASS owner.elements[20].id is 'output1'
+PASS owner.elements[21].id is 'select1'
+PASS owner.elements[22].id is 'textarea1'
+
+Check elements array is updated after adding a new element
+PASS owner.appendChild(newElement); owner.elements.length is 24
+
+Check elements array is updated after remove an element
+PASS owner.removeChild(newElement); owner.elements.length is 23
+
+Check owner.elements is updated properly
+PASS document.getElementById("inputfile").type="image"; owner.elements.length is 22
+
+Check owner.elements is updated properly after removing from parent
+PASS form.appendChild(newElement); form.elements.length is 1
+PASS form.removeChild(newElement); form.elements.length is 0
+PASS owner.elements.length is 22
+PASS owner.appendChild(newElement); owner.elements.length is 23
+PASS owner.removeChild(newElement); owner.elements.length is 22
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/forms/fieldset/fieldset-elements.html (0 => 118720)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-elements.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-elements.html	2012-05-29 03:57:17 UTC (rev 118720)
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+</head>
+<body>
+<script>
+description("This test the elements attibute of HTMLFieldSet element.");
+
+var container = document.createElement('div');
+document.body.appendChild(container);
+
+container.innerHTML = '<form id=formElement> <fieldset id="fs">' +
+    '<button id=button1></button>' +
+    '<fieldset id=fieldset1><legend id=legend1></legend></fieldset>' +
+    '<div> <input id=inputhidden type=hidden> </div>' +
+    '<input id=inputtext type=text>' +
+    '<input id=inputsearch type=search>' +
+    '<input id=inputurl type=url>' +
+    '<input id=inputemail type=email>' +
+    '<input id=inputpassword type=password>' +
+    '<input id=inputdate type=date>' +
+    '<input id=inputnumber type=number>' +
+    '<input id=inputrange type=range>' +
+    '<input id=inputcolor type=color>' +
+    '<input id=inputcheckbox type=checkbox>' +
+    '<input id=inputradio type=radio>' +
+    '<input id=inputfile type=file>' +
+    '<input id=inputsubmit type=submit>' +
+    '<input id=inputimage type=image>' +
+    '<input id=inputreset type=reset>' +
+    '<input id=inputbutton type=button>' +
+    '<keygen id=keygen1></keygen>' +
+    '<label id=label1></label>' +
+    '<meter id=meter1></meter>' +
+    '<object id=object1></object>' +
+    '<output id=output1></output>' +
+    '<progress id=progress1></progress>' +
+    '<select id=select1>' +
+    '    <optgroup id=optgroup1>group1</optgroup>' +
+    '    <option id=option1>option1</option>' +
+    '</select>' +
+    '<textarea id=textarea1></textarea>' +
+    '</fieldset> </form>';
+
+var owner = document.getElementById('fs');
+
+shouldBe('owner.elements.length', '23');
+shouldBe('owner.elements[0].id', "'button1'");
+shouldBe('owner.elements[1].id', "'fieldset1'");
+shouldBe('owner.elements[2].id', "'inputhidden'");
+shouldBe('owner.elements[3].id', "'inputtext'");
+shouldBe('owner.elements[4].id', "'inputsearch'");
+shouldBe('owner.elements[5].id', "'inputurl'");
+shouldBe('owner.elements[6].id', "'inputemail'");
+shouldBe('owner.elements[7].id', "'inputpassword'");
+shouldBe('owner.elements[8].id', "'inputdate'");
+shouldBe('owner.elements[9].id', "'inputnumber'");
+shouldBe('owner.elements[10].id', "'inputrange'");
+shouldBe('owner.elements[11].id', "'inputcolor'");
+shouldBe('owner.elements[12].id', "'inputcheckbox'");
+shouldBe('owner.elements[13].id', "'inputradio'");
+shouldBe('owner.elements[14].id', "'inputfile'");
+shouldBe('owner.elements[15].id', "'inputsubmit'");
+shouldBe('owner.elements[16].id', "'inputreset'");
+shouldBe('owner.elements[17].id', "'inputbutton'");
+shouldBe('owner.elements[18].id', "'keygen1'");
+shouldBe('owner.elements[19].id', "'object1'");
+shouldBe('owner.elements[20].id', "'output1'");
+shouldBe('owner.elements[21].id', "'select1'");
+shouldBe('owner.elements[22].id', "'textarea1'");
+
+var newElement = document.createElement("input");
+newElement.setAttribute("type", "text");
+newElement.setAttribute("value", "new element");
+newElement.setAttribute("id", "inputcommon");
+
+debug("");
+debug("Check elements array is updated after adding a new element");
+shouldBe('owner.appendChild(newElement); owner.elements.length', '24');
+
+debug("");
+debug("Check elements array is updated after remove an element");
+shouldBe('owner.removeChild(newElement); owner.elements.length', '23');
+
+debug("");
+debug("Check owner.elements is updated properly");
+shouldBe('document.getElementById("inputfile").type="image"; owner.elements.length', '22');
+
+debug("");
+debug("Check owner.elements is updated properly after removing from parent");
+owner.parentNode.removeChild(owner);
+var form = document.getElementById("formElement");
+shouldBe('form.appendChild(newElement); form.elements.length', '1');
+shouldBe('form.removeChild(newElement); form.elements.length', '0');
+shouldBe('owner.elements.length', '22');
+shouldBe('owner.appendChild(newElement); owner.elements.length', '23');
+shouldBe('owner.removeChild(newElement); owner.elements.length', '22');
+
+container.parentNode.removeChild(container);
+</script>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt (0 => 118720)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list-expected.txt	2012-05-29 03:57:17 UTC (rev 118720)
@@ -0,0 +1,53 @@
+This test is for RadioNodeList specified at http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#radionodelist
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+PASS owner.elements.length is 23
+PASS radioNodeList.length is 4
+PASS radioNodeList[0].value is 'searching'
+PASS radioNodeList[1].value is '123'
+PASS radioNodeList[2].value is 'inputRadioValue'
+PASS radioNodeList[3].value is 'buttonValue'
+
+Changing the input value to check RadioNodeList is live view of FormCollection
+PASS radioNodeList[1].value is '456'
+
+Checking value IDL attribute on the RadioNodeList
+PASS radioNodeList.value is ""
+PASS radioNodeList.value = "inputRadioValue"; radioNodeList[2].checked is true
+PASS Object.prototype.toString.call(radioNodeList[2]) is '[object HTMLInputElement]'
+PASS radioNodeList[2].type is 'radio'
+PASS radioNodeList.value is ""
+PASS radioNodeList[2].checked = true; radioNodeList.value is 'inputRadioValue'
+
+Check RadioNodeList is updated after adding a new element
+PASS owner.appendChild(newElement); radioNodeList.length is 5
+PASS owner.elements.length is 24
+PASS radioNodeList[4].value is 'new element'
+
+Check RadioNodeList is updated after remove an element
+PASS owner.removeChild(newElement); radioNodeList.length is 4
+PASS radioNodeList[3].value is 'buttonValue'
+
+Check RadioNodeList is updated after change in id, type and checked state of an element
+PASS radioNodeList.length is 4
+After changing the id
+PASS radioNodeList.length is 3
+PASS elementsList[13].checked = false; radioNodeList.value is ""
+PASS elementsList[13].checked = true; radioNodeList.value is 'inputRadioValue'
+PASS elementsList[13].type = "date"; radioNodeList.value is ''
+
+Check second RadioNodeList is also created properly
+PASS radioNodeList2.length is 3
+PASS radioNodeList2[0].type is 'text'
+PASS radioNodeList2[1].type is 'email'
+PASS radioNodeList2[2].type is 'reset'
+After changing the id
+PASS radioNodeList2.length is 2
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list.html (0 => 118720)


--- trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/fieldset/fieldset-form-collection-radionode-list.html	2012-05-29 03:57:17 UTC (rev 118720)
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<p id="description"></p>
+<div id="divId">
+<form>
+<fieldset id="fs">
+    <button id=button1></button>
+    <fieldset id=fieldset1><legend id=legend1></legend></fieldset>
+    <input id=inputhidden type=hidden>
+    <input id=commoninput type=text>
+    <input id=inputcommon type=search value=searching>
+    <input id=inputurl type=url>
+    <input id=commoninput type=email>
+    <input id=inputpassword type=password>
+    <input id=inputdate type=date>
+    <input id=numberId name=inputcommon type=number value=123>
+    <input id=inputrange type=range>
+    <input id=inputcolor type=color>
+    <input id=inputcheckbox type=checkbox>
+    <input id=inputcommon type=radio value="inputRadioValue">
+    <input id=inputfile type=file>
+    <input id=inputsubmit type=submit>
+    <input id=inputcommon type=image>
+    <input id=commoninput type=reset>
+    <input id=inputcommon type=button value=buttonValue>
+    <keygen id=keygen1></keygen>
+    <label id=label1></label>
+    <meter id=meter1></meter>
+    <object id=object1></object>
+    <output id=output1></output>
+    <progress id=progress1></progress>
+    <select id=select1>
+        <optgroup id=optgroup1>group1</optgroup>
+        <option id=option1>option1</option>
+    </select>
+    <textarea id=textarea1></textarea>
+</fieldset>
+</form>
+</div>
+<div id="console"></div>
+<script>
+description("This test is for RadioNodeList specified at http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#radionodelist ");
+debug("");
+var owner = document.getElementById('fs');
+
+shouldBe('owner.elements.length', '23');
+
+var elementsList = owner.elements;
+var radioNodeList = elementsList.namedItem("inputcommon");
+shouldBe('radioNodeList.length', '4');
+
+shouldBe('radioNodeList[0].value', "'searching'");
+shouldBe('radioNodeList[1].value', "'123'");
+shouldBe('radioNodeList[2].value', "'inputRadioValue'");
+shouldBe('radioNodeList[3].value', "'buttonValue'");
+
+debug("");
+debug("Changing the input value to check RadioNodeList is live view of FormCollection");
+document.getElementById("numberId").value = 456;
+shouldBe('radioNodeList[1].value', "'456'");
+
+debug("");
+debug("Checking value IDL attribute on the RadioNodeList");
+shouldBe('radioNodeList.value', '""');
+shouldBe('radioNodeList.value = "inputRadioValue"; radioNodeList[2].checked', 'true');
+shouldBe('Object.prototype.toString.call(radioNodeList[2])', "'[object HTMLInputElement]'");
+shouldBe('radioNodeList[2].type', "'radio'");
+
+radioNodeList[2].checked = false;
+shouldBe('radioNodeList.value', '""');
+shouldBe('radioNodeList[2].checked = true; radioNodeList.value', "'inputRadioValue'");
+
+var newElement = document.createElement("input");
+newElement.setAttribute("type", "text");
+newElement.setAttribute("value", "new element");
+newElement.setAttribute("id", "inputcommon");
+
+debug("");
+debug("Check RadioNodeList is updated after adding a new element");
+shouldBe('owner.appendChild(newElement); radioNodeList.length', '5');
+shouldBe('owner.elements.length', '24');
+shouldBe('radioNodeList[4].value', "'new element'");
+
+debug("");
+debug("Check RadioNodeList is updated after remove an element");
+shouldBe('owner.removeChild(newElement); radioNodeList.length', '4');
+shouldBe('radioNodeList[3].value', "'buttonValue'");
+
+debug("");
+debug("Check RadioNodeList is updated after change in id, type and checked state of an element");
+shouldBe('radioNodeList.length', '4');
+debug("After changing the id");
+radioNodeList[3].id = "changedName";
+shouldBe('radioNodeList.length', '3');
+
+shouldBe('elementsList[13].checked = false; radioNodeList.value', '""');
+shouldBe('elementsList[13].checked = true; radioNodeList.value', "'inputRadioValue'");
+shouldBe('elementsList[13].type = "date"; radioNodeList.value', "''");
+
+debug("");
+debug("Check second RadioNodeList is also created properly");
+var radioNodeList2 = elementsList.namedItem("commoninput");
+shouldBe('radioNodeList2.length', '3');
+
+shouldBe('radioNodeList2[0].type', "'text'");
+shouldBe('radioNodeList2[1].type', "'email'");
+shouldBe('radioNodeList2[2].type', "'reset'");
+radioNodeList2[2].id = "idChanged";
+debug("After changing the id");
+shouldBe('radioNodeList2.length', '2');
+debug("");
+
+var container = document.getElementById("divId");
+container.parentNode.removeChild(container);
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (118719 => 118720)


--- trunk/Source/WebCore/ChangeLog	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/ChangeLog	2012-05-29 03:57:17 UTC (rev 118720)
@@ -1,3 +1,51 @@
+2012-05-28  Rakesh KN  <[email protected]>
+
+        [Forms] HTMLFieldSetElement.idl doesn't have elements attribute.
+        https://bugs.webkit.org/show_bug.cgi?id=80110
+
+        Reviewed by Kent Tamura.
+
+        Implemented elements attribute for HTMLFieldSetElement. This is spec'ed at
+        http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#dom-fieldset-elements
+
+        Tests: fast/forms/fieldset/fieldset-elements.html
+               fast/forms/fieldset/fieldset-form-collection-radionode-list.html
+
+        * dom/Node.cpp:
+        (WebCore::Node::radioNodeList):
+        Extended ASSERT to assert if not HTMLFieldSetElement or HTMLFormElement.
+        * html/HTMLFieldSetElement.cpp:
+        (WebCore::HTMLFieldSetElement::elements):
+        Elements attribute implementation.
+        (WebCore::HTMLFieldSetElement::refreshElementsIfNeeded):
+        Update the formcontrol elements collections if dom tree got modified.
+        (WebCore::HTMLFieldSetElement::associatedElements):
+        FormControl elements collection accessor.
+        (WebCore::HTMLFieldSetElement::length):
+        Number of elements in the fieldset group.
+        * html/HTMLFieldSetElement.h:
+        Added elements collection member and form control collection members.
+        * html/HTMLFieldSetElement.idl:
+        Added elements attribute.
+        * html/HTMLFormCollection.cpp:
+        (WebCore::HTMLFormCollection::formControlElements):
+        Added support for HTMLFieldSetElement, based on base element type gets its associated elements.
+        (WebCore::HTMLFormCollection::numberOfFormControlElements): Ditto
+        (WebCore::HTMLFormCollection::getNamedFormItem): Process image elements only for form element.
+        (WebCore::HTMLFormCollection::updateNameCache): Ditto
+        * html/RadioNodeList.cpp:
+        (WebCore::RadioNodeList::RadioNodeList):
+        DynamicSubTree root element is decided based on the type whether base element is form or fieldset element.
+        Renamed m_formElement to m_baseElement.
+        (WebCore::RadioNodeList::~RadioNodeList):
+        Renamed m_formElement to m_baseElement.
+        (WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter):
+        Form element specific changes moved under form element check.
+        * html/RadioNodeList.h:
+        (WebCore::RadioNodeList::create):
+        (RadioNodeList):
+        Renamed m_formElement to m_baseElement.
+
 2012-05-28  Jonathan Dong  <[email protected]>
 
         [BlackBerry] http authenticate dialog popup only once no matter authentication pass or fail

Modified: trunk/Source/WebCore/dom/Node.cpp (118719 => 118720)


--- trunk/Source/WebCore/dom/Node.cpp	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/dom/Node.cpp	2012-05-29 03:57:17 UTC (rev 118720)
@@ -2931,7 +2931,7 @@
 
 PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name)
 {
-    ASSERT(hasTagName(formTag));
+    ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
 
     NodeListsNodeData* nodeLists = ensureRareData()->ensureNodeLists(this);
 

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.cpp (118719 => 118720)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.cpp	2012-05-29 03:57:17 UTC (rev 118720)
@@ -24,9 +24,11 @@
 
 #include "config.h"
 #include "HTMLFieldSetElement.h"
+
+#include "HTMLFormCollection.h"
 #include "HTMLLegendElement.h"
-
 #include "HTMLNames.h"
+#include "HTMLObjectElement.h"
 #include "RenderFieldset.h"
 #include <wtf/StdLibExtras.h>
 
@@ -81,4 +83,53 @@
     return 0;
 }
 
+HTMLCollection* HTMLFieldSetElement::elements()
+{
+    if (!m_elementsCollection)
+        m_elementsCollection = HTMLFormCollection::create(this);
+    return m_elementsCollection.get();
+}
+
+void HTMLFieldSetElement::refreshElementsIfNeeded() const
+{
+    uint64_t docVersion = document()->domTreeVersion();
+    if (m_documentVersion == docVersion)
+        return;
+
+    m_documentVersion = docVersion;
+
+    m_associatedElements.clear();
+
+    for (Node* node = firstChild(); node; node = node->traverseNextNode(this)) {
+        if (!node->isElementNode())
+            continue;
+
+        if (node->hasTagName(objectTag)) {
+            m_associatedElements.append(static_cast<HTMLObjectElement*>(node));
+            continue;
+        }
+
+        if (!toElement(node)->isFormControlElement())
+            continue;
+
+        m_associatedElements.append(static_cast<HTMLFormControlElement*>(node));
+    }
+}
+
+const Vector<FormAssociatedElement*>& HTMLFieldSetElement::associatedElements() const
+{
+    refreshElementsIfNeeded();
+    return m_associatedElements;
+}
+
+unsigned HTMLFieldSetElement::length() const
+{
+    refreshElementsIfNeeded();
+    unsigned len = 0;
+    for (unsigned i = 0; i < m_associatedElements.size(); ++i)
+        if (m_associatedElements[i]->isEnumeratable())
+            ++len;
+    return len;
+}
+
 } // namespace

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.h (118719 => 118720)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.h	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.h	2012-05-29 03:57:17 UTC (rev 118720)
@@ -25,14 +25,24 @@
 #define HTMLFieldSetElement_h
 
 #include "HTMLFormControlElement.h"
+#include <wtf/OwnPtr.h>
 
 namespace WebCore {
 
+class FormAssociatedElement;
+class HTMLCollection;
+class HTMLFormCollection;
+
 class HTMLFieldSetElement : public HTMLFormControlElement {
 public:
     static PassRefPtr<HTMLFieldSetElement> create(const QualifiedName&, Document*, HTMLFormElement*);
     HTMLLegendElement* legend() const;
 
+    HTMLCollection* elements();
+
+    const Vector<FormAssociatedElement*>& associatedElements() const;
+    unsigned length() const;
+
 protected:
     virtual void disabledAttributeChanged() OVERRIDE;
 
@@ -44,6 +54,13 @@
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     virtual const AtomicString& formControlType() const;
     virtual bool recalcWillValidate() const { return false; }
+
+    void refreshElementsIfNeeded() const;
+
+    OwnPtr<HTMLFormCollection> m_elementsCollection;
+    mutable Vector<FormAssociatedElement*> m_associatedElements;
+    // When dom tree is modified, we have to refresh the m_associatedElements array.
+    mutable uint64_t m_documentVersion;
 };
 
 } // namespace

Modified: trunk/Source/WebCore/html/HTMLFieldSetElement.idl (118719 => 118720)


--- trunk/Source/WebCore/html/HTMLFieldSetElement.idl	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/html/HTMLFieldSetElement.idl	2012-05-29 03:57:17 UTC (rev 118720)
@@ -26,6 +26,8 @@
 
         readonly attribute DOMString type;
 
+        readonly attribute HTMLCollection elements;
+
         readonly attribute boolean         willValidate;
         readonly attribute ValidityState   validity;
         readonly attribute DOMString       validationMessage;

Modified: trunk/Source/WebCore/html/HTMLFormCollection.cpp (118719 => 118720)


--- trunk/Source/WebCore/html/HTMLFormCollection.cpp	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/html/HTMLFormCollection.cpp	2012-05-29 03:57:17 UTC (rev 118720)
@@ -23,6 +23,7 @@
 #include "config.h"
 #include "HTMLFormCollection.h"
 
+#include "HTMLFieldSetElement.h"
 #include "HTMLFormControlElement.h"
 #include "HTMLFormElement.h"
 #include "HTMLImageElement.h"
@@ -53,8 +54,10 @@
 const Vector<FormAssociatedElement*>& HTMLFormCollection::formControlElements() const
 {
     ASSERT(base());
-    ASSERT(base()->hasTagName(formTag));
-    return static_cast<HTMLFormElement*>(base())->associatedElements();
+    ASSERT(base()->hasTagName(formTag) || base()->hasTagName(fieldsetTag));
+    if (base()->hasTagName(formTag))
+        return static_cast<HTMLFormElement*>(base())->associatedElements();
+    return static_cast<HTMLFieldSetElement*>(base())->associatedElements();
 }
 
 const Vector<HTMLImageElement*>& HTMLFormCollection::formImageElements() const
@@ -67,8 +70,10 @@
 unsigned HTMLFormCollection::numberOfFormControlElements() const
 {
     ASSERT(base());
-    ASSERT(base()->hasTagName(formTag));
-    return static_cast<HTMLFormElement*>(base())->length();
+    ASSERT(base()->hasTagName(formTag) || base()->hasTagName(fieldsetTag));
+    if (base()->hasTagName(formTag))
+        return static_cast<HTMLFormElement*>(base())->length();
+    return static_cast<HTMLFieldSetElement*>(base())->length();
 }
 
 unsigned HTMLFormCollection::calcLength() const
@@ -134,6 +139,9 @@
         }
     }
 
+    if (base()->hasTagName(fieldsetTag))
+        return 0;
+
     const Vector<HTMLImageElement*>& imageElementsArray = formImageElements();
     if (!foundInputElements) {
         for (unsigned i = 0; i < imageElementsArray.size(); ++i) {
@@ -195,15 +203,17 @@
         }
     }
 
-    const Vector<HTMLImageElement*>& imageElementsArray = formImageElements();
-    for (unsigned i = 0; i < imageElementsArray.size(); ++i) {
-        HTMLImageElement* element = imageElementsArray[i];
-        const AtomicString& idAttrVal = element->getIdAttribute();
-        const AtomicString& nameAttrVal = element->getNameAttribute();
-        if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl()))
-            append(m_cache.idCache, idAttrVal, element);
-        if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl()))
-            append(m_cache.nameCache, nameAttrVal, element);
+    if (base()->hasTagName(formTag)) {
+        const Vector<HTMLImageElement*>& imageElementsArray = formImageElements();
+        for (unsigned i = 0; i < imageElementsArray.size(); ++i) {
+            HTMLImageElement* element = imageElementsArray[i];
+            const AtomicString& idAttrVal = element->getIdAttribute();
+            const AtomicString& nameAttrVal = element->getNameAttribute();
+            if (!idAttrVal.isEmpty() && !foundInputElements.contains(idAttrVal.impl()))
+                append(m_cache.idCache, idAttrVal, element);
+            if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && !foundInputElements.contains(nameAttrVal.impl()))
+                append(m_cache.nameCache, nameAttrVal, element);
+        }
     }
 
     m_cache.hasNameCache = true;

Modified: trunk/Source/WebCore/html/RadioNodeList.cpp (118719 => 118720)


--- trunk/Source/WebCore/html/RadioNodeList.cpp	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/html/RadioNodeList.cpp	2012-05-29 03:57:17 UTC (rev 118720)
@@ -36,18 +36,18 @@
 
 using namespace HTMLNames;
 
-RadioNodeList::RadioNodeList(const AtomicString& name, Element* formElement)
-    : DynamicSubtreeNodeList(formElement->document())
+RadioNodeList::RadioNodeList(const AtomicString& name, Element* baseElement)
+    : DynamicSubtreeNodeList(baseElement->hasTagName(formTag) ? static_cast<Node*>(baseElement->document()) : baseElement)
     , m_name(name)
-    , m_formElement(formElement)
+    , m_baseElement(baseElement)
 {
-    m_formElement->document()->registerDynamicSubtreeNodeList(this);
+    m_baseElement->document()->registerDynamicSubtreeNodeList(this);
 }
 
 RadioNodeList::~RadioNodeList()
 {
-    m_formElement->removeCachedRadioNodeList(this, m_name);
-    m_formElement->document()->unregisterDynamicSubtreeNodeList(this);
+    m_baseElement->removeCachedRadioNodeList(this, m_name);
+    m_baseElement->document()->unregisterDynamicSubtreeNodeList(this);
 }
 
 static inline HTMLInputElement* toRadioButtonInputElement(Node* node)
@@ -86,13 +86,15 @@
 bool RadioNodeList::checkElementMatchesRadioNodeListFilter(Element* testElement) const
 {
     ASSERT(testElement->hasTagName(objectTag) || testElement->isFormControlElement());
-    HTMLFormElement* formElement = 0;
-    if (testElement->hasTagName(objectTag))
-        formElement = static_cast<HTMLObjectElement*>(testElement)->form();
-    else
-        formElement = static_cast<HTMLFormControlElement*>(testElement)->form();
-    if (!formElement || formElement != m_formElement)
-        return false;
+    if (m_baseElement->hasTagName(formTag)) {
+        HTMLFormElement* formElement = 0;
+        if (testElement->hasTagName(objectTag))
+            formElement = static_cast<HTMLObjectElement*>(testElement)->form();
+        else
+            formElement = static_cast<HTMLFormControlElement*>(testElement)->form();
+        if (!formElement || formElement != m_baseElement)
+            return false;
+    }
 
     return testElement->getIdAttribute() == m_name || testElement->getNameAttribute() == m_name;
 }

Modified: trunk/Source/WebCore/html/RadioNodeList.h (118719 => 118720)


--- trunk/Source/WebCore/html/RadioNodeList.h	2012-05-29 03:49:32 UTC (rev 118719)
+++ trunk/Source/WebCore/html/RadioNodeList.h	2012-05-29 03:57:17 UTC (rev 118720)
@@ -36,9 +36,9 @@
 
 class RadioNodeList : public DynamicSubtreeNodeList {
 public:
-    static PassRefPtr<RadioNodeList> create(const AtomicString& name, Element* formElement)
+    static PassRefPtr<RadioNodeList> create(const AtomicString& name, Element* baseElement)
     {
-        return adoptRef(new RadioNodeList(name, formElement));
+        return adoptRef(new RadioNodeList(name, baseElement));
     }
 
     ~RadioNodeList();
@@ -54,7 +54,7 @@
     bool checkElementMatchesRadioNodeListFilter(Element*) const;
 
     AtomicString m_name;
-    RefPtr<Element> m_formElement;
+    RefPtr<Element> m_baseElement;
 };
 
 } // namepsace
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to