WebCore/html/HTMLOptionElement.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 
       
    45 HTMLOptionElement::HTMLOptionElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
       
    46     : HTMLFormControlElement(tagName, document, form)
       
    47 {
       
    48     ASSERT(hasTagName(optionTag));
       
    49 }
       
    50 
       
    51 PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(Document* document, HTMLFormElement* form)
       
    52 {
       
    53     return adoptRef(new HTMLOptionElement(optionTag, document, form));
       
    54 }
       
    55 
       
    56 PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
       
    57 {
       
    58     return adoptRef(new HTMLOptionElement(tagName, document, form));
       
    59 }
       
    60 
       
    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 
       
    81 bool HTMLOptionElement::checkDTD(const Node* newChild)
       
    82 {
       
    83     return newChild->isTextNode() || newChild->hasTagName(scriptTag);
       
    84 }
       
    85 
       
    86 void HTMLOptionElement::attach()
       
    87 {
       
    88     if (parentNode()->renderStyle())
       
    89         setRenderStyle(styleForRenderer());
       
    90     HTMLFormControlElement::attach();
       
    91 }
       
    92 
       
    93 void HTMLOptionElement::detach()
       
    94 {
       
    95     m_style.clear();
       
    96     HTMLFormControlElement::detach();
       
    97 }
       
    98 
       
    99 bool HTMLOptionElement::supportsFocus() const
       
   100 {
       
   101     return HTMLElement::supportsFocus();
       
   102 }
       
   103 
       
   104 bool HTMLOptionElement::isFocusable() const
       
   105 {
       
   106     // Option elements do not have a renderer so we check the renderStyle instead.
       
   107     return supportsFocus() && renderStyle() && renderStyle()->display() != NONE;
       
   108 }
       
   109 
       
   110 const AtomicString& HTMLOptionElement::formControlType() const
       
   111 {
       
   112     DEFINE_STATIC_LOCAL(const AtomicString, option, ("option"));
       
   113     return option;
       
   114 }
       
   115 
       
   116 String HTMLOptionElement::text() const
       
   117 {
       
   118     return OptionElement::collectOptionLabelOrText(m_data, this);
       
   119 }
       
   120 
       
   121 void HTMLOptionElement::setText(const String &text, ExceptionCode& ec)
       
   122 {
       
   123     // Handle the common special case where there's exactly 1 child node, and it's a text node.
       
   124     Node* child = firstChild();
       
   125     if (child && child->isTextNode() && !child->nextSibling()) {
       
   126         static_cast<Text *>(child)->setData(text, ec);
       
   127         return;
       
   128     }
       
   129 
       
   130     removeChildren();
       
   131     appendChild(Text::create(document(), text), ec);
       
   132 }
       
   133 
       
   134 void HTMLOptionElement::accessKeyAction(bool)
       
   135 {
       
   136     HTMLSelectElement* select = ownerSelectElement();
       
   137     if (select)
       
   138         select->accessKeySetSelectedIndex(index());
       
   139 }
       
   140 
       
   141 int HTMLOptionElement::index() const
       
   142 {
       
   143     return OptionElement::optionIndex(ownerSelectElement(), this);
       
   144 }
       
   145 
       
   146 void HTMLOptionElement::parseMappedAttribute(Attribute* attr)
       
   147 {
       
   148     if (attr->name() == selectedAttr)
       
   149         m_data.setSelected(!attr->isNull());
       
   150     else if (attr->name() == valueAttr)
       
   151         m_data.setValue(attr->value());
       
   152     else if (attr->name() == labelAttr)
       
   153         m_data.setLabel(attr->value());
       
   154     else
       
   155         HTMLFormControlElement::parseMappedAttribute(attr);
       
   156 }
       
   157 
       
   158 String HTMLOptionElement::value() const
       
   159 {
       
   160     return OptionElement::collectOptionValue(m_data, this);
       
   161 }
       
   162 
       
   163 void HTMLOptionElement::setValue(const String& value)
       
   164 {
       
   165     setAttribute(valueAttr, value);
       
   166 }
       
   167 
       
   168 bool HTMLOptionElement::selected() const
       
   169 {
       
   170     if (HTMLSelectElement* select = ownerSelectElement())
       
   171         select->recalcListItemsIfNeeded();
       
   172     return m_data.selected();
       
   173 }
       
   174 
       
   175 void HTMLOptionElement::setSelected(bool selected)
       
   176 {
       
   177     if (m_data.selected() == selected)
       
   178         return;
       
   179 
       
   180     OptionElement::setSelectedState(m_data, this, selected);
       
   181 
       
   182     if (HTMLSelectElement* select = ownerSelectElement())
       
   183         select->setSelectedIndex(selected ? index() : -1, false);
       
   184 }
       
   185 
       
   186 void HTMLOptionElement::setSelectedState(bool selected)
       
   187 {
       
   188     OptionElement::setSelectedState(m_data, this, selected);
       
   189 }
       
   190 
       
   191 void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
       
   192 {
       
   193     HTMLSelectElement* select = ownerSelectElement();
       
   194     if (select)
       
   195         select->childrenChanged(changedByParser);
       
   196     HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
       
   197 }
       
   198 
       
   199 HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const
       
   200 {
       
   201     Node* select = parentNode();
       
   202     while (select && !(select->hasTagName(selectTag) || select->hasTagName(keygenTag)))
       
   203         select = select->parentNode();
       
   204 
       
   205     if (!select)
       
   206         return 0;
       
   207 
       
   208     return static_cast<HTMLSelectElement*>(select);
       
   209 }
       
   210 
       
   211 bool HTMLOptionElement::defaultSelected() const
       
   212 {
       
   213     return !getAttribute(selectedAttr).isNull();
       
   214 }
       
   215 
       
   216 void HTMLOptionElement::setDefaultSelected(bool b)
       
   217 {
       
   218     setAttribute(selectedAttr, b ? "" : 0);
       
   219 }
       
   220 
       
   221 String HTMLOptionElement::label() const
       
   222 {
       
   223     return m_data.label();
       
   224 }
       
   225 
       
   226 void HTMLOptionElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle)
       
   227 {
       
   228     m_style = newStyle;
       
   229 }
       
   230 
       
   231 RenderStyle* HTMLOptionElement::nonRendererRenderStyle() const
       
   232 {
       
   233     return m_style.get();
       
   234 }
       
   235 
       
   236 String HTMLOptionElement::textIndentedToRespectGroupLabel() const
       
   237 {
       
   238     return OptionElement::collectOptionTextRespectingGroupLabel(m_data, this);
       
   239 }
       
   240 
       
   241 bool HTMLOptionElement::disabled() const
       
   242 {
       
   243     return ownElementDisabled() || (parentNode() && static_cast<HTMLFormControlElement*>(parentNode())->disabled());
       
   244 }
       
   245 
       
   246 void HTMLOptionElement::insertedIntoTree(bool deep)
       
   247 {
       
   248     if (HTMLSelectElement* select = ownerSelectElement()) {
       
   249         select->setRecalcListItems();
       
   250         // Avoid our selected() getter since it will recalculate list items incorrectly for us.
       
   251         if (m_data.selected())
       
   252             select->setSelectedIndex(index(), false);
       
   253         select->scrollToSelection();
       
   254     }
       
   255 
       
   256     HTMLFormControlElement::insertedIntoTree(deep);
       
   257 }
       
   258 
       
   259 } // namespace