This source file includes following definitions.
- m_isSelected
 
- create
 
- createForJSConstructor
 
- attach
 
- detach
 
- rendererIsFocusable
 
- text
 
- setText
 
- accessKeyAction
 
- index
 
- parseAttribute
 
- value
 
- setValue
 
- selected
 
- setSelected
 
- setSelectedState
 
- childrenChanged
 
- ownerDataListElement
 
- ownerSelectElement
 
- label
 
- setLabel
 
- updateNonRenderStyle
 
- nonRendererStyle
 
- customStyleForRenderer
 
- didRecalcStyle
 
- textIndentedToRespectGroupLabel
 
- isDisabledFormControl
 
- insertedInto
 
- collectOptionInnerText
 
- form
 
#include "config.h"
#include "core/html/HTMLOptionElement.h"
#include "HTMLNames.h"
#include "bindings/v8/ExceptionState.h"
#include "core/dom/Document.h"
#include "core/dom/NodeRenderStyle.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/ScriptLoader.h"
#include "core/dom/Text.h"
#include "core/html/HTMLDataListElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/rendering/RenderTheme.h"
#include "wtf/Vector.h"
#include "wtf/text/StringBuilder.h"
namespace WebCore {
using namespace HTMLNames;
HTMLOptionElement::HTMLOptionElement(Document& document)
    : HTMLElement(optionTag, document)
    , m_disabled(false)
    , m_isSelected(false)
{
    setHasCustomStyleCallbacks();
    ScriptWrappable::init(this);
}
PassRefPtr<HTMLOptionElement> HTMLOptionElement::create(Document& document)
{
    return adoptRef(new HTMLOptionElement(document));
}
PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document& document, const String& data, const AtomicString& value,
    bool defaultSelected, bool selected, ExceptionState& exceptionState)
{
    RefPtr<HTMLOptionElement> element = adoptRef(new HTMLOptionElement(document));
    RefPtr<Text> text = Text::create(document, data.isNull() ? "" : data);
    element->appendChild(text.release(), exceptionState);
    if (exceptionState.hadException())
        return nullptr;
    if (!value.isNull())
        element->setValue(value);
    if (defaultSelected)
        element->setAttribute(selectedAttr, emptyAtom);
    element->setSelected(selected);
    return element.release();
}
void HTMLOptionElement::attach(const AttachContext& context)
{
    AttachContext optionContext(context);
    if (context.resolvedStyle) {
        ASSERT(!m_style || m_style == context.resolvedStyle);
        m_style = context.resolvedStyle;
    } else {
        updateNonRenderStyle();
        optionContext.resolvedStyle = m_style.get();
    }
    HTMLElement::attach(optionContext);
}
void HTMLOptionElement::detach(const AttachContext& context)
{
    m_style.clear();
    HTMLElement::detach(context);
}
bool HTMLOptionElement::rendererIsFocusable() const
{
    
    return renderStyle() && renderStyle()->display() != NONE;
}
String HTMLOptionElement::text() const
{
    Document& document = this->document();
    String text;
    
    if (!document.inQuirksMode())
        text = fastGetAttribute(labelAttr);
    
    
    
    if (text.isEmpty())
        text = collectOptionInnerText();
    return text.stripWhiteSpace(isHTMLSpace<UChar>).simplifyWhiteSpace(isHTMLSpace<UChar>);
}
void HTMLOptionElement::setText(const String &text, ExceptionState& exceptionState)
{
    RefPtr<Node> protectFromMutationEvents(this);
    
    
    
    RefPtr<HTMLSelectElement> select = ownerSelectElement();
    bool selectIsMenuList = select && select->usesMenuList();
    int oldSelectedIndex = selectIsMenuList ? select->selectedIndex() : -1;
    
    Node* child = firstChild();
    if (child && child->isTextNode() && !child->nextSibling())
        toText(child)->setData(text);
    else {
        removeChildren();
        appendChild(Text::create(document(), text), exceptionState);
    }
    if (selectIsMenuList && select->selectedIndex() != oldSelectedIndex)
        select->setSelectedIndex(oldSelectedIndex);
}
void HTMLOptionElement::accessKeyAction(bool)
{
    if (HTMLSelectElement* select = ownerSelectElement())
        select->accessKeySetSelectedIndex(index());
}
int HTMLOptionElement::index() const
{
    
    HTMLSelectElement* selectElement = ownerSelectElement();
    if (!selectElement)
        return 0;
    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]))
            continue;
        if (items[i] == this)
            return optionIndex;
        ++optionIndex;
    }
    return 0;
}
void HTMLOptionElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    if (name == valueAttr) {
        if (HTMLDataListElement* dataList = ownerDataListElement())
            dataList->optionElementChildrenChanged();
    } else if (name == disabledAttr) {
        bool oldDisabled = m_disabled;
        m_disabled = !value.isNull();
        if (oldDisabled != m_disabled) {
            didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled);
            if (renderer() && renderer()->style()->hasAppearance())
                RenderTheme::theme().stateChanged(renderer(), EnabledState);
        }
    } else if (name == selectedAttr) {
        if (bool willBeSelected = !value.isNull())
            setSelected(willBeSelected);
    } else
        HTMLElement::parseAttribute(name, value);
}
String HTMLOptionElement::value() const
{
    const AtomicString& value = fastGetAttribute(valueAttr);
    if (!value.isNull())
        return value;
    return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplifyWhiteSpace(isHTMLSpace<UChar>);
}
void HTMLOptionElement::setValue(const AtomicString& value)
{
    setAttribute(valueAttr, value);
}
bool HTMLOptionElement::selected() const
{
    if (HTMLSelectElement* select = ownerSelectElement()) {
        
        
        
        
        
        
        
        if (!select->isFinishedParsingChildren())
            return m_isSelected;
        select->updateListItemSelectedStates();
    }
    return m_isSelected;
}
void HTMLOptionElement::setSelected(bool selected)
{
    if (m_isSelected == selected)
        return;
    setSelectedState(selected);
    if (HTMLSelectElement* select = ownerSelectElement())
        select->optionSelectionStateChanged(this, selected);
}
void HTMLOptionElement::setSelectedState(bool selected)
{
    if (m_isSelected == selected)
        return;
    m_isSelected = selected;
    didAffectSelector(AffectedSelectorChecked);
    if (HTMLSelectElement* select = ownerSelectElement())
        select->invalidateSelectedItems();
}
void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
    if (HTMLDataListElement* dataList = ownerDataListElement())
        dataList->optionElementChildrenChanged();
    else if (HTMLSelectElement* select = ownerSelectElement())
        select->optionElementChildrenChanged();
    HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
}
HTMLDataListElement* HTMLOptionElement::ownerDataListElement() const
{
    return Traversal<HTMLDataListElement>::firstAncestor(*this);
}
HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const
{
    return Traversal<HTMLSelectElement>::firstAncestor(*this);
}
String HTMLOptionElement::label() const
{
    const AtomicString& label = fastGetAttribute(labelAttr);
    if (!label.isNull())
        return label;
    return collectOptionInnerText().stripWhiteSpace(isHTMLSpace<UChar>).simplifyWhiteSpace(isHTMLSpace<UChar>);
}
void HTMLOptionElement::setLabel(const AtomicString& label)
{
    setAttribute(labelAttr, label);
}
void HTMLOptionElement::updateNonRenderStyle()
{
    m_style = originalStyleForRenderer();
}
RenderStyle* HTMLOptionElement::nonRendererStyle() const
{
    return m_style.get();
}
PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer()
{
    updateNonRenderStyle();
    return m_style;
}
void HTMLOptionElement::didRecalcStyle(StyleRecalcChange change)
{
    if (change == NoChange)
        return;
    
    if (HTMLSelectElement* select = ownerSelectElement()) {
        if (RenderObject* renderer = select->renderer())
            renderer->repaint();
    }
}
String HTMLOptionElement::textIndentedToRespectGroupLabel() const
{
    ContainerNode* parent = parentNode();
    if (parent && isHTMLOptGroupElement(*parent))
        return "    " + text();
    return text();
}
bool HTMLOptionElement::isDisabledFormControl() const
{
    if (ownElementDisabled())
        return true;
    if (Element* parent = parentElement())
        return isHTMLOptGroupElement(*parent) && parent->isDisabledFormControl();
    return false;
}
Node::InsertionNotificationRequest HTMLOptionElement::insertedInto(ContainerNode* insertionPoint)
{
    if (HTMLSelectElement* select = ownerSelectElement()) {
        select->setRecalcListItems();
        
        
        
        
        if (m_isSelected)
            select->optionSelectionStateChanged(this, true);
        select->scrollToSelection();
    }
    return HTMLElement::insertedInto(insertionPoint);
}
String HTMLOptionElement::collectOptionInnerText() const
{
    StringBuilder text;
    for (Node* node = firstChild(); node; ) {
        if (node->isTextNode())
            text.append(node->nodeValue());
        
        if (node->isElementNode() && toScriptLoaderIfPossible(toElement(node)))
            node = NodeTraversal::nextSkippingChildren(*node, this);
        else
            node = NodeTraversal::next(*node, this);
    }
    return text.toString();
}
HTMLFormElement* HTMLOptionElement::form() const
{
    if (HTMLSelectElement* selectElement = ownerSelectElement())
        return selectElement->formOwner();
    return 0;
}
}