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

Side by Side Diff: Source/core/html/HTMLOptionElement.cpp

Issue 347773002: Implement select listbox using shadow DOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: gixed slow select-max-length.html Created 6 years, 6 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 | Annotate | Revision Log
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 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 5 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
6 * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved. 7 * Copyright (C) 2010 Google Inc. All rights reserved.
8 * Copyright (C) 2011 Motorola Mobility, Inc. All rights reserved. 8 * Copyright (C) 2011 Motorola Mobility, Inc. All rights reserved.
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 16 matching lines...) Expand all
27 #include "config.h" 27 #include "config.h"
28 #include "core/html/HTMLOptionElement.h" 28 #include "core/html/HTMLOptionElement.h"
29 29
30 #include "bindings/v8/ExceptionState.h" 30 #include "bindings/v8/ExceptionState.h"
31 #include "core/HTMLNames.h" 31 #include "core/HTMLNames.h"
32 #include "core/dom/Document.h" 32 #include "core/dom/Document.h"
33 #include "core/dom/NodeRenderStyle.h" 33 #include "core/dom/NodeRenderStyle.h"
34 #include "core/dom/NodeTraversal.h" 34 #include "core/dom/NodeTraversal.h"
35 #include "core/dom/ScriptLoader.h" 35 #include "core/dom/ScriptLoader.h"
36 #include "core/dom/Text.h" 36 #include "core/dom/Text.h"
37 #include "core/dom/shadow/ShadowRoot.h"
37 #include "core/html/HTMLDataListElement.h" 38 #include "core/html/HTMLDataListElement.h"
39 #include "core/html/HTMLOptGroupElement.h"
38 #include "core/html/HTMLSelectElement.h" 40 #include "core/html/HTMLSelectElement.h"
39 #include "core/html/parser/HTMLParserIdioms.h" 41 #include "core/html/parser/HTMLParserIdioms.h"
40 #include "core/rendering/RenderTheme.h" 42 #include "core/rendering/RenderTheme.h"
41 #include "wtf/Vector.h" 43 #include "wtf/Vector.h"
42 #include "wtf/text/StringBuilder.h" 44 #include "wtf/text/StringBuilder.h"
43 45
44 namespace WebCore { 46 namespace WebCore {
45 47
46 using namespace HTMLNames; 48 using namespace HTMLNames;
47 49
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } 92 }
91 93
92 void HTMLOptionElement::detach(const AttachContext& context) 94 void HTMLOptionElement::detach(const AttachContext& context)
93 { 95 {
94 m_style.clear(); 96 m_style.clear();
95 HTMLElement::detach(context); 97 HTMLElement::detach(context);
96 } 98 }
97 99
98 bool HTMLOptionElement::rendererIsFocusable() const 100 bool HTMLOptionElement::rendererIsFocusable() const
99 { 101 {
100 // Option elements do not have a renderer so we check the renderStyle instea d. 102 HTMLSelectElement* selectElement = ownerSelectElement();
101 return renderStyle() && renderStyle()->display() != NONE; 103 if (!selectElement || selectElement->usesMenuList()) {
104 return !isDisplayNone();
105 }
106 return HTMLElement::rendererIsFocusable();
102 } 107 }
103 108
104 String HTMLOptionElement::text() const 109 String HTMLOptionElement::text() const
105 { 110 {
106 Document& document = this->document(); 111 Document& document = this->document();
107 String text; 112 String text;
108 113
109 // WinIE does not use the label attribute, so as a quirk, we ignore it. 114 // WinIE does not use the label attribute, so as a quirk, we ignore it.
110 if (!document.inQuirksMode()) 115 if (!document.inQuirksMode())
111 text = fastGetAttribute(labelAttr); 116 text = fastGetAttribute(labelAttr);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 bool oldDisabled = m_disabled; 186 bool oldDisabled = m_disabled;
182 m_disabled = !value.isNull(); 187 m_disabled = !value.isNull();
183 if (oldDisabled != m_disabled) { 188 if (oldDisabled != m_disabled) {
184 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled ); 189 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled );
185 if (renderer() && renderer()->style()->hasAppearance()) 190 if (renderer() && renderer()->style()->hasAppearance())
186 RenderTheme::theme().stateChanged(renderer(), EnabledControlStat e); 191 RenderTheme::theme().stateChanged(renderer(), EnabledControlStat e);
187 } 192 }
188 } else if (name == selectedAttr) { 193 } else if (name == selectedAttr) {
189 if (bool willBeSelected = !value.isNull()) 194 if (bool willBeSelected = !value.isNull())
190 setSelected(willBeSelected); 195 setSelected(willBeSelected);
196 } else if (name == labelAttr) {
197 updateLabel();
191 } else 198 } else
192 HTMLElement::parseAttribute(name, value); 199 HTMLElement::parseAttribute(name, value);
193 } 200 }
194 201
195 String HTMLOptionElement::value() const 202 String HTMLOptionElement::value() const
196 { 203 {
197 const AtomicString& value = fastGetAttribute(valueAttr); 204 const AtomicString& value = fastGetAttribute(valueAttr);
198 if (!value.isNull()) 205 if (!value.isNull())
199 return value; 206 return value;
200 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>); 207 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 if (HTMLSelectElement* select = ownerSelectElement()) 251 if (HTMLSelectElement* select = ownerSelectElement())
245 select->invalidateSelectedItems(); 252 select->invalidateSelectedItems();
246 } 253 }
247 254
248 void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange , Node* afterChange, int childCountDelta) 255 void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange , Node* afterChange, int childCountDelta)
249 { 256 {
250 if (HTMLDataListElement* dataList = ownerDataListElement()) 257 if (HTMLDataListElement* dataList = ownerDataListElement())
251 dataList->optionElementChildrenChanged(); 258 dataList->optionElementChildrenChanged();
252 else if (HTMLSelectElement* select = ownerSelectElement()) 259 else if (HTMLSelectElement* select = ownerSelectElement())
253 select->optionElementChildrenChanged(); 260 select->optionElementChildrenChanged();
261 updateLabel();
254 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi ldCountDelta); 262 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi ldCountDelta);
255 } 263 }
256 264
257 HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const 265 HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const
258 { 266 {
259 return Traversal<HTMLDataListElement>::firstAncestor(*this); 267 return Traversal<HTMLDataListElement>::firstAncestor(*this);
260 } 268 }
261 269
262 HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const 270 HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const
263 { 271 {
264 return Traversal<HTMLSelectElement>::firstAncestor(*this); 272 return Traversal<HTMLSelectElement>::firstAncestor(*this);
265 } 273 }
266 274
267 String HTMLOptionElement::label() const 275 String HTMLOptionElement::label() const
268 { 276 {
269 const AtomicString& label = fastGetAttribute(labelAttr); 277 const AtomicString& label = fastGetAttribute(labelAttr);
270 if (!label.isNull()) 278 if (!label.isNull())
271 return label; 279 return label;
272 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>); 280 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>);
273 } 281 }
274 282
275 void HTMLOptionElement::setLabel(const AtomicString& label) 283 void HTMLOptionElement::setLabel(const AtomicString& label)
276 { 284 {
277 setAttribute(labelAttr, label); 285 setAttribute(labelAttr, label);
278 } 286 }
279 287
288 bool HTMLOptionElement::rendererIsNeeded(const RenderStyle&)
289 {
290 HTMLSelectElement* select = ownerSelectElement();
291 return select && !select->usesMenuList() && !isDisplayNone();
esprehn 2014/06/23 21:59:56 ditto
keishi 2014/07/01 04:53:32 Done.
292 }
293
280 void HTMLOptionElement::updateNonRenderStyle() 294 void HTMLOptionElement::updateNonRenderStyle()
281 { 295 {
282 bool oldDisplayNoneStatus = isDisplayNone(); 296 bool oldDisplayNoneStatus = isDisplayNone();
283 m_style = originalStyleForRenderer(); 297 m_style = originalStyleForRenderer();
284 if (oldDisplayNoneStatus != isDisplayNone()) { 298 if (oldDisplayNoneStatus != isDisplayNone()) {
285 if (HTMLSelectElement* select = ownerSelectElement()) 299 if (HTMLSelectElement* select = ownerSelectElement())
286 select->updateListOnRenderer(); 300 select->updateListOnRenderer();
287 } 301 }
288 } 302 }
289 303
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 { 336 {
323 if (ownElementDisabled()) 337 if (ownElementDisabled())
324 return true; 338 return true;
325 if (Element* parent = parentElement()) 339 if (Element* parent = parentElement())
326 return isHTMLOptGroupElement(*parent) && parent->isDisabledFormControl() ; 340 return isHTMLOptGroupElement(*parent) && parent->isDisabledFormControl() ;
327 return false; 341 return false;
328 } 342 }
329 343
330 Node::InsertionNotificationRequest HTMLOptionElement::insertedInto(ContainerNode * insertionPoint) 344 Node::InsertionNotificationRequest HTMLOptionElement::insertedInto(ContainerNode * insertionPoint)
331 { 345 {
346 HTMLElement::insertedInto(insertionPoint);
332 if (HTMLSelectElement* select = ownerSelectElement()) { 347 if (HTMLSelectElement* select = ownerSelectElement()) {
333 select->setRecalcListItems(); 348 select->setRecalcListItems();
334 // Do not call selected() since calling updateListItemSelectedStates() 349 // Do not call selected() since calling updateListItemSelectedStates()
335 // at this time won't do the right thing. (Why, exactly?) 350 // at this time won't do the right thing. (Why, exactly?)
336 // FIXME: Might be better to call this unconditionally, always passing m _isSelected, 351 // FIXME: Might be better to call this unconditionally, always passing m _isSelected,
337 // rather than only calling it if we are selected. 352 // rather than only calling it if we are selected.
338 if (m_isSelected) 353 if (m_isSelected)
339 select->optionSelectionStateChanged(this, true); 354 select->optionSelectionStateChanged(this, true);
340 select->scrollToSelection(); 355 select->scrollToSelection();
341 } 356 }
357 return insertionPoint->inDocument() ? InsertionShouldCallDidNotifySubtreeIns ertions : InsertionDone;
358 }
342 359
343 return HTMLElement::insertedInto(insertionPoint); 360 void HTMLOptionElement::didNotifySubtreeInsertionsToDocument()
361 {
362 updateView();
363 }
364
365 void HTMLOptionElement::updateView()
366 {
367 HTMLSelectElement* select = ownerSelectElement();
368 if (select && !select->usesMenuList())
369 ensureUserAgentShadowRoot();
370 else if (userAgentShadowRoot() && document().lifecycle().stateAllowsDetach() )
esprehn 2014/06/23 21:59:56 ditto
keishi 2014/07/01 04:53:32 Done.
371 userAgentShadowRoot()->detach();
372 }
373
374 void HTMLOptionElement::removedFrom(ContainerNode* insertionPoint)
375 {
376 HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestorOrSel f(*insertionPoint);
377 if (select)
378 return select->optionRemoved(this);
379 HTMLElement::removedFrom(insertionPoint);
344 } 380 }
345 381
346 String HTMLOptionElement::collectOptionInnerText() const 382 String HTMLOptionElement::collectOptionInnerText() const
347 { 383 {
348 StringBuilder text; 384 StringBuilder text;
349 for (Node* node = firstChild(); node; ) { 385 for (Node* node = firstChild(); node; ) {
350 if (node->isTextNode()) 386 if (node->isTextNode())
351 text.append(node->nodeValue()); 387 text.append(node->nodeValue());
352 // Text nodes inside script elements are not part of the option text. 388 // Text nodes inside script elements are not part of the option text.
353 if (node->isElementNode() && toScriptLoaderIfPossible(toElement(node))) 389 if (node->isElementNode() && toScriptLoaderIfPossible(toElement(node)))
(...skipping 17 matching lines...) Expand all
371 ContainerNode* parent = parentNode(); 407 ContainerNode* parent = parentNode();
372 // Check for parent optgroup having display NONE 408 // Check for parent optgroup having display NONE
373 if (parent && isHTMLOptGroupElement(*parent)) { 409 if (parent && isHTMLOptGroupElement(*parent)) {
374 if (toHTMLOptGroupElement(*parent).isDisplayNone()) 410 if (toHTMLOptGroupElement(*parent).isDisplayNone())
375 return true; 411 return true;
376 } 412 }
377 RenderStyle* style = nonRendererStyle(); 413 RenderStyle* style = nonRendererStyle();
378 return style && style->display() == NONE; 414 return style && style->display() == NONE;
379 } 415 }
380 416
417 void HTMLOptionElement::didAddUserAgentShadowRoot(ShadowRoot& root)
418 {
419 updateLabel();
420 }
421
422 void HTMLOptionElement::updateLabel()
423 {
424 ShadowRoot* root = userAgentShadowRoot();
425 if (!root)
426 return;
427 Text* const textNode = toText(root->firstChild());
428 if (textNode)
429 textNode->replaceWholeText(textIndentedToRespectGroupLabel());
430 else
431 root->appendChild(Text::create(document(), textIndentedToRespectGroupLab el()), ASSERT_NO_EXCEPTION);
esprehn 2014/06/23 21:59:56 ditto.
keishi 2014/07/01 04:53:32 Done.
432 }
433
381 } // namespace WebCore 434 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698