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/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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(); | |
| 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 Loading... | |
| 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; | |
|
keishi
2014/06/22 11:59:55
We can't call ensureUserAgentShadow inside inserte
| |
| 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()) | |
|
keishi
2014/06/22 11:59:55
Only create shadow root when shown in a listbox.
| |
| 369 ensureUserAgentShadowRoot(); | |
| 370 else if (userAgentShadowRoot()) | |
| 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 Loading... | |
| 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::updateLabel() | |
| 418 { | |
| 419 ShadowRoot* root = userAgentShadowRoot(); | |
| 420 if (!root) | |
| 421 return; | |
| 422 Text* const textNode = toText(root->firstChild()); | |
| 423 if (textNode) | |
| 424 textNode->replaceWholeText(textIndentedToRespectGroupLabel()); | |
| 425 else | |
| 426 root->appendChild(Text::create(document(), textIndentedToRespectGroupLab el()), ASSERT_NO_EXCEPTION); | |
| 427 } | |
| 428 | |
| 381 } // namespace WebCore | 429 } // namespace WebCore |
| OLD | NEW |