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 38namespace WebCore { 39 40void 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 49int 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 70String 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->inCompatMode()) 77 text = data.label(); 78 if (text.isEmpty()) 79 text = collectOptionInnerText(element); 80 return normalizeText(document, text); 81} 82 83String 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 100String 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 112String 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 121String 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 132OptionElementData::OptionElementData() 133 : m_selected(false) 134{ 135} 136 137OptionElement* toOptionElement(Element* element) 138{ 139 if (element->isHTMLElement() && element->hasTagName(HTMLNames::optionTag)) 140 return static_cast<HTMLOptionElement*>(element); 141 142#if ENABLE(WML) 143 if (element->isWMLElement() && element->hasTagName(WMLNames::optionTag)) 144 return static_cast<WMLOptionElement*>(element); 145#endif 146 147 return 0; 148} 149 150bool isOptionElement(Element* element) 151{ 152 return element->hasLocalName(HTMLNames::optionTag) 153#if ENABLE(WML) 154 || element->hasLocalName(WMLNames::optionTag) 155#endif 156 ; 157} 158 159} 160