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 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 "HTMLOptGroupElement.h" 27 28 #include "CSSStyleSelector.h" 29 #include "Document.h" 30 #include "HTMLNames.h" 31 #include "HTMLSelectElement.h" 32 #include "RenderMenuList.h" 33 #include "NodeRenderStyle.h" 34 #include <wtf/StdLibExtras.h> 35 36 namespace WebCore { 37 38 using namespace HTMLNames; 39 40 HTMLOptGroupElement::HTMLOptGroupElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f) 41 : HTMLFormControlElement(tagName, doc, f) 42 , m_style(0) 43 { 44 ASSERT(hasTagName(optgroupTag)); 45 } 46 47 bool HTMLOptGroupElement::supportsFocus() const 48 { 49 return HTMLElement::supportsFocus(); 50 } 51 52 bool HTMLOptGroupElement::isFocusable() const 53 { 54 // Optgroup elements do not have a renderer so we check the renderStyle instead. 55 return supportsFocus() && renderStyle() && renderStyle()->display() != NONE; 56 } 57 58 const AtomicString& HTMLOptGroupElement::formControlType() const 59 { 60 DEFINE_STATIC_LOCAL(const AtomicString, optgroup, ("optgroup")); 61 return optgroup; 62 } 63 64 bool HTMLOptGroupElement::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach) 65 { 66 bool result = HTMLFormControlElement::insertBefore(newChild, refChild, ec, shouldLazyAttach); 67 return result; 68 } 69 70 bool HTMLOptGroupElement::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach) 71 { 72 bool result = HTMLFormControlElement::replaceChild(newChild, oldChild, ec, shouldLazyAttach); 73 return result; 74 } 75 76 bool HTMLOptGroupElement::removeChild(Node* oldChild, ExceptionCode& ec) 77 { 78 bool result = HTMLFormControlElement::removeChild(oldChild, ec); 79 return result; 80 } 81 82 bool HTMLOptGroupElement::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach) 83 { 84 bool result = HTMLFormControlElement::appendChild(newChild, ec, shouldLazyAttach); 85 return result; 86 } 87 88 bool HTMLOptGroupElement::removeChildren() 89 { 90 bool result = HTMLFormControlElement::removeChildren(); 91 return result; 92 } 93 94 void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 95 { 96 recalcSelectOptions(); 97 HTMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 98 } 99 100 void HTMLOptGroupElement::parseMappedAttribute(MappedAttribute* attr) 101 { 102 HTMLFormControlElement::parseMappedAttribute(attr); 103 recalcSelectOptions(); 104 } 105 106 void HTMLOptGroupElement::recalcSelectOptions() 107 { 108 Node* select = parentNode(); 109 while (select && !select->hasTagName(selectTag)) 110 select = select->parentNode(); 111 if (select) 112 static_cast<HTMLSelectElement*>(select)->setRecalcListItems(); 113 } 114 115 String HTMLOptGroupElement::label() const 116 { 117 return getAttribute(labelAttr); 118 } 119 120 void HTMLOptGroupElement::setLabel(const String &value) 121 { 122 setAttribute(labelAttr, value); 123 } 124 125 bool HTMLOptGroupElement::checkDTD(const Node* newChild) 126 { 127 // Make sure to keep this in sync with <select> (other than not allowing an optgroup). 128 return newChild->isTextNode() || newChild->hasTagName(HTMLNames::optionTag) || newChild->hasTagName(HTMLNames::hrTag) || newChild->hasTagName(HTMLNames::scriptTag); 129 } 130 131 void HTMLOptGroupElement::attach() 132 { 133 if (parentNode()->renderStyle()) 134 setRenderStyle(styleForRenderer()); 135 HTMLFormControlElement::attach(); 136 } 137 138 void HTMLOptGroupElement::detach() 139 { 140 m_style.clear(); 141 HTMLFormControlElement::detach(); 142 } 143 144 void HTMLOptGroupElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle) 145 { 146 m_style = newStyle; 147 } 148 149 RenderStyle* HTMLOptGroupElement::nonRendererRenderStyle() const 150 { 151 return m_style.get(); 152 } 153 154 String HTMLOptGroupElement::groupLabelText() const 155 { 156 String itemText = document()->displayStringModifiedByEncoding(getAttribute(labelAttr)); 157 158 // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. 159 itemText = itemText.stripWhiteSpace(); 160 // We want to collapse our whitespace too. This will match other browsers. 161 itemText = itemText.simplifyWhiteSpace(); 162 163 return itemText; 164 } 165 166 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const 167 { 168 Node* select = parentNode(); 169 while (select && !select->hasTagName(selectTag)) 170 select = select->parentNode(); 171 172 if (!select) 173 return 0; 174 175 return static_cast<HTMLSelectElement*>(select); 176 } 177 178 void HTMLOptGroupElement::accessKeyAction(bool) 179 { 180 HTMLSelectElement* select = ownerSelectElement(); 181 // send to the parent to bring focus to the list box 182 if (select && !select->focused()) 183 select->accessKeyAction(false); 184 } 185 186 } // namespace 187