1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25#include "config.h" 26#include "HTMLOptGroupElement.h" 27 28#include "Document.h" 29#include "HTMLNames.h" 30#include "HTMLSelectElement.h" 31#include "RenderMenuList.h" 32#include "NodeRenderStyle.h" 33#include "NodeRenderingContext.h" 34#include "StyleResolver.h" 35#include <wtf/StdLibExtras.h> 36 37namespace WebCore { 38 39using namespace HTMLNames; 40 41inline HTMLOptGroupElement::HTMLOptGroupElement(const QualifiedName& tagName, Document* document) 42 : HTMLElement(tagName, document) 43{ 44 ASSERT(hasTagName(optgroupTag)); 45 setHasCustomStyleCallbacks(); 46} 47 48PassRefPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(const QualifiedName& tagName, Document* document) 49{ 50 return adoptRef(new HTMLOptGroupElement(tagName, document)); 51} 52 53bool HTMLOptGroupElement::isDisabledFormControl() const 54{ 55 return fastHasAttribute(disabledAttr); 56} 57 58bool HTMLOptGroupElement::supportsFocus() const 59{ 60 return HTMLElement::supportsFocus(); 61} 62 63bool HTMLOptGroupElement::isFocusable() const 64{ 65 // Optgroup elements do not have a renderer so we check the renderStyle instead. 66 return supportsFocus() && renderStyle() && renderStyle()->display() != NONE; 67} 68 69const AtomicString& HTMLOptGroupElement::formControlType() const 70{ 71 DEFINE_STATIC_LOCAL(const AtomicString, optgroup, ("optgroup", AtomicString::ConstructFromLiteral)); 72 return optgroup; 73} 74 75void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 76{ 77 recalcSelectOptions(); 78 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 79} 80 81void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 82{ 83 HTMLElement::parseAttribute(name, value); 84 recalcSelectOptions(); 85 86 if (name == disabledAttr) 87 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); 88} 89 90void HTMLOptGroupElement::recalcSelectOptions() 91{ 92 ContainerNode* select = parentNode(); 93 while (select && !select->hasTagName(selectTag)) 94 select = select->parentNode(); 95 if (select) 96 toHTMLSelectElement(select)->setRecalcListItems(); 97} 98 99void HTMLOptGroupElement::attach(const AttachContext& context) 100{ 101 HTMLElement::attach(context); 102 // If after attaching nothing called styleForRenderer() on this node we 103 // manually cache the value. This happens if our parent doesn't have a 104 // renderer like <optgroup> or if it doesn't allow children like <select>. 105 if (!m_style && parentNode()->renderStyle()) 106 updateNonRenderStyle(); 107} 108 109void HTMLOptGroupElement::detach(const AttachContext& context) 110{ 111 m_style.clear(); 112 HTMLElement::detach(context); 113} 114 115void HTMLOptGroupElement::updateNonRenderStyle() 116{ 117 m_style = document()->ensureStyleResolver()->styleForElement(this); 118} 119 120RenderStyle* HTMLOptGroupElement::nonRendererStyle() const 121{ 122 return m_style.get(); 123} 124 125PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer() 126{ 127 // styleForRenderer is called whenever a new style should be associated 128 // with an Element so now is a good time to update our cached style. 129 updateNonRenderStyle(); 130 return m_style; 131} 132 133String HTMLOptGroupElement::groupLabelText() const 134{ 135 String itemText = document()->displayStringModifiedByEncoding(getAttribute(labelAttr)); 136 137 // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. 138 itemText = itemText.stripWhiteSpace(); 139 // We want to collapse our whitespace too. This will match other browsers. 140 itemText = itemText.simplifyWhiteSpace(); 141 142 return itemText; 143} 144 145HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const 146{ 147 ContainerNode* select = parentNode(); 148 while (select && !select->hasTagName(selectTag)) 149 select = select->parentNode(); 150 151 if (!select) 152 return 0; 153 154 return toHTMLSelectElement(select); 155} 156 157void HTMLOptGroupElement::accessKeyAction(bool) 158{ 159 HTMLSelectElement* select = ownerSelectElement(); 160 // send to the parent to bring focus to the list box 161 if (select && !select->focused()) 162 select->accessKeyAction(false); 163} 164 165} // namespace 166