15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *           (C) 1999 Antti Koivisto (koivisto@kde.org)
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *           (C) 2001 Dirk Mueller (mueller@kde.org)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLOptGroupElement.h"
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "HTMLNames.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/NodeRenderStyle.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLSelectElement.h"
32e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "wtf/StdLibExtras.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline HTMLOptGroupElement::HTMLOptGroupElement(const QualifiedName& tagName, Document* document)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : HTMLElement(tagName, document)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(hasTagName(optgroupTag));
42926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setHasCustomStyleCallbacks();
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ScriptWrappable::init(this);
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(const QualifiedName& tagName, Document* document)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new HTMLOptGroupElement(tagName, document));
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool HTMLOptGroupElement::isDisabledFormControl() const
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fastHasAttribute(disabledAttr);
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
56521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)bool HTMLOptGroupElement::rendererIsFocusable() const
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Optgroup elements do not have a renderer so we check the renderStyle instead.
59521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return renderStyle() && renderStyle()->display() != NONE;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const AtomicString& HTMLOptGroupElement::formControlType() const
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const AtomicString, optgroup, ("optgroup", AtomicString::ConstructFromLiteral));
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return optgroup;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    recalcSelectOptions();
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    HTMLElement::parseAttribute(name, value);
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    recalcSelectOptions();
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (name == disabledAttr)
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled);
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void HTMLOptGroupElement::recalcSelectOptions()
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ContainerNode* select = parentNode();
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (select && !select->hasTagName(selectTag))
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        select = select->parentNode();
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (select)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        toHTMLSelectElement(select)->setRecalcListItems();
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
92521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void HTMLOptGroupElement::attach(const AttachContext& context)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
94521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    HTMLElement::attach(context);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If after attaching nothing called styleForRenderer() on this node we
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // manually cache the value. This happens if our parent doesn't have a
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // renderer like <optgroup> or if it doesn't allow children like <select>.
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_style && parentNode()->renderStyle())
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        updateNonRenderStyle();
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
102521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void HTMLOptGroupElement::detach(const AttachContext& context)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_style.clear();
105521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    HTMLElement::detach(context);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void HTMLOptGroupElement::updateNonRenderStyle()
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    m_style = originalStyleForRenderer();
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderStyle* HTMLOptGroupElement::nonRendererStyle() const
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_style.get();
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer()
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // styleForRenderer is called whenever a new style should be associated
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // with an Element so now is a good time to update our cached style.
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateNonRenderStyle();
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_style;
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String HTMLOptGroupElement::groupLabelText() const
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String itemText = document()->displayStringModifiedByEncoding(getAttribute(labelAttr));
12902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    itemText = itemText.stripWhiteSpace();
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We want to collapse our whitespace too.  This will match other browsers.
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    itemText = itemText.simplifyWhiteSpace();
13402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return itemText;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ContainerNode* select = parentNode();
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (select && !select->hasTagName(selectTag))
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        select = select->parentNode();
14302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!select)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       return 0;
14602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return toHTMLSelectElement(select);
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void HTMLOptGroupElement::accessKeyAction(bool)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HTMLSelectElement* select = ownerSelectElement();
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // send to the parent to bring focus to the list box
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (select && !select->focused())
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        select->accessKeyAction(false);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace
159