1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/* 2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * This library is free software; you can redistribute it and/or 5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modify it under the terms of the GNU Library General Public 6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * License as published by the Free Software Foundation; either 7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * version 2 of the License, or (at your option) any later version. 8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * This library is distributed in the hope that it will be useful, 10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Library General Public License for more details. 13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * You should have received a copy of the GNU Library General Public License 15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * along with this library; see the file COPYING.LIB. If not, write to 16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Boston, MA 02110-1301, USA. 18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */ 20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h" 22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "OptionElement.h" 23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Document.h" 25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Element.h" 26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLNames.h" 27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "HTMLOptionElement.h" 28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "OptionGroupElement.h" 29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "ScriptElement.h" 305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "SelectElement.h" 31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/Assertions.h> 32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if ENABLE(WML) 34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "WMLOptionElement.h" 35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "WMLNames.h" 36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore { 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid OptionElement::setSelectedState(OptionElementData& data, Element* element, bool selected) 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (data.selected() == selected) 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 45635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project data.setSelected(selected); 465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian element->setNeedsStyleRecalc(); 47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianint OptionElement::optionIndex(SelectElement* selectElement, const Element* element) 50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!selectElement) 525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return 0; 535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Let's do this dynamically. Might be a bit slow, but we're sure 555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // we won't forget to update a member variable in some cases... 565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian const Vector<Element*>& items = selectElement->listItems(); 575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int length = items.size(); 585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian int optionIndex = 0; 595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian for (int i = 0; i < length; ++i) { 605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!isOptionElement(items[i])) 615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian continue; 625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (items[i] == element) 635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return optionIndex; 645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ++optionIndex; 655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return 0; 685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochString OptionElement::collectOptionLabelOrText(const OptionElementData& data, const Element* element) 715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Document* document = element->document(); 73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project String text; 74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // WinIE does not use the label attribute, so as a quirk, we ignore it. 765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen if (!document->inQuirksMode()) 77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project text = data.label(); 780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (text.isEmpty()) 790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch text = collectOptionInnerText(element); 800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return normalizeText(document, text); 810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochString OptionElement::collectOptionInnerText(const Element* element) 840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch String text; 860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Node* n = element->firstChild(); 870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (n) { 880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) 890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch text += n->nodeValue(); 900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // skip script content 920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (n->isElementNode() && toScriptElement(static_cast<Element*>(n))) 930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch n = n->traverseNextSibling(element); 940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else 950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch n = n->traverseNextNode(element); 96635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return text; 980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochString OptionElement::normalizeText(const Document* document, const String& src) 1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch String text = document->displayStringModifiedByEncoding(src); 103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 104635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. 105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project text = text.stripWhiteSpace(); 106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // We want to collapse our whitespace too. This will match other browsers. 108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project text = text.simplifyWhiteSpace(); 109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return text; 110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1125f1ab04193ad0130ca8204aadaceae083aca9881Feng QianString OptionElement::collectOptionTextRespectingGroupLabel(const OptionElementData& data, const Element* element) 113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian Element* parentElement = static_cast<Element*>(element->parentNode()); 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (parentElement && toOptionGroupElement(parentElement)) 1160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return " " + collectOptionLabelOrText(data, element); 117635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return collectOptionLabelOrText(data, element); 119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 120635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1215f1ab04193ad0130ca8204aadaceae083aca9881Feng QianString OptionElement::collectOptionValue(const OptionElementData& data, const Element* element) 122635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 123635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project String value = data.value(); 124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!value.isNull()) 125635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return value; 126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Use the text if the value wasn't set. 1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return collectOptionInnerText(element).stripWhiteSpace(); 129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// OptionElementData 1325f1ab04193ad0130ca8204aadaceae083aca9881Feng QianOptionElementData::OptionElementData() 1335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian : m_selected(false) 134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 137a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochOptionElementData::~OptionElementData() 138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectOptionElement* toOptionElement(Element* element) 142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (element->isHTMLElement() && element->hasTagName(HTMLNames::optionTag)) 144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return static_cast<HTMLOptionElement*>(element); 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#if ENABLE(WML) 147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (element->isWMLElement() && element->hasTagName(WMLNames::optionTag)) 148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return static_cast<WMLOptionElement*>(element); 149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return 0; 152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 1545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool isOptionElement(Element* element) 1555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 1565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return element->hasLocalName(HTMLNames::optionTag) 1575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#if ENABLE(WML) 1585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian || element->hasLocalName(WMLNames::optionTag) 1595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif 1605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ; 1615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 1625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 164