OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. |
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 #include "core/html/HTMLOptGroupElement.h" | 26 #include "core/html/HTMLOptGroupElement.h" |
27 | 27 |
28 #include "core/HTMLNames.h" | 28 #include "core/HTMLNames.h" |
29 #include "core/dom/NodeRenderStyle.h" | 29 #include "core/dom/NodeRenderStyle.h" |
| 30 #include "core/dom/Text.h" |
| 31 #include "core/editing/htmlediting.h" |
| 32 #include "core/html/HTMLContentElement.h" |
| 33 #include "core/html/HTMLDivElement.h" |
30 #include "core/html/HTMLSelectElement.h" | 34 #include "core/html/HTMLSelectElement.h" |
| 35 #include "core/html/shadow/ShadowElementNames.h" |
31 #include "wtf/StdLibExtras.h" | 36 #include "wtf/StdLibExtras.h" |
| 37 #include "wtf/unicode/CharacterNames.h" |
32 | 38 |
33 namespace WebCore { | 39 namespace WebCore { |
34 | 40 |
35 using namespace HTMLNames; | 41 using namespace HTMLNames; |
36 | 42 |
37 inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) | 43 inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) |
38 : HTMLElement(optgroupTag, document) | 44 : HTMLElement(optgroupTag, document) |
39 { | 45 { |
40 setHasCustomStyleCallbacks(); | |
41 ScriptWrappable::init(this); | 46 ScriptWrappable::init(this); |
42 } | 47 } |
43 | 48 |
44 DEFINE_NODE_FACTORY(HTMLOptGroupElement) | 49 PassRefPtrWillBeRawPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(Document
& document) |
| 50 { |
| 51 RefPtrWillBeRawPtr<HTMLOptGroupElement> optGroupElement = adoptRefWillBeNoop
(new HTMLOptGroupElement(document)); |
| 52 optGroupElement->ensureUserAgentShadowRoot(); |
| 53 return optGroupElement.release(); |
| 54 } |
45 | 55 |
46 bool HTMLOptGroupElement::isDisabledFormControl() const | 56 bool HTMLOptGroupElement::isDisabledFormControl() const |
47 { | 57 { |
48 return fastHasAttribute(disabledAttr); | 58 return fastHasAttribute(disabledAttr); |
49 } | 59 } |
50 | 60 |
51 bool HTMLOptGroupElement::rendererIsFocusable() const | |
52 { | |
53 // Optgroup elements do not have a renderer so we check the renderStyle inst
ead. | |
54 return renderStyle() && renderStyle()->display() != NONE; | |
55 } | |
56 | |
57 void HTMLOptGroupElement::childrenChanged(const ChildrenChange& change) | 61 void HTMLOptGroupElement::childrenChanged(const ChildrenChange& change) |
58 { | 62 { |
59 recalcSelectOptions(); | 63 recalcSelectOptions(); |
60 HTMLElement::childrenChanged(change); | 64 HTMLElement::childrenChanged(change); |
61 } | 65 } |
62 | 66 |
63 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic
String& value) | 67 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic
String& value) |
64 { | 68 { |
65 HTMLElement::parseAttribute(name, value); | 69 HTMLElement::parseAttribute(name, value); |
66 recalcSelectOptions(); | 70 recalcSelectOptions(); |
67 | 71 |
68 if (name == disabledAttr) | 72 if (name == disabledAttr) |
69 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); | 73 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); |
| 74 else if (name == labelAttr) |
| 75 updateGroupLabel(); |
70 } | 76 } |
71 | 77 |
72 void HTMLOptGroupElement::recalcSelectOptions() | 78 void HTMLOptGroupElement::recalcSelectOptions() |
73 { | 79 { |
74 if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestor(
*this)) | 80 if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestor(
*this)) |
75 select->setRecalcListItems(); | 81 select->setRecalcListItems(); |
76 } | 82 } |
77 | 83 |
78 void HTMLOptGroupElement::attach(const AttachContext& context) | |
79 { | |
80 if (context.resolvedStyle) { | |
81 ASSERT(!m_style || m_style == context.resolvedStyle); | |
82 m_style = context.resolvedStyle; | |
83 } | |
84 HTMLElement::attach(context); | |
85 } | |
86 | |
87 void HTMLOptGroupElement::detach(const AttachContext& context) | |
88 { | |
89 m_style.clear(); | |
90 HTMLElement::detach(context); | |
91 } | |
92 | |
93 void HTMLOptGroupElement::updateNonRenderStyle() | |
94 { | |
95 bool oldDisplayNoneStatus = isDisplayNone(); | |
96 m_style = originalStyleForRenderer(); | |
97 if (oldDisplayNoneStatus != isDisplayNone()) { | |
98 if (HTMLSelectElement* select = ownerSelectElement()) | |
99 select->updateListOnRenderer(); | |
100 } | |
101 } | |
102 | |
103 RenderStyle* HTMLOptGroupElement::nonRendererStyle() const | |
104 { | |
105 return m_style.get(); | |
106 } | |
107 | |
108 PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer() | |
109 { | |
110 updateNonRenderStyle(); | |
111 return m_style; | |
112 } | |
113 | |
114 String HTMLOptGroupElement::groupLabelText() const | 84 String HTMLOptGroupElement::groupLabelText() const |
115 { | 85 { |
116 String itemText = getAttribute(labelAttr); | 86 String itemText = getAttribute(labelAttr); |
117 | 87 |
118 // In WinIE, leading and trailing whitespace is ignored in options and optgr
oups. We match this behavior. | 88 // In WinIE, leading and trailing whitespace is ignored in options and optgr
oups. We match this behavior. |
119 itemText = itemText.stripWhiteSpace(); | 89 itemText = itemText.stripWhiteSpace(); |
120 // We want to collapse our whitespace too. This will match other browsers. | 90 // We want to collapse our whitespace too. This will match other browsers. |
121 itemText = itemText.simplifyWhiteSpace(); | 91 itemText = itemText.simplifyWhiteSpace(); |
122 | 92 |
123 return itemText; | 93 return itemText; |
124 } | 94 } |
125 | 95 |
126 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const | 96 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const |
127 { | 97 { |
128 return Traversal<HTMLSelectElement>::firstAncestor(*this); | 98 return Traversal<HTMLSelectElement>::firstAncestor(*this); |
129 } | 99 } |
130 | 100 |
131 void HTMLOptGroupElement::accessKeyAction(bool) | 101 void HTMLOptGroupElement::accessKeyAction(bool) |
132 { | 102 { |
133 HTMLSelectElement* select = ownerSelectElement(); | 103 HTMLSelectElement* select = ownerSelectElement(); |
134 // send to the parent to bring focus to the list box | 104 // send to the parent to bring focus to the list box |
135 if (select && !select->focused()) | 105 if (select && !select->focused()) |
136 select->accessKeyAction(false); | 106 select->accessKeyAction(false); |
137 } | 107 } |
138 | 108 |
139 bool HTMLOptGroupElement::isDisplayNone() const | 109 void HTMLOptGroupElement::didAddUserAgentShadowRoot(ShadowRoot& root) |
140 { | 110 { |
141 RenderStyle* style = nonRendererStyle(); | 111 DEFINE_STATIC_LOCAL(AtomicString, labelPadding, ("0 2px 1px 2px", AtomicStri
ng::ConstructFromLiteral)); |
142 return style && style->display() == NONE; | 112 DEFINE_STATIC_LOCAL(AtomicString, labelMinHeight, ("1.2em", AtomicString::Co
nstructFromLiteral)); |
| 113 RefPtrWillBeRawPtr<HTMLDivElement> label = HTMLDivElement::create(document()
); |
| 114 label->setAttribute(roleAttr, AtomicString("group", AtomicString::ConstructF
romLiteral)); |
| 115 label->setAttribute(aria_labelAttr, AtomicString()); |
| 116 label->setInlineStyleProperty(CSSPropertyPadding, labelPadding); |
| 117 label->setInlineStyleProperty(CSSPropertyMinHeight, labelMinHeight); |
| 118 label->setIdAttribute(ShadowElementNames::optGroupLabel()); |
| 119 root.appendChild(label); |
| 120 |
| 121 RefPtrWillBeRawPtr<HTMLContentElement> content = HTMLContentElement::create(
document()); |
| 122 content->setAttribute(selectAttr, "option,optgroup"); |
| 123 root.appendChild(content); |
| 124 } |
| 125 |
| 126 void HTMLOptGroupElement::updateGroupLabel() |
| 127 { |
| 128 const String& labelText = groupLabelText(); |
| 129 HTMLDivElement& label = optGroupLabelElement(); |
| 130 label.setTextContent(labelText); |
| 131 label.setAttribute(aria_labelAttr, AtomicString(labelText)); |
| 132 } |
| 133 |
| 134 HTMLDivElement& HTMLOptGroupElement::optGroupLabelElement() const |
| 135 { |
| 136 return *toHTMLDivElement(userAgentShadowRoot()->getElementById(ShadowElement
Names::optGroupLabel())); |
143 } | 137 } |
144 | 138 |
145 } // namespace | 139 } // namespace |
OLD | NEW |