Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: Source/WebCore/html/HTMLOptGroupElement.cpp

Issue 14096013: Implement select element list box with shadow DOM. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@shadowselect
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "HTMLOptGroupElement.h" 26 #include "HTMLOptGroupElement.h"
27 27
28 #include "Document.h" 28 #include "Document.h"
29 #include "HTMLContentElement.h"
30 #include "HTMLDivElement.h"
29 #include "HTMLNames.h" 31 #include "HTMLNames.h"
30 #include "HTMLSelectElement.h" 32 #include "HTMLSelectElement.h"
31 #include "RenderMenuList.h" 33 #include "RenderMenuList.h"
32 #include "NodeRenderStyle.h" 34 #include "NodeRenderStyle.h"
33 #include "NodeRenderingContext.h" 35 #include "NodeRenderingContext.h"
34 #include "StyleResolver.h" 36 #include "StyleResolver.h"
37 #include "Text.h"
35 #include <wtf/StdLibExtras.h> 38 #include <wtf/StdLibExtras.h>
39 #include <wtf/unicode/CharacterNames.h>
36 40
37 namespace WebCore { 41 namespace WebCore {
38 42
39 using namespace HTMLNames; 43 using namespace HTMLNames;
40 44
45 class GroupLabelElement : public HTMLDivElement {
46 public:
47 static PassRefPtr<GroupLabelElement> create(Document*);
48
49 private:
50 GroupLabelElement(Document* document)
51 : HTMLDivElement(HTMLNames::divTag, document)
52 {
53 setHasCustomStyleCallbacks();
54 }
55 virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
56 };
57
58 PassRefPtr<GroupLabelElement> GroupLabelElement::create(Document* document)
59 {
60 return adoptRef(new GroupLabelElement(document));
61 }
62
63 PassRefPtr<RenderStyle> GroupLabelElement::customStyleForRenderer()
64 {
65 RefPtr<RenderStyle> originalStyle = document()->styleResolver()->styleForEle ment(this);
66 RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
67
68 style->setPaddingRight(Length(2, Fixed));
69 style->setPaddingLeft(Length(2, Fixed));
70
71 int paddingBottom = 1;
72 HTMLSelectElement* selectElement = toHTMLOptGroupElement(shadowHost())->owne rSelectElement();
73 if (selectElement) {
74 const Vector<HTMLElement*>& items = selectElement->listItems();
75 if (items[items.size() - 1] == this)
76 paddingBottom = 0;
77 }
78 style->setPaddingBottom(Length(paddingBottom, Fixed));
79
80 return style.release();
81 }
82
41 inline HTMLOptGroupElement::HTMLOptGroupElement(const QualifiedName& tagName, Do cument* document) 83 inline HTMLOptGroupElement::HTMLOptGroupElement(const QualifiedName& tagName, Do cument* document)
42 : HTMLElement(tagName, document) 84 : HTMLElement(tagName, document)
43 { 85 {
44 ASSERT(hasTagName(optgroupTag)); 86 ASSERT(hasTagName(optgroupTag));
45 setHasCustomStyleCallbacks(); 87 setHasCustomStyleCallbacks();
46 ScriptWrappable::init(this); 88 ScriptWrappable::init(this);
47 } 89 }
48 90
49 PassRefPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(const QualifiedName& tagName, Document* document) 91 PassRefPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(const QualifiedName& tagName, Document* document)
50 { 92 {
51 return adoptRef(new HTMLOptGroupElement(tagName, document)); 93 RefPtr<HTMLOptGroupElement> optGroup = adoptRef(new HTMLOptGroupElement(tagN ame, document));
94 optGroup->ensureUserAgentShadowRoot();
95 return optGroup.release();
52 } 96 }
53 97
54 bool HTMLOptGroupElement::isDisabledFormControl() const 98 bool HTMLOptGroupElement::isDisabledFormControl() const
55 { 99 {
56 return fastHasAttribute(disabledAttr); 100 return fastHasAttribute(disabledAttr);
57 } 101 }
58 102
59 bool HTMLOptGroupElement::supportsFocus() const 103 bool HTMLOptGroupElement::supportsFocus() const
60 { 104 {
61 return HTMLElement::supportsFocus(); 105 return HTMLElement::supportsFocus();
(...skipping 17 matching lines...) Expand all
79 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi ldCountDelta); 123 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi ldCountDelta);
80 } 124 }
81 125
82 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic String& value) 126 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic String& value)
83 { 127 {
84 HTMLElement::parseAttribute(name, value); 128 HTMLElement::parseAttribute(name, value);
85 recalcSelectOptions(); 129 recalcSelectOptions();
86 130
87 if (name == disabledAttr) 131 if (name == disabledAttr)
88 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); 132 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled);
133 else if (name == labelAttr)
134 updateGroupLabel();
89 } 135 }
90 136
91 void HTMLOptGroupElement::recalcSelectOptions() 137 void HTMLOptGroupElement::recalcSelectOptions()
92 { 138 {
93 ContainerNode* select = parentNode(); 139 ContainerNode* select = parentNode();
94 while (select && !select->hasTagName(selectTag)) 140 while (select && !select->hasTagName(selectTag))
95 select = select->parentNode(); 141 select = select->parentNode();
96 if (select) 142 if (select)
97 toHTMLSelectElement(select)->setRecalcListItems(); 143 toHTMLSelectElement(select)->setRecalcListItems();
98 } 144 }
99 145
100 void HTMLOptGroupElement::attach()
101 {
102 HTMLElement::attach();
103 // If after attaching nothing called styleForRenderer() on this node we
104 // manually cache the value. This happens if our parent doesn't have a
105 // renderer like <optgroup> or if it doesn't allow children like <select>.
106 if (!m_style && parentNode()->renderStyle())
107 updateNonRenderStyle();
108 }
109
110 void HTMLOptGroupElement::detach()
111 {
112 m_style.clear();
113 HTMLElement::detach();
114 }
115
116 void HTMLOptGroupElement::updateNonRenderStyle()
117 {
118 m_style = document()->styleResolver()->styleForElement(this);
119 }
120
121 RenderStyle* HTMLOptGroupElement::nonRendererStyle() const
122 {
123 return m_style.get();
124 }
125
126 PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer()
127 {
128 // styleForRenderer is called whenever a new style should be associated
129 // with an Element so now is a good time to update our cached style.
130 updateNonRenderStyle();
131 return m_style;
132 }
133
134 String HTMLOptGroupElement::groupLabelText() const 146 String HTMLOptGroupElement::groupLabelText() const
135 { 147 {
136 String itemText = document()->displayStringModifiedByEncoding(getAttribute(l abelAttr)); 148 String itemText = document()->displayStringModifiedByEncoding(getAttribute(l abelAttr));
137 149
138 // In WinIE, leading and trailing whitespace is ignored in options and optgr oups. We match this behavior. 150 // In WinIE, leading and trailing whitespace is ignored in options and optgr oups. We match this behavior.
139 itemText = itemText.stripWhiteSpace(); 151 itemText = itemText.stripWhiteSpace();
140 // We want to collapse our whitespace too. This will match other browsers. 152 // We want to collapse our whitespace too. This will match other browsers.
141 itemText = itemText.simplifyWhiteSpace(); 153 itemText = itemText.simplifyWhiteSpace();
142 154
143 return itemText; 155 return itemText;
(...skipping 12 matching lines...) Expand all
156 } 168 }
157 169
158 void HTMLOptGroupElement::accessKeyAction(bool) 170 void HTMLOptGroupElement::accessKeyAction(bool)
159 { 171 {
160 HTMLSelectElement* select = ownerSelectElement(); 172 HTMLSelectElement* select = ownerSelectElement();
161 // send to the parent to bring focus to the list box 173 // send to the parent to bring focus to the list box
162 if (select && !select->focused()) 174 if (select && !select->focused())
163 select->accessKeyAction(false); 175 select->accessKeyAction(false);
164 } 176 }
165 177
178 void HTMLOptGroupElement::didAddUserAgentShadowRoot(ShadowRoot* root)
179 {
180 RefPtr<GroupLabelElement> groupLabelElement = GroupLabelElement::create(docu ment());
181 groupLabelElement->appendChild(Text::create(document(), "TEST"), ASSERT_NO_E XCEPTION);
182 root->appendChild(groupLabelElement);
183 m_groupLabelElement = groupLabelElement.get();
184
185 RefPtr<HTMLContentElement> content = HTMLContentElement::create(document());
186 content->setAttribute(selectAttr, "option");
187 root->appendChild(content);
188
189 updateGroupLabel();
190 }
191
192 void HTMLOptGroupElement::updateGroupLabel()
193 {
194 DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1));
195 String labelText = groupLabelText();
196 if (labelText.isEmpty())
197 labelText = nonBreakingSpaceString;
198 Text* const textNode = toText(userAgentShadowRoot()->firstChild()->firstChil d());
199 ASSERT(textNode);
200 if (!textNode)
201 return;
202 textNode->replaceWholeText(labelText, ASSERT_NO_EXCEPTION);
203 }
204
205 HTMLOptGroupElement* toHTMLOptGroupElement(Node* node)
206 {
207 ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(optgroupTag));
208 return static_cast<HTMLOptGroupElement*>(node);
209 }
210
166 } // namespace 211 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698