Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      6  *           (C) 2006 Alexey Proskuryakov (ap (at) nypop.com)
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  *
     23  */
     24 
     25 #include "config.h"
     26 #include "HTMLOptGroupElement.h"
     27 
     28 #include "CSSStyleSelector.h"
     29 #include "Document.h"
     30 #include "HTMLNames.h"
     31 #include "HTMLSelectElement.h"
     32 #include "RenderMenuList.h"
     33 #include "NodeRenderStyle.h"
     34 #include <wtf/StdLibExtras.h>
     35 
     36 namespace WebCore {
     37 
     38 using namespace HTMLNames;
     39 
     40 HTMLOptGroupElement::HTMLOptGroupElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
     41     : HTMLFormControlElement(tagName, doc, f)
     42     , m_style(0)
     43 {
     44     ASSERT(hasTagName(optgroupTag));
     45 }
     46 
     47 bool HTMLOptGroupElement::supportsFocus() const
     48 {
     49     return HTMLElement::supportsFocus();
     50 }
     51 
     52 bool HTMLOptGroupElement::isFocusable() const
     53 {
     54     // Optgroup elements do not have a renderer so we check the renderStyle instead.
     55     return supportsFocus() && renderStyle() && renderStyle()->display() != NONE;
     56 }
     57 
     58 const AtomicString& HTMLOptGroupElement::formControlType() const
     59 {
     60     DEFINE_STATIC_LOCAL(const AtomicString, optgroup, ("optgroup"));
     61     return optgroup;
     62 }
     63 
     64 bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
     65 {
     66     bool result = HTMLFormControlElement::insertBefore(newChild, refChild, ec, shouldLazyAttach);
     67     return result;
     68 }
     69 
     70 bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
     71 {
     72     bool result = HTMLFormControlElement::replaceChild(newChild, oldChild, ec, shouldLazyAttach);
     73     return result;
     74 }
     75 
     76 bool HTMLOptGroupElement::removeChild(Node* oldChild, ExceptionCode& ec)
     77 {
     78     bool result = HTMLFormControlElement::removeChild(oldChild, ec);
     79     return result;
     80 }
     81 
     82 bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
     83 {
     84     bool result = HTMLFormControlElement::appendChild(newChild, ec, shouldLazyAttach);
     85     return result;
     86 }
     87 
     88 bool HTMLOptGroupElement::removeChildren()
     89 {
     90     bool result = HTMLFormControlElement::removeChildren();
     91     return result;
     92 }
     93 
     94 void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
     95 {
     96     recalcSelectOptions();
     97     HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
     98 }
     99 
    100 void HTMLOptGroupElement::parseMappedAttribute(MappedAttribute* attr)
    101 {
    102     HTMLFormControlElement::parseMappedAttribute(attr);
    103     recalcSelectOptions();
    104 }
    105 
    106 void HTMLOptGroupElement::recalcSelectOptions()
    107 {
    108     Node* select = parentNode();
    109     while (select && !select->hasTagName(selectTag))
    110         select = select->parentNode();
    111     if (select)
    112         static_cast<HTMLSelectElement*>(select)->setRecalcListItems();
    113 }
    114 
    115 String HTMLOptGroupElement::label() const
    116 {
    117     return getAttribute(labelAttr);
    118 }
    119 
    120 void HTMLOptGroupElement::setLabel(const String &value)
    121 {
    122     setAttribute(labelAttr, value);
    123 }
    124 
    125 bool HTMLOptGroupElement::checkDTD(const Node* newChild)
    126 {
    127     // Make sure to keep this in sync with <select> (other than not allowing an optgroup).
    128     return newChild->isTextNode() || newChild->hasTagName(HTMLNames::optionTag) || newChild->hasTagName(HTMLNames::hrTag) || newChild->hasTagName(HTMLNames::scriptTag);
    129 }
    130 
    131 void HTMLOptGroupElement::attach()
    132 {
    133     if (parentNode()->renderStyle())
    134         setRenderStyle(styleForRenderer());
    135     HTMLFormControlElement::attach();
    136 }
    137 
    138 void HTMLOptGroupElement::detach()
    139 {
    140     m_style.clear();
    141     HTMLFormControlElement::detach();
    142 }
    143 
    144 void HTMLOptGroupElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle)
    145 {
    146     m_style = newStyle;
    147 }
    148 
    149 RenderStyle* HTMLOptGroupElement::nonRendererRenderStyle() const
    150 {
    151     return m_style.get();
    152 }
    153 
    154 String HTMLOptGroupElement::groupLabelText() const
    155 {
    156     String itemText = document()->displayStringModifiedByEncoding(getAttribute(labelAttr));
    157 
    158     // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
    159     itemText = itemText.stripWhiteSpace();
    160     // We want to collapse our whitespace too.  This will match other browsers.
    161     itemText = itemText.simplifyWhiteSpace();
    162 
    163     return itemText;
    164 }
    165 
    166 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const
    167 {
    168     Node* select = parentNode();
    169     while (select && !select->hasTagName(selectTag))
    170         select = select->parentNode();
    171 
    172     if (!select)
    173        return 0;
    174 
    175     return static_cast<HTMLSelectElement*>(select);
    176 }
    177 
    178 void HTMLOptGroupElement::accessKeyAction(bool)
    179 {
    180     HTMLSelectElement* select = ownerSelectElement();
    181     // send to the parent to bring focus to the list box
    182     if (select && !select->focused())
    183         select->accessKeyAction(false);
    184 }
    185 
    186 } // namespace
    187