Remove unnecessary functions: setName() and formControlName()
[WebKit-https.git] / Source / WebCore / html / HTMLFormControlElement.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 "HTMLFormControlElement.h"
27
28 #include "Attribute.h"
29 #include "ElementShadow.h"
30 #include "Event.h"
31 #include "EventHandler.h"
32 #include "EventNames.h"
33 #include "Frame.h"
34 #include "HTMLFieldSetElement.h"
35 #include "HTMLFormElement.h"
36 #include "HTMLInputElement.h"
37 #include "HTMLLegendElement.h"
38 #include "RenderBox.h"
39 #include "RenderTheme.h"
40 #include "ScriptEventListener.h"
41 #include "ValidationMessage.h"
42 #include "ValidityState.h"
43 #include <wtf/Vector.h>
44
45 namespace WebCore {
46
47 using namespace HTMLNames;
48 using namespace std;
49
50 HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
51     : LabelableElement(tagName, document)
52     , m_disabled(false)
53     , m_readOnly(false)
54     , m_required(false)
55     , m_valueMatchesRenderer(false)
56     , m_ancestorDisabledState(AncestorDisabledStateUnknown)
57     , m_dataListAncestorState(Unknown)
58     , m_willValidateInitialized(false)
59     , m_willValidate(true)
60     , m_isValid(true)
61     , m_wasChangedSinceLastFormControlChangeEvent(false)
62     , m_hasAutofocused(false)
63 {
64     setForm(form ? form : findFormAncestor());
65     setHasCustomCallbacks();
66 }
67
68 HTMLFormControlElement::~HTMLFormControlElement()
69 {
70 }
71
72 String HTMLFormControlElement::formEnctype() const
73 {
74     return FormSubmission::Attributes::parseEncodingType(fastGetAttribute(formenctypeAttr));
75 }
76
77 void HTMLFormControlElement::setFormEnctype(const String& value)
78 {
79     setAttribute(formenctypeAttr, value);
80 }
81
82 String HTMLFormControlElement::formMethod() const
83 {
84     return FormSubmission::Attributes::methodString(FormSubmission::Attributes::parseMethodType(fastGetAttribute(formmethodAttr)));
85 }
86
87 void HTMLFormControlElement::setFormMethod(const String& value)
88 {
89     setAttribute(formmethodAttr, value);
90 }
91
92 bool HTMLFormControlElement::formNoValidate() const
93 {
94     return fastHasAttribute(formnovalidateAttr);
95 }
96
97 void HTMLFormControlElement::updateAncestorDisabledState() const
98 {
99     HTMLFieldSetElement* fieldSetAncestor = 0;
100     ContainerNode* legendAncestor = 0;
101     for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
102         if (!legendAncestor && ancestor->hasTagName(legendTag))
103             legendAncestor = ancestor;
104         if (ancestor->hasTagName(fieldsetTag)) {
105             fieldSetAncestor = static_cast<HTMLFieldSetElement*>(ancestor);
106             break;
107         }
108     }
109     m_ancestorDisabledState = (fieldSetAncestor && fieldSetAncestor->disabled() && !(legendAncestor && legendAncestor == fieldSetAncestor->legend())) ? AncestorDisabledStateDisabled : AncestorDisabledStateEnabled;
110 }
111
112 void HTMLFormControlElement::ancestorDisabledStateWasChanged()
113 {
114     m_ancestorDisabledState = AncestorDisabledStateUnknown;
115     disabledAttributeChanged();
116 }
117
118 void HTMLFormControlElement::parseAttribute(const Attribute& attribute)
119 {
120     if (attribute.name() == formAttr)
121         formAttributeChanged();
122     else if (attribute.name() == disabledAttr) {
123         bool oldDisabled = m_disabled;
124         m_disabled = !attribute.isNull();
125         if (oldDisabled != m_disabled)
126             disabledAttributeChanged();
127     } else if (attribute.name() == readonlyAttr) {
128         bool oldReadOnly = m_readOnly;
129         m_readOnly = !attribute.isNull();
130         if (oldReadOnly != m_readOnly) {
131             setNeedsWillValidateCheck();
132             setNeedsStyleRecalc();
133             if (renderer() && renderer()->style()->hasAppearance())
134                 renderer()->theme()->stateChanged(renderer(), ReadOnlyState);
135         }
136     } else if (attribute.name() == requiredAttr) {
137         bool oldRequired = m_required;
138         m_required = !attribute.isNull();
139         if (oldRequired != m_required)
140             requiredAttributeChanged();
141     } else
142         HTMLElement::parseAttribute(attribute);
143 }
144
145 void HTMLFormControlElement::disabledAttributeChanged()
146 {
147     setNeedsWillValidateCheck();
148     setNeedsStyleRecalc();
149     if (renderer() && renderer()->style()->hasAppearance())
150         renderer()->theme()->stateChanged(renderer(), EnabledState);
151 }
152
153 void HTMLFormControlElement::requiredAttributeChanged()
154 {
155     setNeedsValidityCheck();
156     // Style recalculation is needed because style selectors may include
157     // :required and :optional pseudo-classes.
158     setNeedsStyleRecalc();
159 }
160
161 static bool shouldAutofocus(HTMLFormControlElement* element)
162 {
163     if (!element->autofocus())
164         return false;
165     if (!element->renderer())
166         return false;
167     if (element->document()->ignoreAutofocus())
168         return false;
169     if (element->document()->isSandboxed(SandboxAutomaticFeatures))
170         return false;
171     if (element->hasAutofocused())
172         return false;
173
174     // FIXME: Should this set of hasTagName checks be replaced by a
175     // virtual member function?
176     if (element->hasTagName(inputTag))
177         return !static_cast<HTMLInputElement*>(element)->isInputTypeHidden();
178     if (element->hasTagName(selectTag))
179         return true;
180     if (element->hasTagName(keygenTag))
181         return true;
182     if (element->hasTagName(buttonTag))
183         return true;
184     if (element->hasTagName(textareaTag))
185         return true;
186
187     return false;
188 }
189
190 static void focusPostAttach(Node* element, unsigned)
191
192     static_cast<Element*>(element)->focus(); 
193     element->deref(); 
194 }
195
196 void HTMLFormControlElement::attach()
197 {
198     ASSERT(!attached());
199
200     suspendPostAttachCallbacks();
201
202     HTMLElement::attach();
203
204     // The call to updateFromElement() needs to go after the call through
205     // to the base class's attach() because that can sometimes do a close
206     // on the renderer.
207     if (renderer())
208         renderer()->updateFromElement();
209
210     if (shouldAutofocus(this)) {
211         setAutofocused();
212         ref();
213         queuePostAttachCallback(focusPostAttach, this);
214     }
215
216     resumePostAttachCallbacks();
217 }
218
219 void HTMLFormControlElement::didMoveToNewDocument(Document* oldDocument)
220 {
221     FormAssociatedElement::didMoveToNewDocument(oldDocument);
222     HTMLElement::didMoveToNewDocument(oldDocument);
223 }
224
225 Node::InsertionNotificationRequest HTMLFormControlElement::insertedInto(ContainerNode* insertionPoint)
226 {
227     m_ancestorDisabledState = AncestorDisabledStateUnknown;
228     m_dataListAncestorState = Unknown;
229     setNeedsWillValidateCheck();
230     HTMLElement::insertedInto(insertionPoint);
231     FormAssociatedElement::insertedInto(insertionPoint);
232     return InsertionDone;
233 }
234
235 void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint)
236 {
237     m_validationMessage = nullptr;
238     m_ancestorDisabledState = AncestorDisabledStateUnknown;
239     m_dataListAncestorState = Unknown;
240     HTMLElement::removedFrom(insertionPoint);
241     FormAssociatedElement::removedFrom(insertionPoint);
242 }
243
244 bool HTMLFormControlElement::wasChangedSinceLastFormControlChangeEvent() const
245 {
246     return m_wasChangedSinceLastFormControlChangeEvent;
247 }
248
249 void HTMLFormControlElement::setChangedSinceLastFormControlChangeEvent(bool changed)
250 {
251     m_wasChangedSinceLastFormControlChangeEvent = changed;
252 }
253
254 void HTMLFormControlElement::dispatchFormControlChangeEvent()
255 {
256     HTMLElement::dispatchChangeEvent();
257     setChangedSinceLastFormControlChangeEvent(false);
258 }
259
260 void HTMLFormControlElement::dispatchFormControlInputEvent()
261 {
262     setChangedSinceLastFormControlChangeEvent(true);
263     HTMLElement::dispatchInputEvent();
264 }
265
266 bool HTMLFormControlElement::disabled() const
267 {
268     if (m_disabled)
269         return true;
270
271     if (m_ancestorDisabledState == AncestorDisabledStateUnknown)
272         updateAncestorDisabledState();
273     return m_ancestorDisabledState == AncestorDisabledStateDisabled;
274 }
275
276 void HTMLFormControlElement::setDisabled(bool b)
277 {
278     setAttribute(disabledAttr, b ? "" : 0);
279 }
280
281 bool HTMLFormControlElement::autofocus() const
282 {
283     return hasAttribute(autofocusAttr);
284 }
285
286 bool HTMLFormControlElement::required() const
287 {
288     return m_required;
289 }
290
291 static void updateFromElementCallback(Node* node, unsigned)
292 {
293     ASSERT_ARG(node, node->isElementNode());
294     ASSERT_ARG(node, static_cast<Element*>(node)->isFormControlElement());
295     ASSERT(node->renderer());
296     if (RenderObject* renderer = node->renderer())
297         renderer->updateFromElement();
298 }
299
300 void HTMLFormControlElement::didRecalcStyle(StyleChange)
301 {
302     // updateFromElement() can cause the selection to change, and in turn
303     // trigger synchronous layout, so it must not be called during style recalc.
304     if (renderer())
305         queuePostAttachCallback(updateFromElementCallback, this);
306 }
307
308 bool HTMLFormControlElement::supportsFocus() const
309 {
310     return !disabled();
311 }
312
313 bool HTMLFormControlElement::isFocusable() const
314 {
315     if (!renderer() || !renderer()->isBox() || toRenderBox(renderer())->size().isEmpty())
316         return false;
317     // HTMLElement::isFocusable handles visibility and calls suportsFocus which
318     // will cover the disabled case.
319     return HTMLElement::isFocusable();
320 }
321
322 bool HTMLFormControlElement::isKeyboardFocusable(KeyboardEvent* event) const
323 {
324     if (isFocusable())
325         if (document()->frame())
326             return document()->frame()->eventHandler()->tabsToAllFormControls(event);
327     return false;
328 }
329
330 bool HTMLFormControlElement::isMouseFocusable() const
331 {
332 #if PLATFORM(GTK) || PLATFORM(QT)
333     return HTMLElement::isMouseFocusable();
334 #else
335     return false;
336 #endif
337 }
338
339 short HTMLFormControlElement::tabIndex() const
340 {
341     // Skip the supportsFocus check in HTMLElement.
342     return Element::tabIndex();
343 }
344
345 bool HTMLFormControlElement::recalcWillValidate() const
346 {
347     if (m_dataListAncestorState == Unknown) {
348         for (ContainerNode* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
349             if (ancestor->hasTagName(datalistTag)) {
350                 m_dataListAncestorState = InsideDataList;
351                 break;
352             }
353         }
354         if (m_dataListAncestorState == Unknown)
355             m_dataListAncestorState = NotInsideDataList;
356     }
357     return m_dataListAncestorState == NotInsideDataList && !disabled() && !m_readOnly;
358 }
359
360 bool HTMLFormControlElement::willValidate() const
361 {
362     if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) {
363         m_willValidateInitialized = true;
364         bool newWillValidate = recalcWillValidate();
365         if (m_willValidate != newWillValidate) {
366             m_willValidate = newWillValidate;
367             const_cast<HTMLFormControlElement*>(this)->setNeedsValidityCheck();
368         }
369     } else {
370         // If the following assertion fails, setNeedsWillValidateCheck() is not
371         // called correctly when something which changes recalcWillValidate() result
372         // is updated.
373         ASSERT(m_willValidate == recalcWillValidate());
374     }
375     return m_willValidate;
376 }
377
378 void HTMLFormControlElement::setNeedsWillValidateCheck()
379 {
380     // We need to recalculate willValidate immediately because willValidate change can causes style change.
381     bool newWillValidate = recalcWillValidate();
382     if (m_willValidateInitialized && m_willValidate == newWillValidate)
383         return;
384     m_willValidateInitialized = true;
385     m_willValidate = newWillValidate;
386     setNeedsValidityCheck();
387     setNeedsStyleRecalc();
388     if (!m_willValidate)
389         hideVisibleValidationMessage();
390 }
391
392 void HTMLFormControlElement::updateVisibleValidationMessage()
393 {
394     Page* page = document()->page();
395     if (!page)
396         return;
397     String message;
398     if (renderer() && willValidate()) {
399         message = validationMessage().stripWhiteSpace();
400         // HTML5 specification doesn't ask UA to show the title attribute value
401         // with the validationMessage.  However, this behavior is same as Opera
402         // and the specification describes such behavior as an example.
403         const AtomicString& title = getAttribute(titleAttr);
404         if (!message.isEmpty() && !title.isEmpty()) {
405             message.append('\n');
406             message.append(title);
407         }
408     }
409     if (message.isEmpty()) {
410         hideVisibleValidationMessage();
411         return;
412     }
413     if (!m_validationMessage) {
414         m_validationMessage = ValidationMessage::create(this);
415         m_validationMessage->setMessage(message);
416     } else {
417         // Call setMessage() even if m_validationMesage->message() == message
418         // because the existing message might be to be hidden.
419         m_validationMessage->setMessage(message);
420     }
421 }
422
423 void HTMLFormControlElement::hideVisibleValidationMessage()
424 {
425     if (m_validationMessage)
426         m_validationMessage->requestToHideMessage();
427 }
428
429 String HTMLFormControlElement::visibleValidationMessage() const
430 {
431     return m_validationMessage ? m_validationMessage->message() : String();
432 }
433
434 bool HTMLFormControlElement::checkValidity(Vector<RefPtr<FormAssociatedElement> >* unhandledInvalidControls)
435 {
436     if (!willValidate() || isValidFormControlElement())
437         return true;
438     // An event handler can deref this object.
439     RefPtr<HTMLFormControlElement> protector(this);
440     RefPtr<Document> originalDocument(document());
441     bool needsDefaultAction = dispatchEvent(Event::create(eventNames().invalidEvent, false, true));
442     if (needsDefaultAction && unhandledInvalidControls && inDocument() && originalDocument == document())
443         unhandledInvalidControls->append(this);
444     return false;
445 }
446
447 bool HTMLFormControlElement::isValidFormControlElement()
448 {
449     // If the following assertion fails, setNeedsValidityCheck() is not called
450     // correctly when something which changes validity is updated.
451     ASSERT(m_isValid == validity()->valid());
452     return m_isValid;
453 }
454
455 void HTMLFormControlElement::setNeedsValidityCheck()
456 {
457     bool newIsValid = validity()->valid();
458     if (willValidate() && newIsValid != m_isValid) {
459         // Update style for pseudo classes such as :valid :invalid.
460         setNeedsStyleRecalc();
461     }
462     m_isValid = newIsValid;
463
464     // Updates only if this control already has a validtion message.
465     if (!visibleValidationMessage().isEmpty()) {
466         // Calls updateVisibleValidationMessage() even if m_isValid is not
467         // changed because a validation message can be chagned.
468         updateVisibleValidationMessage();
469     }
470 }
471
472 void HTMLFormControlElement::setCustomValidity(const String& error)
473 {
474     FormAssociatedElement::setCustomValidity(error);
475     setNeedsValidityCheck();
476 }
477
478 void HTMLFormControlElement::dispatchBlurEvent(PassRefPtr<Node> newFocusedNode)
479 {
480     HTMLElement::dispatchBlurEvent(newFocusedNode);
481     hideVisibleValidationMessage();
482 }
483
484 HTMLFormElement* HTMLFormControlElement::virtualForm() const
485 {
486     return FormAssociatedElement::form();
487 }
488
489 bool HTMLFormControlElement::isDefaultButtonForForm() const
490 {
491     return isSuccessfulSubmitButton() && form() && form()->defaultButton() == this;
492 }
493
494 HTMLFormControlElement* HTMLFormControlElement::enclosingFormControlElement(Node* node)
495 {
496     for (; node; node = node->parentNode()) {
497         if (node->isElementNode() && toElement(node)->isFormControlElement())
498             return static_cast<HTMLFormControlElement*>(node);
499     }
500     return 0;
501 }
502
503 } // namespace Webcore