1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. 6 * (C) 2006 Alexey Proskuryakov (ap (at) 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 "core/html/HTMLOptGroupElement.h" 27 28 #include "core/HTMLNames.h" 29 #include "core/dom/Document.h" 30 #include "core/dom/NodeRenderStyle.h" 31 #include "core/html/HTMLSelectElement.h" 32 #include "wtf/StdLibExtras.h" 33 34 namespace WebCore { 35 36 using namespace HTMLNames; 37 38 inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) 39 : HTMLElement(optgroupTag, document) 40 { 41 setHasCustomStyleCallbacks(); 42 ScriptWrappable::init(this); 43 } 44 45 DEFINE_NODE_FACTORY(HTMLOptGroupElement) 46 47 bool HTMLOptGroupElement::isDisabledFormControl() const 48 { 49 return fastHasAttribute(disabledAttr); 50 } 51 52 bool HTMLOptGroupElement::rendererIsFocusable() const 53 { 54 // Optgroup elements do not have a renderer so we check the renderStyle instead. 55 return renderStyle() && renderStyle()->display() != NONE; 56 } 57 58 void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 59 { 60 recalcSelectOptions(); 61 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 62 } 63 64 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 65 { 66 HTMLElement::parseAttribute(name, value); 67 recalcSelectOptions(); 68 69 if (name == disabledAttr) 70 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); 71 } 72 73 void HTMLOptGroupElement::recalcSelectOptions() 74 { 75 if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestor(*this)) 76 select->setRecalcListItems(); 77 } 78 79 void HTMLOptGroupElement::attach(const AttachContext& context) 80 { 81 if (context.resolvedStyle) { 82 ASSERT(!m_style || m_style == context.resolvedStyle); 83 m_style = context.resolvedStyle; 84 } 85 HTMLElement::attach(context); 86 } 87 88 void HTMLOptGroupElement::detach(const AttachContext& context) 89 { 90 m_style.clear(); 91 HTMLElement::detach(context); 92 } 93 94 void HTMLOptGroupElement::updateNonRenderStyle() 95 { 96 bool oldDisplayNoneStatus = isDisplayNone(); 97 m_style = originalStyleForRenderer(); 98 if (oldDisplayNoneStatus != isDisplayNone()) { 99 if (HTMLSelectElement* select = ownerSelectElement()) 100 select->updateListOnRenderer(); 101 } 102 } 103 104 RenderStyle* HTMLOptGroupElement::nonRendererStyle() const 105 { 106 return m_style.get(); 107 } 108 109 PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer() 110 { 111 updateNonRenderStyle(); 112 return m_style; 113 } 114 115 String HTMLOptGroupElement::groupLabelText() const 116 { 117 String itemText = getAttribute(labelAttr); 118 119 // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. 120 itemText = itemText.stripWhiteSpace(); 121 // We want to collapse our whitespace too. This will match other browsers. 122 itemText = itemText.simplifyWhiteSpace(); 123 124 return itemText; 125 } 126 127 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const 128 { 129 return Traversal<HTMLSelectElement>::firstAncestor(*this); 130 } 131 132 void HTMLOptGroupElement::accessKeyAction(bool) 133 { 134 HTMLSelectElement* select = ownerSelectElement(); 135 // send to the parent to bring focus to the list box 136 if (select && !select->focused()) 137 select->accessKeyAction(false); 138 } 139 140 bool HTMLOptGroupElement::isDisplayNone() const 141 { 142 RenderStyle* style = nonRendererStyle(); 143 return style && style->display() == NONE; 144 } 145 146 } // namespace 147