• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
6  * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
7  * Copyright (C) 2010 Google Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25 
26 #include "config.h"
27 #include "HTMLOptionElement.h"
28 
29 #include "Attribute.h"
30 #include "CSSStyleSelector.h"
31 #include "Document.h"
32 #include "ExceptionCode.h"
33 #include "HTMLNames.h"
34 #include "HTMLSelectElement.h"
35 #include "NodeRenderStyle.h"
36 #include "RenderMenuList.h"
37 #include "Text.h"
38 #include <wtf/StdLibExtras.h>
39 #include <wtf/Vector.h>
40 
41 namespace WebCore {
42 
43 using namespace HTMLNames;
44 
HTMLOptionElement(const QualifiedName & tagName,Document * document,HTMLFormElement * form)45 HTMLOptionElement::HTMLOptionElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
46     : HTMLFormControlElement(tagName, document, form)
47 {
48     ASSERT(hasTagName(optionTag));
49 }
50 
create(Document * document,HTMLFormElement * form)51 PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(Document* document, HTMLFormElement* form)
52 {
53     return adoptRef(new HTMLOptionElement(optionTag, document, form));
54 }
55 
create(const QualifiedName & tagName,Document * document,HTMLFormElement * form)56 PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
57 {
58     return adoptRef(new HTMLOptionElement(tagName, document, form));
59 }
60 
createForJSConstructor(Document * document,const String & data,const String & value,bool defaultSelected,bool selected,ExceptionCode & ec)61 PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document* document, const String& data, const String& value,
62         bool defaultSelected, bool selected, ExceptionCode& ec)
63 {
64     RefPtr<HTMLOptionElement> element = adoptRef(new HTMLOptionElement(optionTag, document));
65 
66     RefPtr<Text> text = Text::create(document, data.isNull() ? "" : data);
67 
68     ec = 0;
69     element->appendChild(text.release(), ec);
70     if (ec)
71         return 0;
72 
73     if (!value.isNull())
74         element->setValue(value);
75     element->setDefaultSelected(defaultSelected);
76     element->setSelected(selected);
77 
78     return element.release();
79 }
80 
attach()81 void HTMLOptionElement::attach()
82 {
83     if (parentNode()->renderStyle())
84         setRenderStyle(styleForRenderer());
85     HTMLFormControlElement::attach();
86 }
87 
detach()88 void HTMLOptionElement::detach()
89 {
90     m_style.clear();
91     HTMLFormControlElement::detach();
92 }
93 
supportsFocus() const94 bool HTMLOptionElement::supportsFocus() const
95 {
96     return HTMLElement::supportsFocus();
97 }
98 
isFocusable() const99 bool HTMLOptionElement::isFocusable() const
100 {
101     // Option elements do not have a renderer so we check the renderStyle instead.
102     return supportsFocus() && renderStyle() && renderStyle()->display() != NONE;
103 }
104 
formControlType() const105 const AtomicString& HTMLOptionElement::formControlType() const
106 {
107     DEFINE_STATIC_LOCAL(const AtomicString, option, ("option"));
108     return option;
109 }
110 
text() const111 String HTMLOptionElement::text() const
112 {
113     return OptionElement::collectOptionLabelOrText(m_data, this);
114 }
115 
setText(const String & text,ExceptionCode & ec)116 void HTMLOptionElement::setText(const String &text, ExceptionCode& ec)
117 {
118     // Handle the common special case where there's exactly 1 child node, and it's a text node.
119     Node* child = firstChild();
120     if (child && child->isTextNode() && !child->nextSibling()) {
121         static_cast<Text *>(child)->setData(text, ec);
122         return;
123     }
124 
125     removeChildren();
126     appendChild(Text::create(document(), text), ec);
127 }
128 
accessKeyAction(bool)129 void HTMLOptionElement::accessKeyAction(bool)
130 {
131     HTMLSelectElement* select = ownerSelectElement();
132     if (select)
133         select->accessKeySetSelectedIndex(index());
134 }
135 
index() const136 int HTMLOptionElement::index() const
137 {
138     return OptionElement::optionIndex(ownerSelectElement(), this);
139 }
140 
parseMappedAttribute(Attribute * attr)141 void HTMLOptionElement::parseMappedAttribute(Attribute* attr)
142 {
143     if (attr->name() == selectedAttr)
144         m_data.setSelected(!attr->isNull());
145     else if (attr->name() == valueAttr)
146         m_data.setValue(attr->value());
147     else if (attr->name() == labelAttr)
148         m_data.setLabel(attr->value());
149     else
150         HTMLFormControlElement::parseMappedAttribute(attr);
151 }
152 
value() const153 String HTMLOptionElement::value() const
154 {
155     return OptionElement::collectOptionValue(m_data, this);
156 }
157 
setValue(const String & value)158 void HTMLOptionElement::setValue(const String& value)
159 {
160     setAttribute(valueAttr, value);
161 }
162 
selected() const163 bool HTMLOptionElement::selected() const
164 {
165     if (HTMLSelectElement* select = ownerSelectElement())
166         select->recalcListItemsIfNeeded();
167     return m_data.selected();
168 }
169 
setSelected(bool selected)170 void HTMLOptionElement::setSelected(bool selected)
171 {
172     if (m_data.selected() == selected)
173         return;
174 
175     OptionElement::setSelectedState(m_data, this, selected);
176 
177     if (HTMLSelectElement* select = ownerSelectElement())
178         select->setSelectedIndex(selected ? index() : -1, false);
179 }
180 
setSelectedState(bool selected)181 void HTMLOptionElement::setSelectedState(bool selected)
182 {
183     OptionElement::setSelectedState(m_data, this, selected);
184 }
185 
childrenChanged(bool changedByParser,Node * beforeChange,Node * afterChange,int childCountDelta)186 void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
187 {
188     HTMLSelectElement* select = ownerSelectElement();
189     if (select)
190         select->childrenChanged(changedByParser);
191     HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
192 }
193 
ownerSelectElement() const194 HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const
195 {
196     ContainerNode* select = parentNode();
197     while (select && !select->hasTagName(selectTag))
198         select = select->parentNode();
199 
200     if (!select)
201         return 0;
202 
203     return static_cast<HTMLSelectElement*>(select);
204 }
205 
defaultSelected() const206 bool HTMLOptionElement::defaultSelected() const
207 {
208     return fastHasAttribute(selectedAttr);
209 }
210 
setDefaultSelected(bool b)211 void HTMLOptionElement::setDefaultSelected(bool b)
212 {
213     setAttribute(selectedAttr, b ? "" : 0);
214 }
215 
label() const216 String HTMLOptionElement::label() const
217 {
218     return m_data.label();
219 }
220 
setRenderStyle(PassRefPtr<RenderStyle> newStyle)221 void HTMLOptionElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle)
222 {
223     m_style = newStyle;
224     if (HTMLSelectElement* select = ownerSelectElement())
225         if (RenderObject* renderer = select->renderer())
226             renderer->repaint();
227 }
228 
nonRendererRenderStyle() const229 RenderStyle* HTMLOptionElement::nonRendererRenderStyle() const
230 {
231     return m_style.get();
232 }
233 
textIndentedToRespectGroupLabel() const234 String HTMLOptionElement::textIndentedToRespectGroupLabel() const
235 {
236     return OptionElement::collectOptionTextRespectingGroupLabel(m_data, this);
237 }
238 
disabled() const239 bool HTMLOptionElement::disabled() const
240 {
241     return ownElementDisabled() || (parentNode() && static_cast<HTMLFormControlElement*>(parentNode())->disabled());
242 }
243 
insertedIntoTree(bool deep)244 void HTMLOptionElement::insertedIntoTree(bool deep)
245 {
246     if (HTMLSelectElement* select = ownerSelectElement()) {
247         select->setRecalcListItems();
248         // Avoid our selected() getter since it will recalculate list items incorrectly for us.
249         if (m_data.selected())
250             select->setSelectedIndex(index(), false);
251         select->scrollToSelection();
252     }
253 
254     HTMLFormControlElement::insertedIntoTree(deep);
255 }
256 
257 } // namespace
258