diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/html/HTMLOptionElement.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/html/HTMLOptionElement.cpp')
-rw-r--r-- | Source/WebCore/html/HTMLOptionElement.cpp | 157 |
1 files changed, 60 insertions, 97 deletions
diff --git a/Source/WebCore/html/HTMLOptionElement.cpp b/Source/WebCore/html/HTMLOptionElement.cpp index f5049b674..8fbe51edb 100644 --- a/Source/WebCore/html/HTMLOptionElement.cpp +++ b/Source/WebCore/html/HTMLOptionElement.cpp @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * (C) 2006 Alexey Proskuryakov (ap@nypop.com) - * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * Copyright (C) 2010 Google Inc. All rights reserved. * Copyright (C) 2011 Motorola Mobility, Inc. All rights reserved. * @@ -27,9 +27,7 @@ #include "config.h" #include "HTMLOptionElement.h" -#include "Attribute.h" #include "Document.h" -#include "ExceptionCode.h" #include "HTMLDataListElement.h" #include "HTMLNames.h" #include "HTMLOptGroupElement.h" @@ -57,79 +55,62 @@ HTMLOptionElement::HTMLOptionElement(const QualifiedName& tagName, Document& doc setHasCustomStyleResolveCallbacks(); } -PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(Document& document) +Ref<HTMLOptionElement> HTMLOptionElement::create(Document& document) { - return adoptRef(new HTMLOptionElement(optionTag, document)); + return adoptRef(*new HTMLOptionElement(optionTag, document)); } -PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(const QualifiedName& tagName, Document& document) +Ref<HTMLOptionElement> HTMLOptionElement::create(const QualifiedName& tagName, Document& document) { - return adoptRef(new HTMLOptionElement(tagName, document)); + return adoptRef(*new HTMLOptionElement(tagName, document)); } -PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document& document, const String& data, const String& value, - bool defaultSelected, bool selected, ExceptionCode& ec) +ExceptionOr<Ref<HTMLOptionElement>> HTMLOptionElement::createForJSConstructor(Document& document, + const String& data, const String& value, bool defaultSelected, bool selected) { - RefPtr<HTMLOptionElement> element = adoptRef(new HTMLOptionElement(optionTag, document)); + Ref<HTMLOptionElement> element = adoptRef(*new HTMLOptionElement(optionTag, document)); - RefPtr<Text> text = Text::create(document, data.isNull() ? "" : data); + auto text = Text::create(document, data.isNull() ? emptyString() : data); - ec = 0; - element->appendChild(text.release(), ec); - if (ec) - return 0; + auto appendResult = element->appendChild(text); + if (appendResult.hasException()) + return appendResult.releaseException(); if (!value.isNull()) element->setValue(value); if (defaultSelected) - element->setAttribute(selectedAttr, emptyAtom); + element->setAttributeWithoutSynchronization(selectedAttr, emptyAtom); element->setSelected(selected); - return element.release(); + return WTFMove(element); } -void HTMLOptionElement::didAttachRenderers() +bool HTMLOptionElement::isFocusable() const { - // If after attaching nothing called styleForRenderer() on this node we - // manually cache the value. This happens if our parent doesn't have a - // renderer like <optgroup> or if it doesn't allow children like <select>. - if (!m_style && parentNode()->renderStyle()) - updateNonRenderStyle(); + if (!supportsFocus()) + return false; + // Option elements do not have a renderer. + auto* style = const_cast<HTMLOptionElement&>(*this).computedStyle(); + return style && style->display() != NONE; } -void HTMLOptionElement::willDetachRenderers() +bool HTMLOptionElement::matchesDefaultPseudoClass() const { - m_style.clear(); -} - -bool HTMLOptionElement::isFocusable() const -{ - // Option elements do not have a renderer so we check the renderStyle instead. - return supportsFocus() && renderStyle() && renderStyle()->display() != NONE; + return hasAttributeWithoutSynchronization(selectedAttr); } String HTMLOptionElement::text() const { - String text; - - // WinIE does not use the label attribute, so as a quirk, we ignore it. - if (!document().inQuirksMode()) - text = fastGetAttribute(labelAttr); - - // FIXME: The following treats an element with the label attribute set to - // the empty string the same as an element with no label attribute at all. - // Is that correct? If it is, then should the label function work the same way? - if (text.isEmpty()) - text = collectOptionInnerText(); + String text = collectOptionInnerText(); // FIXME: Is displayStringModifiedByEncoding helpful here? // If it's correct here, then isn't it needed in the value and label functions too? return document().displayStringModifiedByEncoding(text).stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace); } -void HTMLOptionElement::setText(const String &text, ExceptionCode& ec) +void HTMLOptionElement::setText(const String &text) { - Ref<HTMLOptionElement> protectFromMutationEvents(*this); + Ref<HTMLOptionElement> protectedThis(*this); // Changing the text causes a recalc of a select's items, which will reset the selected // index to the first item if the select is single selection with a menu list. We attempt to @@ -140,11 +121,11 @@ void HTMLOptionElement::setText(const String &text, ExceptionCode& ec) // Handle the common special case where there's exactly 1 child node, and it's a text node. Node* child = firstChild(); - if (child && child->isTextNode() && !child->nextSibling()) - toText(child)->setData(text, ec); + if (is<Text>(child) && !child->nextSibling()) + downcast<Text>(*child).setData(text); else { removeChildren(); - appendChild(Text::create(document(), text), ec); + appendChild(Text::create(document(), text)); } if (selectIsMenuList && select->selectedIndex() != oldSelectedIndex) @@ -168,12 +149,10 @@ int HTMLOptionElement::index() const int optionIndex = 0; - const Vector<HTMLElement*>& items = selectElement->listItems(); - size_t length = items.size(); - for (size_t i = 0; i < length; ++i) { - if (!isHTMLOptionElement(items[i])) + for (auto& item : selectElement->listItems()) { + if (!is<HTMLOptionElement>(*item)) continue; - if (items[i] == this) + if (item == this) return optionIndex; ++optionIndex; } @@ -193,11 +172,13 @@ void HTMLOptionElement::parseAttribute(const QualifiedName& name, const AtomicSt bool oldDisabled = m_disabled; m_disabled = !value.isNull(); if (oldDisabled != m_disabled) { - didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); + invalidateStyleForSubtree(); if (renderer() && renderer()->style().hasAppearance()) - renderer()->theme().stateChanged(renderer(), EnabledState); + renderer()->theme().stateChanged(*renderer(), ControlStates::EnabledState); } } else if (name == selectedAttr) { + invalidateStyleForSubtree(); + // FIXME: This doesn't match what the HTML specification says. // The specification implies that removing the selected attribute or // changing the value of a selected attribute that is already present @@ -211,7 +192,7 @@ void HTMLOptionElement::parseAttribute(const QualifiedName& name, const AtomicSt String HTMLOptionElement::value() const { - const AtomicString& value = fastGetAttribute(valueAttr); + const AtomicString& value = attributeWithoutSynchronization(valueAttr); if (!value.isNull()) return value; return collectOptionInnerText().stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace); @@ -219,7 +200,7 @@ String HTMLOptionElement::value() const void HTMLOptionElement::setValue(const String& value) { - setAttribute(valueAttr, value); + setAttributeWithoutSynchronization(valueAttr, value); } bool HTMLOptionElement::selected() @@ -237,7 +218,7 @@ void HTMLOptionElement::setSelected(bool selected) setSelectedState(selected); if (HTMLSelectElement* select = ownerSelectElement()) - select->optionSelectionStateChanged(this, selected); + select->optionSelectionStateChanged(*this, selected); } void HTMLOptionElement::setSelectedState(bool selected) @@ -246,7 +227,7 @@ void HTMLOptionElement::setSelectedState(bool selected) return; m_isSelected = selected; - didAffectSelector(AffectedSelectorChecked); + invalidateStyleForSubtree(); if (HTMLSelectElement* select = ownerSelectElement()) select->invalidateSelectedItems(); @@ -268,57 +249,39 @@ void HTMLOptionElement::childrenChanged(const ChildChange& change) HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const { for (ContainerNode* parent = parentNode(); parent ; parent = parent->parentNode()) { - if (parent->hasTagName(datalistTag)) - return toHTMLDataListElement(parent); + if (is<HTMLDataListElement>(*parent)) + return downcast<HTMLDataListElement>(parent); } - return 0; + return nullptr; } #endif HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const { ContainerNode* select = parentNode(); - while (select && !select->hasTagName(selectTag)) + while (select && !is<HTMLSelectElement>(*select)) select = select->parentNode(); if (!select) - return 0; + return nullptr; - return toHTMLSelectElement(select); + return downcast<HTMLSelectElement>(select); } String HTMLOptionElement::label() const { - const AtomicString& label = fastGetAttribute(labelAttr); + String label = attributeWithoutSynchronization(labelAttr); if (!label.isNull()) - return label; + return label.stripWhiteSpace(isHTMLSpace); return collectOptionInnerText().stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace); } void HTMLOptionElement::setLabel(const String& label) { - setAttribute(labelAttr, label); -} - -void HTMLOptionElement::updateNonRenderStyle() -{ - m_style = document().ensureStyleResolver().styleForElement(this); -} - -RenderStyle* HTMLOptionElement::nonRendererStyle() const -{ - return m_style.get(); -} - -PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer() -{ - // styleForRenderer is called whenever a new style should be associated - // with an Element so now is a good time to update our cached style. - updateNonRenderStyle(); - return m_style; + setAttributeWithoutSynchronization(labelAttr, label); } -void HTMLOptionElement::didRecalcStyle(Style::Change) +void HTMLOptionElement::willResetComputedStyle() { // FIXME: This is nasty, we ask our owner select to repaint even if the new // style is exactly the same. @@ -331,9 +294,9 @@ void HTMLOptionElement::didRecalcStyle(Style::Change) String HTMLOptionElement::textIndentedToRespectGroupLabel() const { ContainerNode* parent = parentNode(); - if (parent && isHTMLOptGroupElement(parent)) - return " " + text(); - return text(); + if (is<HTMLOptGroupElement>(parent)) + return " " + label(); + return label(); } bool HTMLOptionElement::isDisabledFormControl() const @@ -341,23 +304,23 @@ bool HTMLOptionElement::isDisabledFormControl() const if (ownElementDisabled()) return true; - if (!parentNode() || !parentNode()->isHTMLElement()) + if (!is<HTMLOptGroupElement>(parentNode())) return false; - HTMLElement& parentElement = toHTMLElement(*parentNode()); - return isHTMLOptGroupElement(parentElement) && parentElement.isDisabledFormControl(); + return downcast<HTMLOptGroupElement>(*parentNode()).isDisabledFormControl(); } Node::InsertionNotificationRequest HTMLOptionElement::insertedInto(ContainerNode& insertionPoint) { if (HTMLSelectElement* select = ownerSelectElement()) { select->setRecalcListItems(); + select->updateValidity(); // Do not call selected() since calling updateListItemSelectedStates() // at this time won't do the right thing. (Why, exactly?) // FIXME: Might be better to call this unconditionally, always passing m_isSelected, // rather than only calling it if we are selected. if (m_isSelected) - select->optionSelectionStateChanged(this, true); + select->optionSelectionStateChanged(*this, true); select->scrollToSelection(); } @@ -368,13 +331,13 @@ String HTMLOptionElement::collectOptionInnerText() const { StringBuilder text; for (Node* node = firstChild(); node; ) { - if (node->isTextNode()) + if (is<Text>(*node)) text.append(node->nodeValue()); // Text nodes inside script elements are not part of the option text. - if (node->isElementNode() && toScriptElementIfPossible(toElement(node))) - node = NodeTraversal::nextSkippingChildren(node, this); + if (is<Element>(*node) && isScriptElement(downcast<Element>(*node))) + node = NodeTraversal::nextSkippingChildren(*node, this); else - node = NodeTraversal::next(node, this); + node = NodeTraversal::next(*node, this); } return text.toString(); } |