3045b90072b96f554b9facfdb2e882615579fe2b
[WebKit-https.git] / Source / WebCore / html / RadioNodeList.cpp
1 /*
2  * Copyright (c) 2012 Motorola Mobility, Inc. All rights reserved.
3  * Copyright (C) 2014 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY MOTOROLA MOBILITY, INC. AND ITS CONTRIBUTORS
15  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY, INC. OR ITS
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "RadioNodeList.h"
29
30 #include "HTMLFormElement.h"
31 #include "HTMLInputElement.h"
32 #include "HTMLNames.h"
33 #include "HTMLObjectElement.h"
34 #include "NodeRareData.h"
35
36 namespace WebCore {
37
38 using namespace HTMLNames;
39
40 RadioNodeList::RadioNodeList(ContainerNode& rootNode, const AtomicString& name)
41     : CachedLiveNodeList(rootNode, InvalidateForFormControls)
42     , m_name(name)
43     , m_isRootedAtDocument(is<HTMLFormElement>(ownerNode()))
44 {
45 }
46
47 RadioNodeList::~RadioNodeList()
48 {
49     ownerNode().nodeLists()->removeCacheWithAtomicName(this, m_name);
50 }
51
52 static inline HTMLInputElement* toRadioButtonInputElement(HTMLElement& element)
53 {
54     if (!is<HTMLInputElement>(element))
55         return nullptr;
56
57     auto& inputElement = downcast<HTMLInputElement>(element);
58     if (!inputElement.isRadioButton() || inputElement.value().isEmpty())
59         return nullptr;
60     return &inputElement;
61 }
62
63 String RadioNodeList::value() const
64 {
65     auto length = this->length();
66     for (unsigned i = 0; i < length; ++i) {
67         auto* inputElement = toRadioButtonInputElement(*item(i));
68         if (!inputElement || !inputElement->checked())
69             continue;
70         return inputElement->value();
71     }
72     return String();
73 }
74
75 void RadioNodeList::setValue(const String& value)
76 {
77     auto length = this->length();
78     for (unsigned i = 0; i < length; ++i) {
79         auto* inputElement = toRadioButtonInputElement(*item(i));
80         if (!inputElement || inputElement->value() != value)
81             continue;
82         inputElement->setChecked(true);
83         return;
84     }
85 }
86
87 bool RadioNodeList::checkElementMatchesRadioNodeListFilter(const Element& testElement) const
88 {
89     ASSERT(is<HTMLObjectElement>(testElement) || is<HTMLFormControlElement>(testElement));
90     if (is<HTMLFormElement>(ownerNode())) {
91         RefPtr<HTMLFormElement> formElement;
92         if (testElement.hasTagName(objectTag))
93             formElement = downcast<HTMLObjectElement>(testElement).form();
94         else
95             formElement = downcast<HTMLFormControlElement>(testElement).form();
96         if (!formElement || formElement != &ownerNode())
97             return false;
98     }
99
100     return testElement.getIdAttribute() == m_name || testElement.getNameAttribute() == m_name;
101 }
102
103 bool RadioNodeList::elementMatches(Element& testElement) const
104 {
105     if (!is<HTMLObjectElement>(testElement) && !is<HTMLFormControlElement>(testElement))
106         return false;
107
108     if (is<HTMLInputElement>(testElement) && downcast<HTMLInputElement>(testElement).isImageButton())
109         return false;
110
111     return checkElementMatchesRadioNodeListFilter(testElement);
112 }
113
114 } // namspace
115