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 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
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.
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.
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.
26 #include "core/html/HTMLOptGroupElement.h"
28 #include "core/HTMLNames.h"
29 #include "core/dom/NodeComputedStyle.h"
30 #include "core/dom/Text.h"
31 #include "core/editing/EditingUtilities.h"
32 #include "core/html/HTMLContentElement.h"
33 #include "core/html/HTMLDivElement.h"
34 #include "core/html/HTMLSelectElement.h"
35 #include "core/html/shadow/ShadowElementNames.h"
36 #include "wtf/StdLibExtras.h"
37 #include "wtf/text/CharacterNames.h"
41 using namespace HTMLNames
;
43 inline HTMLOptGroupElement::HTMLOptGroupElement(Document
& document
)
44 : HTMLElement(optgroupTag
, document
)
46 setHasCustomStyleCallbacks();
49 PassRefPtrWillBeRawPtr
<HTMLOptGroupElement
> HTMLOptGroupElement::create(Document
& document
)
51 RefPtrWillBeRawPtr
<HTMLOptGroupElement
> optGroupElement
= adoptRefWillBeNoop(new HTMLOptGroupElement(document
));
52 optGroupElement
->ensureUserAgentShadowRoot();
53 return optGroupElement
.release();
56 bool HTMLOptGroupElement::isDisabledFormControl() const
58 return fastHasAttribute(disabledAttr
);
61 void HTMLOptGroupElement::childrenChanged(const ChildrenChange
& change
)
63 recalcSelectOptions();
64 HTMLElement::childrenChanged(change
);
67 void HTMLOptGroupElement::parseAttribute(const QualifiedName
& name
, const AtomicString
& value
)
69 HTMLElement::parseAttribute(name
, value
);
70 recalcSelectOptions();
72 if (name
== disabledAttr
) {
73 pseudoStateChanged(CSSSelector::PseudoDisabled
);
74 pseudoStateChanged(CSSSelector::PseudoEnabled
);
75 } else if (name
== labelAttr
) {
80 void HTMLOptGroupElement::recalcSelectOptions()
82 if (HTMLSelectElement
* select
= Traversal
<HTMLSelectElement
>::firstAncestor(*this))
83 select
->setRecalcListItems();
86 void HTMLOptGroupElement::attach(const AttachContext
& context
)
88 if (context
.resolvedStyle
) {
89 ASSERT(!m_style
|| m_style
== context
.resolvedStyle
);
90 m_style
= context
.resolvedStyle
;
92 HTMLElement::attach(context
);
95 void HTMLOptGroupElement::detach(const AttachContext
& context
)
98 HTMLElement::detach(context
);
101 bool HTMLOptGroupElement::supportsFocus() const
103 RefPtrWillBeRawPtr
<HTMLSelectElement
> select
= ownerSelectElement();
104 if (select
&& select
->usesMenuList())
106 return HTMLElement::supportsFocus();
109 void HTMLOptGroupElement::updateNonComputedStyle()
111 m_style
= originalStyleForLayoutObject();
112 if (layoutObject()) {
113 if (HTMLSelectElement
* select
= ownerSelectElement())
114 select
->updateListOnLayoutObject();
118 ComputedStyle
* HTMLOptGroupElement::nonLayoutObjectComputedStyle() const
120 return m_style
.get();
123 PassRefPtr
<ComputedStyle
> HTMLOptGroupElement::customStyleForLayoutObject()
125 updateNonComputedStyle();
129 String
HTMLOptGroupElement::groupLabelText() const
131 String itemText
= getAttribute(labelAttr
);
133 // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
134 itemText
= itemText
.stripWhiteSpace();
135 // We want to collapse our whitespace too. This will match other browsers.
136 itemText
= itemText
.simplifyWhiteSpace();
141 HTMLSelectElement
* HTMLOptGroupElement::ownerSelectElement() const
143 return Traversal
<HTMLSelectElement
>::firstAncestor(*this);
146 void HTMLOptGroupElement::accessKeyAction(bool)
148 HTMLSelectElement
* select
= ownerSelectElement();
149 // send to the parent to bring focus to the list box
150 if (select
&& !select
->focused())
151 select
->accessKeyAction(false);
154 void HTMLOptGroupElement::didAddUserAgentShadowRoot(ShadowRoot
& root
)
156 DEFINE_STATIC_LOCAL(AtomicString
, labelPadding
, ("0 2px 1px 2px", AtomicString::ConstructFromLiteral
));
157 DEFINE_STATIC_LOCAL(AtomicString
, labelMinHeight
, ("1.2em", AtomicString::ConstructFromLiteral
));
158 RefPtrWillBeRawPtr
<HTMLDivElement
> label
= HTMLDivElement::create(document());
159 label
->setAttribute(roleAttr
, AtomicString("group", AtomicString::ConstructFromLiteral
));
160 label
->setAttribute(aria_labelAttr
, AtomicString());
161 label
->setInlineStyleProperty(CSSPropertyPadding
, labelPadding
);
162 label
->setInlineStyleProperty(CSSPropertyMinHeight
, labelMinHeight
);
163 label
->setIdAttribute(ShadowElementNames::optGroupLabel());
164 root
.appendChild(label
);
166 RefPtrWillBeRawPtr
<HTMLContentElement
> content
= HTMLContentElement::create(document());
167 content
->setAttribute(selectAttr
, "option,hr");
168 root
.appendChild(content
);
171 void HTMLOptGroupElement::updateGroupLabel()
173 const String
& labelText
= groupLabelText();
174 HTMLDivElement
& label
= optGroupLabelElement();
175 label
.setTextContent(labelText
);
176 label
.setAttribute(aria_labelAttr
, AtomicString(labelText
));
179 HTMLDivElement
& HTMLOptGroupElement::optGroupLabelElement() const
181 return *toHTMLDivElement(userAgentShadowRoot()->getElementById(ShadowElementNames::optGroupLabel()));