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 |