• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
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 
21 #include "config.h"
22 #include "OptionElement.h"
23 
24 #include "Document.h"
25 #include "Element.h"
26 #include "HTMLNames.h"
27 #include "HTMLOptionElement.h"
28 #include "OptionGroupElement.h"
29 #include "ScriptElement.h"
30 #include "SelectElement.h"
31 #include <wtf/Assertions.h>
32 
33 #if ENABLE(WML)
34 #include "WMLOptionElement.h"
35 #include "WMLNames.h"
36 #endif
37 
38 namespace WebCore {
39 
setSelectedState(OptionElementData & data,Element * element,bool selected)40 void OptionElement::setSelectedState(OptionElementData& data, Element* element, bool selected)
41 {
42     if (data.selected() == selected)
43         return;
44 
45     data.setSelected(selected);
46     element->setNeedsStyleRecalc();
47 }
48 
optionIndex(SelectElement * selectElement,const Element * element)49 int OptionElement::optionIndex(SelectElement* selectElement, const Element* element)
50 {
51     if (!selectElement)
52         return 0;
53 
54     // Let's do this dynamically. Might be a bit slow, but we're sure
55     // we won't forget to update a member variable in some cases...
56     const Vector<Element*>& items = selectElement->listItems();
57     int length = items.size();
58     int optionIndex = 0;
59     for (int i = 0; i < length; ++i) {
60         if (!isOptionElement(items[i]))
61             continue;
62         if (items[i] == element)
63             return optionIndex;
64         ++optionIndex;
65     }
66 
67     return 0;
68 }
69 
collectOptionLabelOrText(const OptionElementData & data,const Element * element)70 String OptionElement::collectOptionLabelOrText(const OptionElementData& data, const Element* element)
71 {
72     Document* document = element->document();
73     String text;
74 
75     // WinIE does not use the label attribute, so as a quirk, we ignore it.
76     if (!document->inQuirksMode())
77         text = data.label();
78     if (text.isEmpty())
79         text = collectOptionInnerText(element);
80     return normalizeText(document, text);
81 }
82 
collectOptionInnerText(const Element * element)83 String OptionElement::collectOptionInnerText(const Element* element)
84 {
85     String text;
86     Node* n = element->firstChild();
87     while (n) {
88         if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE)
89             text += n->nodeValue();
90 
91         // skip script content
92         if (n->isElementNode() && toScriptElement(static_cast<Element*>(n)))
93             n = n->traverseNextSibling(element);
94         else
95             n = n->traverseNextNode(element);
96     }
97     return text;
98 }
99 
normalizeText(const Document * document,const String & src)100 String OptionElement::normalizeText(const Document* document, const String& src)
101 {
102     String text = document->displayStringModifiedByEncoding(src);
103 
104     // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
105     text = text.stripWhiteSpace();
106 
107     // We want to collapse our whitespace too.  This will match other browsers.
108     text = text.simplifyWhiteSpace();
109     return text;
110 }
111 
collectOptionTextRespectingGroupLabel(const OptionElementData & data,const Element * element)112 String OptionElement::collectOptionTextRespectingGroupLabel(const OptionElementData& data, const Element* element)
113 {
114     Element* parentElement = static_cast<Element*>(element->parentNode());
115     if (parentElement && toOptionGroupElement(parentElement))
116         return "    " + collectOptionLabelOrText(data, element);
117 
118     return collectOptionLabelOrText(data, element);
119 }
120 
collectOptionValue(const OptionElementData & data,const Element * element)121 String OptionElement::collectOptionValue(const OptionElementData& data, const Element* element)
122 {
123     String value = data.value();
124     if (!value.isNull())
125         return value;
126 
127     // Use the text if the value wasn't set.
128     return collectOptionInnerText(element).stripWhiteSpace();
129 }
130 
131 // OptionElementData
OptionElementData()132 OptionElementData::OptionElementData()
133     : m_selected(false)
134 {
135 }
136 
~OptionElementData()137 OptionElementData::~OptionElementData()
138 {
139 }
140 
toOptionElement(Element * element)141 OptionElement* toOptionElement(Element* element)
142 {
143     if (element->isHTMLElement() && element->hasTagName(HTMLNames::optionTag))
144         return static_cast<HTMLOptionElement*>(element);
145 
146 #if ENABLE(WML)
147     if (element->isWMLElement() && element->hasTagName(WMLNames::optionTag))
148         return static_cast<WMLOptionElement*>(element);
149 #endif
150 
151     return 0;
152 }
153 
isOptionElement(Element * element)154 bool isOptionElement(Element* element)
155 {
156     return element->hasLocalName(HTMLNames::optionTag)
157 #if ENABLE(WML)
158         || element->hasLocalName(WMLNames::optionTag)
159 #endif
160         ;
161 }
162 
163 }
164