Chromium Code Reviews| 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 * (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 Loading... | |
| 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/core/v8/ExceptionState.h" | 30 #include "bindings/core/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 |
| 48 HTMLOptionElement::HTMLOptionElement(Document& document) | 50 HTMLOptionElement::HTMLOptionElement(Document& document) |
| 49 : HTMLElement(optionTag, document) | 51 : HTMLElement(optionTag, document) |
| 50 , m_disabled(false) | 52 , m_disabled(false) |
| 51 , m_isSelected(false) | 53 , m_isSelected(false) |
| 52 { | 54 { |
| 53 setHasCustomStyleCallbacks(); | 55 setHasCustomStyleCallbacks(); |
| 54 ScriptWrappable::init(this); | 56 ScriptWrappable::init(this); |
| 55 } | 57 } |
| 56 | 58 |
| 57 PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::create(Document& do cument) | 59 PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::create(Document& do cument) |
| 58 { | 60 { |
| 59 return adoptRefWillBeNoop(new HTMLOptionElement(document)); | 61 RefPtrWillBeRawPtr<HTMLOptionElement> option = adoptRefWillBeNoop(new HTMLOp tionElement(document)); |
| 62 option->ensureUserAgentShadowRoot(); | |
| 63 return option.release(); | |
| 60 } | 64 } |
| 61 | 65 |
| 62 PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstruc tor(Document& document, const String& data, const AtomicString& value, | 66 PassRefPtrWillBeRawPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstruc tor(Document& document, const String& data, const AtomicString& value, |
| 63 bool defaultSelected, bool selected, ExceptionState& exceptionState) | 67 bool defaultSelected, bool selected, ExceptionState& exceptionState) |
| 64 { | 68 { |
| 65 RefPtrWillBeRawPtr<HTMLOptionElement> element = adoptRefWillBeNoop(new HTMLO ptionElement(document)); | 69 RefPtrWillBeRawPtr<HTMLOptionElement> element = adoptRefWillBeNoop(new HTMLO ptionElement(document)); |
| 70 element->ensureUserAgentShadowRoot(); | |
| 66 element->appendChild(Text::create(document, data.isNull() ? "" : data), exce ptionState); | 71 element->appendChild(Text::create(document, data.isNull() ? "" : data), exce ptionState); |
| 67 if (exceptionState.hadException()) | 72 if (exceptionState.hadException()) |
| 68 return nullptr; | 73 return nullptr; |
| 69 | 74 |
| 70 if (!value.isNull()) | 75 if (!value.isNull()) |
| 71 element->setValue(value); | 76 element->setValue(value); |
| 72 if (defaultSelected) | 77 if (defaultSelected) |
| 73 element->setAttribute(selectedAttr, emptyAtom); | 78 element->setAttribute(selectedAttr, emptyAtom); |
| 74 element->setSelected(selected); | 79 element->setSelected(selected); |
| 75 | 80 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 88 } | 93 } |
| 89 HTMLElement::attach(optionContext); | 94 HTMLElement::attach(optionContext); |
| 90 } | 95 } |
| 91 | 96 |
| 92 void HTMLOptionElement::detach(const AttachContext& context) | 97 void HTMLOptionElement::detach(const AttachContext& context) |
| 93 { | 98 { |
| 94 m_style.clear(); | 99 m_style.clear(); |
| 95 HTMLElement::detach(context); | 100 HTMLElement::detach(context); |
| 96 } | 101 } |
| 97 | 102 |
| 98 bool HTMLOptionElement::rendererIsFocusable() const | |
| 99 { | |
| 100 // Option elements do not have a renderer so we check the renderStyle instea d. | |
| 101 return renderStyle() && renderStyle()->display() != NONE; | |
| 102 } | |
| 103 | |
| 104 String HTMLOptionElement::text() const | 103 String HTMLOptionElement::text() const |
| 105 { | 104 { |
| 106 Document& document = this->document(); | 105 Document& document = this->document(); |
| 107 String text; | 106 String text; |
| 108 | 107 |
| 109 // WinIE does not use the label attribute, so as a quirk, we ignore it. | 108 // WinIE does not use the label attribute, so as a quirk, we ignore it. |
| 110 if (!document.inQuirksMode()) | 109 if (!document.inQuirksMode()) |
| 111 text = fastGetAttribute(labelAttr); | 110 text = fastGetAttribute(labelAttr); |
| 112 | 111 |
| 113 // FIXME: The following treats an element with the label attribute set to | 112 // FIXME: The following treats an element with the label attribute set to |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 bool oldDisabled = m_disabled; | 180 bool oldDisabled = m_disabled; |
| 182 m_disabled = !value.isNull(); | 181 m_disabled = !value.isNull(); |
| 183 if (oldDisabled != m_disabled) { | 182 if (oldDisabled != m_disabled) { |
| 184 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled ); | 183 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled ); |
| 185 if (renderer() && renderer()->style()->hasAppearance()) | 184 if (renderer() && renderer()->style()->hasAppearance()) |
| 186 RenderTheme::theme().stateChanged(renderer(), EnabledControlStat e); | 185 RenderTheme::theme().stateChanged(renderer(), EnabledControlStat e); |
| 187 } | 186 } |
| 188 } else if (name == selectedAttr) { | 187 } else if (name == selectedAttr) { |
| 189 if (bool willBeSelected = !value.isNull()) | 188 if (bool willBeSelected = !value.isNull()) |
| 190 setSelected(willBeSelected); | 189 setSelected(willBeSelected); |
| 190 } else if (name == labelAttr) { | |
| 191 updateLabel(); | |
| 191 } else | 192 } else |
| 192 HTMLElement::parseAttribute(name, value); | 193 HTMLElement::parseAttribute(name, value); |
| 193 } | 194 } |
| 194 | 195 |
| 195 String HTMLOptionElement::value() const | 196 String HTMLOptionElement::value() const |
| 196 { | 197 { |
| 197 const AtomicString& value = fastGetAttribute(valueAttr); | 198 const AtomicString& value = fastGetAttribute(valueAttr); |
| 198 if (!value.isNull()) | 199 if (!value.isNull()) |
| 199 return value; | 200 return value; |
| 200 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>); | 201 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 if (HTMLSelectElement* select = ownerSelectElement()) | 245 if (HTMLSelectElement* select = ownerSelectElement()) |
| 245 select->invalidateSelectedItems(); | 246 select->invalidateSelectedItems(); |
| 246 } | 247 } |
| 247 | 248 |
| 248 void HTMLOptionElement::childrenChanged(const ChildrenChange& change) | 249 void HTMLOptionElement::childrenChanged(const ChildrenChange& change) |
| 249 { | 250 { |
| 250 if (HTMLDataListElement* dataList = ownerDataListElement()) | 251 if (HTMLDataListElement* dataList = ownerDataListElement()) |
| 251 dataList->optionElementChildrenChanged(); | 252 dataList->optionElementChildrenChanged(); |
| 252 else if (HTMLSelectElement* select = ownerSelectElement()) | 253 else if (HTMLSelectElement* select = ownerSelectElement()) |
| 253 select->optionElementChildrenChanged(); | 254 select->optionElementChildrenChanged(); |
| 255 updateLabel(); | |
| 254 HTMLElement::childrenChanged(change); | 256 HTMLElement::childrenChanged(change); |
| 255 } | 257 } |
| 256 | 258 |
| 257 HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const | 259 HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const |
| 258 { | 260 { |
| 259 return Traversal<HTMLDataListElement>::firstAncestor(*this); | 261 return Traversal<HTMLDataListElement>::firstAncestor(*this); |
| 260 } | 262 } |
| 261 | 263 |
| 262 HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const | 264 HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const |
| 263 { | 265 { |
| 264 return Traversal<HTMLSelectElement>::firstAncestor(*this); | 266 return Traversal<HTMLSelectElement>::firstAncestor(*this); |
| 265 } | 267 } |
| 266 | 268 |
| 267 String HTMLOptionElement::label() const | 269 String HTMLOptionElement::label() const |
| 268 { | 270 { |
| 269 const AtomicString& label = fastGetAttribute(labelAttr); | 271 const AtomicString& label = fastGetAttribute(labelAttr); |
| 270 if (!label.isNull()) | 272 if (!label.isNull()) |
| 271 return label; | 273 return label; |
| 272 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>); | 274 return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplify WhiteSpace(isHTMLSpace<UChar>); |
| 273 } | 275 } |
| 274 | 276 |
| 275 void HTMLOptionElement::setLabel(const AtomicString& label) | 277 void HTMLOptionElement::setLabel(const AtomicString& label) |
| 276 { | 278 { |
| 277 setAttribute(labelAttr, label); | 279 setAttribute(labelAttr, label); |
| 278 } | 280 } |
| 279 | 281 |
| 280 void HTMLOptionElement::updateNonRenderStyle() | 282 void HTMLOptionElement::updateNonRenderStyle() |
| 281 { | 283 { |
| 282 bool oldDisplayNoneStatus = isDisplayNone(); | |
| 283 m_style = originalStyleForRenderer(); | 284 m_style = originalStyleForRenderer(); |
| 284 if (oldDisplayNoneStatus != isDisplayNone()) { | 285 if (HTMLSelectElement* select = ownerSelectElement()) |
| 285 if (HTMLSelectElement* select = ownerSelectElement()) | 286 select->updateListOnRenderer(); |
| 286 select->updateListOnRenderer(); | |
| 287 } | |
| 288 } | 287 } |
| 289 | 288 |
| 290 RenderStyle* HTMLOptionElement::nonRendererStyle() const | 289 RenderStyle* HTMLOptionElement::nonRendererStyle() const |
| 291 { | 290 { |
| 292 return m_style.get(); | 291 return m_style.get(); |
| 293 } | 292 } |
| 294 | 293 |
| 295 PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer() | 294 PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer() |
| 296 { | 295 { |
| 297 updateNonRenderStyle(); | 296 updateNonRenderStyle(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 // FIXME: Might be better to call this unconditionally, always passing m _isSelected, | 335 // FIXME: Might be better to call this unconditionally, always passing m _isSelected, |
| 337 // rather than only calling it if we are selected. | 336 // rather than only calling it if we are selected. |
| 338 if (m_isSelected) | 337 if (m_isSelected) |
| 339 select->optionSelectionStateChanged(this, true); | 338 select->optionSelectionStateChanged(this, true); |
| 340 select->scrollToSelection(); | 339 select->scrollToSelection(); |
| 341 } | 340 } |
| 342 | 341 |
| 343 return HTMLElement::insertedInto(insertionPoint); | 342 return HTMLElement::insertedInto(insertionPoint); |
| 344 } | 343 } |
| 345 | 344 |
| 345 void HTMLOptionElement::removedFrom(ContainerNode* insertionPoint) | |
| 346 { | |
| 347 HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestorOrSel f(*insertionPoint); | |
|
tkent
2014/07/08 02:20:59
nit: You can write this as:
if (HTMLSelectElement*
keishi
2014/07/10 09:48:03
Done.
| |
| 348 if (select) | |
| 349 return select->optionRemoved(this); | |
|
tkent
2014/07/08 02:20:59
This is weird for void function.
Also, should we c
keishi
2014/07/10 09:48:03
Done.
| |
| 350 HTMLElement::removedFrom(insertionPoint); | |
| 351 } | |
| 352 | |
| 346 String HTMLOptionElement::collectOptionInnerText() const | 353 String HTMLOptionElement::collectOptionInnerText() const |
| 347 { | 354 { |
| 348 StringBuilder text; | 355 StringBuilder text; |
| 349 for (Node* node = firstChild(); node; ) { | 356 for (Node* node = firstChild(); node; ) { |
| 350 if (node->isTextNode()) | 357 if (node->isTextNode()) |
| 351 text.append(node->nodeValue()); | 358 text.append(node->nodeValue()); |
| 352 // Text nodes inside script elements are not part of the option text. | 359 // Text nodes inside script elements are not part of the option text. |
| 353 if (node->isElementNode() && toScriptLoaderIfPossible(toElement(node))) | 360 if (node->isElementNode() && toScriptLoaderIfPossible(toElement(node))) |
| 354 node = NodeTraversal::nextSkippingChildren(*node, this); | 361 node = NodeTraversal::nextSkippingChildren(*node, this); |
| 355 else | 362 else |
| 356 node = NodeTraversal::next(*node, this); | 363 node = NodeTraversal::next(*node, this); |
| 357 } | 364 } |
| 358 return text.toString(); | 365 return text.toString(); |
| 359 } | 366 } |
| 360 | 367 |
| 361 HTMLFormElement* HTMLOptionElement::form() const | 368 HTMLFormElement* HTMLOptionElement::form() const |
| 362 { | 369 { |
| 363 if (HTMLSelectElement* selectElement = ownerSelectElement()) | 370 if (HTMLSelectElement* selectElement = ownerSelectElement()) |
| 364 return selectElement->formOwner(); | 371 return selectElement->formOwner(); |
| 365 | 372 |
| 366 return 0; | 373 return 0; |
| 367 } | 374 } |
| 368 | 375 |
| 369 bool HTMLOptionElement::isDisplayNone() const | 376 void HTMLOptionElement::didAddUserAgentShadowRoot(ShadowRoot& root) |
| 370 { | 377 { |
| 371 ContainerNode* parent = parentNode(); | 378 updateLabel(); |
| 372 // Check for parent optgroup having display NONE | 379 } |
| 373 if (parent && isHTMLOptGroupElement(*parent)) { | 380 |
| 374 if (toHTMLOptGroupElement(*parent).isDisplayNone()) | 381 void HTMLOptionElement::updateLabel() |
| 375 return true; | 382 { |
| 376 } | 383 ShadowRoot* root = userAgentShadowRoot(); |
|
tkent
2014/07/08 02:20:59
nit: You can write this as:
if (ShadowRoot* root =
keishi
2014/07/10 09:48:03
Done.
| |
| 377 RenderStyle* style = nonRendererStyle(); | 384 if (!root) |
| 378 return style && style->display() == NONE; | 385 return; |
| 386 root->setTextContent(textIndentedToRespectGroupLabel()); | |
| 387 } | |
| 388 | |
| 389 bool HTMLOptionElement::spatialNavigationFocused() const | |
| 390 { | |
| 391 HTMLSelectElement* select = ownerSelectElement(); | |
| 392 if (!select || !select->focused()) | |
| 393 return false; | |
| 394 return select->spatialNavigationFocusedOption() == this; | |
| 379 } | 395 } |
| 380 | 396 |
| 381 } // namespace WebCore | 397 } // namespace WebCore |
| OLD | NEW |