53e0c9ec3a7711f2e7609df1af81969c90cfbbc8
[WebKit-https.git] / WebCore / html / HTMLGenericFormElement.cpp
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 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 "HTMLGenericFormElement.h"
27
28 #include "Document.h"
29 #include "EventHandler.h"
30 #include "EventNames.h"
31 #include "Frame.h"
32 #include "HTMLFormElement.h"
33 #include "HTMLInputElement.h"
34 #include "HTMLNames.h"
35 #include "HTMLParser.h"
36 #include "HTMLTokenizer.h"
37 #include "RenderTheme.h"
38 #include "Tokenizer.h"
39
40 namespace WebCore {
41
42 using namespace EventNames;
43 using namespace HTMLNames;
44
45 HTMLGenericFormElement::HTMLGenericFormElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
46     : HTMLElement(tagName, doc)
47     , m_form(f)
48     , m_disabled(false)
49     , m_readOnly(false)
50     , m_valueMatchesRenderer(false)
51 {
52     if (!m_form)
53         m_form = findFormAncestor();
54     if (m_form)
55         m_form->registerFormElement(this);
56 }
57
58 HTMLGenericFormElement::~HTMLGenericFormElement()
59 {
60     if (m_form)
61         m_form->removeFormElement(this);
62 }
63
64 void HTMLGenericFormElement::parseMappedAttribute(MappedAttribute *attr)
65 {
66     if (attr->name() == nameAttr) {
67         // Do nothing.
68     } else if (attr->name() == disabledAttr) {
69         bool oldDisabled = m_disabled;
70         m_disabled = !attr->isNull();
71         if (oldDisabled != m_disabled) {
72             setChanged();
73             if (renderer() && renderer()->style()->hasAppearance())
74                 theme()->stateChanged(renderer(), EnabledState);
75         }
76     } else if (attr->name() == readonlyAttr) {
77         bool oldReadOnly = m_readOnly;
78         m_readOnly = !attr->isNull();
79         if (oldReadOnly != m_readOnly) {
80             setChanged();
81             if (renderer() && renderer()->style()->hasAppearance())
82                 theme()->stateChanged(renderer(), ReadOnlyState);
83         }
84     } else
85         HTMLElement::parseMappedAttribute(attr);
86 }
87
88 void HTMLGenericFormElement::attach()
89 {
90     ASSERT(!attached());
91
92     HTMLElement::attach();
93
94     // The call to updateFromElement() needs to go after the call through
95     // to the base class's attach() because that can sometimes do a close
96     // on the renderer.
97     if (renderer())
98         renderer()->updateFromElement();
99 }
100
101 void HTMLGenericFormElement::insertedIntoTree(bool deep)
102 {
103     if (!m_form) {
104         // This handles the case of a new form element being created by
105         // JavaScript and inserted inside a form.  In the case of the parser
106         // setting a form, we will already have a non-null value for m_form, 
107         // and so we don't need to do anything.
108         m_form = findFormAncestor();
109         if (m_form)
110             m_form->registerFormElement(this);
111         else
112             document()->checkedRadioButtons().addButton(this);
113     }
114
115     HTMLElement::insertedIntoTree(deep);
116 }
117
118 static inline Node* findRoot(Node* n)
119 {
120     Node* root = n;
121     for (; n; n = n->parentNode())
122         root = n;
123     return root;
124 }
125
126 void HTMLGenericFormElement::removedFromTree(bool deep)
127 {
128     // If the form and element are both in the same tree, preserve the connection to the form.
129     // Otherwise, null out our form and remove ourselves from the form's list of elements.
130     HTMLParser* parser = 0;
131     if (Tokenizer* tokenizer = document()->tokenizer())
132         if (tokenizer->isHTMLTokenizer())
133             parser = static_cast<HTMLTokenizer*>(tokenizer)->htmlParser();
134     
135     if (m_form && !(parser && parser->isHandlingResidualStyleAcrossBlocks()) && findRoot(this) != findRoot(m_form)) {
136         m_form->removeFormElement(this);
137         m_form = 0;
138     }
139
140     HTMLElement::removedFromTree(deep);
141 }
142
143 const AtomicString& HTMLGenericFormElement::name() const
144 {
145     const AtomicString& n = getAttribute(nameAttr);
146     return n.isNull() ? emptyAtom : n;
147 }
148
149 void HTMLGenericFormElement::setName(const AtomicString &value)
150 {
151     setAttribute(nameAttr, value);
152 }
153
154 void HTMLGenericFormElement::onChange()
155 {
156     dispatchHTMLEvent(changeEvent, true, false);
157 }
158
159 bool HTMLGenericFormElement::disabled() const
160 {
161     return m_disabled;
162 }
163
164 void HTMLGenericFormElement::setDisabled(bool b)
165 {
166     setAttribute(disabledAttr, b ? "" : 0);
167 }
168
169 void HTMLGenericFormElement::setReadOnly(bool b)
170 {
171     setAttribute(readonlyAttr, b ? "" : 0);
172 }
173
174 void HTMLGenericFormElement::recalcStyle(StyleChange change)
175 {
176     HTMLElement::recalcStyle(change);
177
178     if (renderer())
179         renderer()->updateFromElement();
180 }
181
182 bool HTMLGenericFormElement::isFocusable() const
183 {
184     if (disabled() || !renderer() || 
185         (renderer()->style() && renderer()->style()->visibility() != VISIBLE) || 
186         renderer()->width() == 0 || renderer()->height() == 0)
187         return false;
188     return true;
189 }
190
191 bool HTMLGenericFormElement::isKeyboardFocusable(KeyboardEvent* event) const
192 {
193     if (isFocusable())
194         if (document()->frame())
195             return document()->frame()->eventHandler()->tabsToAllControls(event);
196     return false;
197 }
198
199 bool HTMLGenericFormElement::isMouseFocusable() const
200 {
201     return false;
202 }
203
204 void HTMLGenericFormElement::setTabIndex(int value)
205 {
206     setAttribute(tabindexAttr, String::number(value));
207 }
208     
209 bool HTMLGenericFormElement::supportsFocus() const
210 {
211     return isFocusable() || (!disabled() && !document()->haveStylesheetsLoaded());
212 }
213
214 HTMLFormElement* HTMLGenericFormElement::virtualForm() const
215 {
216     return m_form;
217 }
218
219 void HTMLGenericFormElement::removeFromForm()
220 {
221     if (!m_form)
222         return;
223     m_form->removeFormElement(this);
224     m_form = 0;
225 }
226
227 HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
228     : HTMLGenericFormElement(tagName, doc, f)
229 {
230     doc->registerFormElementWithState(this);
231 }
232
233 HTMLFormControlElementWithState::~HTMLFormControlElementWithState()
234 {
235     document()->unregisterFormElementWithState(this);
236 }
237
238 void HTMLFormControlElementWithState::willMoveToNewOwnerDocument()
239 {
240     document()->unregisterFormElementWithState(this);
241     HTMLGenericFormElement::willMoveToNewOwnerDocument();
242 }
243
244 void HTMLFormControlElementWithState::didMoveToNewOwnerDocument()
245 {
246     document()->registerFormElementWithState(this);
247     HTMLGenericFormElement::didMoveToNewOwnerDocument();
248 }
249
250 void HTMLFormControlElementWithState::finishedParsing()
251 {
252     Document* doc = document();
253     if (doc->hasStateForNewFormElements()) {
254         String state;
255         if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
256             restoreState(state);
257     }
258 }
259
260 } // namespace Webcore