Rubber-stamped by Brady Eidson.
[webbrowser.git] / WebCore / html / HTMLFormControlElement.cpp
blob4e20dc35539543dd31a9b7cf3fa13281dd28ed3a
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)
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.
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.
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.
25 #include "config.h"
26 #include "HTMLFormControlElement.h"
28 #include "ChromeClient.h"
29 #include "Document.h"
30 #include "Event.h"
31 #include "EventHandler.h"
32 #include "EventNames.h"
33 #include "Frame.h"
34 #include "HTMLFormElement.h"
35 #include "HTMLInputElement.h"
36 #include "HTMLNames.h"
37 #include "HTMLParser.h"
38 #include "HTMLTokenizer.h"
39 #include "MappedAttribute.h"
40 #include "Page.h"
41 #include "RenderBox.h"
42 #include "RenderTextControl.h"
43 #include "RenderTheme.h"
44 #include "ScriptEventListener.h"
45 #include "ValidityState.h"
47 namespace WebCore {
49 using namespace HTMLNames;
51 HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
52 : HTMLElement(tagName, doc)
53 , m_form(f)
54 , m_disabled(false)
55 , m_readOnly(false)
56 , m_required(false)
57 , m_valueMatchesRenderer(false)
59 if (!m_form)
60 m_form = findFormAncestor();
61 if (m_form)
62 m_form->registerFormElement(this);
65 HTMLFormControlElement::~HTMLFormControlElement()
67 if (m_form)
68 m_form->removeFormElement(this);
71 bool HTMLFormControlElement::formNoValidate() const
73 return !getAttribute(formnovalidateAttr).isNull();
76 void HTMLFormControlElement::setFormNoValidate(bool formnovalidate)
78 setAttribute(formnovalidateAttr, formnovalidate ? "" : 0);
81 ValidityState* HTMLFormControlElement::validity()
83 if (!m_validityState)
84 m_validityState = ValidityState::create(this);
86 return m_validityState.get();
89 void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
91 if (attr->name() == nameAttr)
92 setNeedsStyleRecalc();
93 else if (attr->name() == disabledAttr) {
94 bool oldDisabled = m_disabled;
95 m_disabled = !attr->isNull();
96 if (oldDisabled != m_disabled) {
97 setNeedsStyleRecalc();
98 if (renderer() && renderer()->style()->hasAppearance())
99 renderer()->theme()->stateChanged(renderer(), EnabledState);
101 } else if (attr->name() == readonlyAttr) {
102 bool oldReadOnly = m_readOnly;
103 m_readOnly = !attr->isNull();
104 if (oldReadOnly != m_readOnly) {
105 setNeedsStyleRecalc();
106 if (renderer() && renderer()->style()->hasAppearance())
107 renderer()->theme()->stateChanged(renderer(), ReadOnlyState);
109 } else if (attr->name() == requiredAttr) {
110 bool oldRequired = m_required;
111 m_required = !attr->isNull();
112 if (oldRequired != m_required)
113 setNeedsStyleRecalc();
114 } else
115 HTMLElement::parseMappedAttribute(attr);
118 void HTMLFormControlElement::attach()
120 ASSERT(!attached());
122 HTMLElement::attach();
124 // The call to updateFromElement() needs to go after the call through
125 // to the base class's attach() because that can sometimes do a close
126 // on the renderer.
127 if (renderer())
128 renderer()->updateFromElement();
130 // Focus the element if it should honour its autofocus attribute.
131 // We have to determine if the element is a TextArea/Input/Button/Select,
132 // if input type hidden ignore autofocus. So if disabled or readonly.
133 bool isInputTypeHidden = false;
134 if (hasTagName(inputTag))
135 isInputTypeHidden = static_cast<HTMLInputElement*>(this)->isInputTypeHidden();
137 if (autofocus() && renderer() && !document()->ignoreAutofocus() && !isReadOnlyFormControl() &&
138 ((hasTagName(inputTag) && !isInputTypeHidden) || hasTagName(selectTag) ||
139 hasTagName(buttonTag) || hasTagName(textareaTag)))
140 focus();
143 void HTMLFormControlElement::insertedIntoTree(bool deep)
145 if (!m_form) {
146 // This handles the case of a new form element being created by
147 // JavaScript and inserted inside a form. In the case of the parser
148 // setting a form, we will already have a non-null value for m_form,
149 // and so we don't need to do anything.
150 m_form = findFormAncestor();
151 if (m_form)
152 m_form->registerFormElement(this);
153 else
154 document()->checkedRadioButtons().addButton(this);
157 HTMLElement::insertedIntoTree(deep);
160 static inline Node* findRoot(Node* n)
162 Node* root = n;
163 for (; n; n = n->parentNode())
164 root = n;
165 return root;
168 void HTMLFormControlElement::removedFromTree(bool deep)
170 // If the form and element are both in the same tree, preserve the connection to the form.
171 // Otherwise, null out our form and remove ourselves from the form's list of elements.
172 HTMLParser* parser = 0;
173 if (Tokenizer* tokenizer = document()->tokenizer())
174 if (tokenizer->isHTMLTokenizer())
175 parser = static_cast<HTMLTokenizer*>(tokenizer)->htmlParser();
177 if (m_form && !(parser && parser->isHandlingResidualStyleAcrossBlocks()) && findRoot(this) != findRoot(m_form)) {
178 m_form->removeFormElement(this);
179 m_form = 0;
182 HTMLElement::removedFromTree(deep);
185 const AtomicString& HTMLFormControlElement::formControlName() const
187 const AtomicString& n = getAttribute(nameAttr);
188 return n.isNull() ? emptyAtom : n;
191 void HTMLFormControlElement::setName(const AtomicString &value)
193 setAttribute(nameAttr, value);
196 void HTMLFormControlElement::dispatchFormControlChangeEvent()
198 dispatchEvent(Event::create(eventNames().changeEvent, true, false));
201 bool HTMLFormControlElement::disabled() const
203 return m_disabled;
206 void HTMLFormControlElement::setDisabled(bool b)
208 setAttribute(disabledAttr, b ? "" : 0);
211 void HTMLFormControlElement::setReadOnly(bool b)
213 setAttribute(readonlyAttr, b ? "" : 0);
216 bool HTMLFormControlElement::autofocus() const
218 return hasAttribute(autofocusAttr);
221 void HTMLFormControlElement::setAutofocus(bool b)
223 setAttribute(autofocusAttr, b ? "autofocus" : 0);
226 bool HTMLFormControlElement::required() const
228 return m_required;
231 void HTMLFormControlElement::setRequired(bool b)
233 setAttribute(requiredAttr, b ? "required" : 0);
236 static void updateFromElementCallback(Node* node)
238 ASSERT_ARG(node, node->isElementNode());
239 ASSERT_ARG(node, static_cast<Element*>(node)->isFormControlElement());
240 ASSERT(node->renderer());
241 if (RenderObject* renderer = node->renderer())
242 renderer->updateFromElement();
245 void HTMLFormControlElement::recalcStyle(StyleChange change)
247 HTMLElement::recalcStyle(change);
249 // updateFromElement() can cause the selection to change, and in turn
250 // trigger synchronous layout, so it must not be called during style recalc.
251 if (renderer())
252 queuePostAttachCallback(updateFromElementCallback, this);
255 bool HTMLFormControlElement::supportsFocus() const
257 return !disabled();
260 bool HTMLFormControlElement::isFocusable() const
262 if (!renderer() ||
263 !renderer()->isBox() || toRenderBox(renderer())->size().isEmpty())
264 return false;
265 // HTMLElement::isFocusable handles visibility and calls suportsFocus which
266 // will cover the disabled case.
267 return HTMLElement::isFocusable();
270 bool HTMLFormControlElement::isKeyboardFocusable(KeyboardEvent* event) const
272 if (isFocusable())
273 if (document()->frame())
274 return document()->frame()->eventHandler()->tabsToAllControls(event);
275 return false;
278 bool HTMLFormControlElement::isMouseFocusable() const
280 #if PLATFORM(GTK)
281 return HTMLElement::isMouseFocusable();
282 #else
283 return false;
284 #endif
287 short HTMLFormControlElement::tabIndex() const
289 // Skip the supportsFocus check in HTMLElement.
290 return Element::tabIndex();
293 bool HTMLFormControlElement::willValidate() const
295 // FIXME: Implementation shall be completed with these checks:
296 // The control does not have a repetition template as an ancestor.
297 // The control does not have a datalist element as an ancestor.
298 // The control is not an output element.
299 return form() && !name().isEmpty() && !disabled() && !isReadOnlyFormControl();
302 String HTMLFormControlElement::validationMessage()
304 return validity()->validationMessage();
307 bool HTMLFormControlElement::checkValidity()
309 if (willValidate() && !isValidFormControlElement()) {
310 dispatchEvent(Event::create(eventNames().invalidEvent, false, true));
311 return false;
314 return true;
317 void HTMLFormControlElement::updateValidity()
319 if (willValidate()) {
320 // Update style for pseudo classes such as :valid :invalid.
321 setNeedsStyleRecalc();
325 void HTMLFormControlElement::setCustomValidity(const String& error)
327 validity()->setCustomErrorMessage(error);
330 void HTMLFormControlElement::dispatchFocusEvent()
332 if (document()->frame() && document()->frame()->page())
333 document()->frame()->page()->chrome()->client()->formDidFocus(this);
335 HTMLElement::dispatchFocusEvent();
338 void HTMLFormControlElement::dispatchBlurEvent()
340 if (document()->frame() && document()->frame()->page())
341 document()->frame()->page()->chrome()->client()->formDidBlur(this);
343 HTMLElement::dispatchBlurEvent();
346 HTMLFormElement* HTMLFormControlElement::virtualForm() const
348 return m_form;
351 bool HTMLFormControlElement::isDefaultButtonForForm() const
353 return isSuccessfulSubmitButton() && m_form && m_form->defaultButton() == this;
356 bool HTMLFormControlElement::isValidFormControlElement()
358 return validity()->valid();
361 void HTMLFormControlElement::removeFromForm()
363 if (!m_form)
364 return;
365 m_form->removeFormElement(this);
366 m_form = 0;
369 HTMLFormControlElementWithState::HTMLFormControlElementWithState(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
370 : HTMLFormControlElement(tagName, doc, f)
372 document()->registerFormElementWithState(this);
375 HTMLFormControlElementWithState::~HTMLFormControlElementWithState()
377 document()->unregisterFormElementWithState(this);
380 void HTMLFormControlElementWithState::willMoveToNewOwnerDocument()
382 document()->unregisterFormElementWithState(this);
383 HTMLFormControlElement::willMoveToNewOwnerDocument();
386 void HTMLFormControlElementWithState::didMoveToNewOwnerDocument()
388 document()->registerFormElementWithState(this);
389 HTMLFormControlElement::didMoveToNewOwnerDocument();
392 void HTMLFormControlElementWithState::finishParsingChildren()
394 HTMLFormControlElement::finishParsingChildren();
395 Document* doc = document();
396 if (doc->hasStateForNewFormElements()) {
397 String state;
398 if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
399 restoreFormControlState(state);
403 HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* form)
404 : HTMLFormControlElementWithState(tagName, doc, form)
408 HTMLTextFormControlElement::~HTMLTextFormControlElement()
412 void HTMLTextFormControlElement::dispatchFocusEvent()
414 if (supportsPlaceholder())
415 updatePlaceholderVisibility(false);
416 handleFocusEvent();
417 HTMLFormControlElementWithState::dispatchFocusEvent();
420 void HTMLTextFormControlElement::dispatchBlurEvent()
422 if (supportsPlaceholder())
423 updatePlaceholderVisibility(false);
424 handleBlurEvent();
425 HTMLFormControlElementWithState::dispatchBlurEvent();
428 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const
430 return supportsPlaceholder()
431 && isEmptyValue()
432 && document()->focusedNode() != this
433 && !getAttribute(placeholderAttr).isEmpty();
436 void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
438 if (supportsPlaceholder() && renderer())
439 toRenderTextControl(renderer())->updatePlaceholderVisibility(placeholderShouldBeVisible(), placeholderValueChanged);
442 RenderTextControl* HTMLTextFormControlElement::textRendererAfterUpdateLayout()
444 if (!isTextFormControl())
445 return 0;
446 document()->updateLayoutIgnorePendingStylesheets();
447 return toRenderTextControl(renderer());
450 void HTMLTextFormControlElement::setSelectionStart(int start)
452 if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
453 renderer->setSelectionStart(start);
456 void HTMLTextFormControlElement::setSelectionEnd(int end)
458 if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
459 renderer->setSelectionEnd(end);
462 void HTMLTextFormControlElement::select()
464 if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
465 renderer->select();
468 void HTMLTextFormControlElement::setSelectionRange(int start, int end)
470 if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
471 renderer->setSelectionRange(start, end);
474 int HTMLTextFormControlElement::selectionStart()
476 if (!isTextFormControl())
477 return 0;
478 if (document()->focusedNode() != this && cachedSelectionStart() >= 0)
479 return cachedSelectionStart();
480 if (!renderer())
481 return 0;
482 return toRenderTextControl(renderer())->selectionStart();
485 int HTMLTextFormControlElement::selectionEnd()
487 if (!isTextFormControl())
488 return 0;
489 if (document()->focusedNode() != this && cachedSelectionEnd() >= 0)
490 return cachedSelectionEnd();
491 if (!renderer())
492 return 0;
493 return toRenderTextControl(renderer())->selectionEnd();
496 VisibleSelection HTMLTextFormControlElement::selection() const
498 if (!renderer() || !isTextFormControl() || cachedSelectionStart() < 0 || cachedSelectionEnd() < 0)
499 return VisibleSelection();
500 return toRenderTextControl(renderer())->selection(cachedSelectionStart(), cachedSelectionEnd());
503 void HTMLTextFormControlElement::parseMappedAttribute(MappedAttribute* attr)
505 if (attr->name() == placeholderAttr)
506 updatePlaceholderVisibility(true);
507 else if (attr->name() == onfocusAttr)
508 setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
509 else if (attr->name() == onblurAttr)
510 setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
511 else if (attr->name() == onselectAttr)
512 setAttributeEventListener(eventNames().selectEvent, createAttributeEventListener(this, attr));
513 else if (attr->name() == onchangeAttr)
514 setAttributeEventListener(eventNames().changeEvent, createAttributeEventListener(this, attr));
515 else
516 HTMLFormControlElementWithState::parseMappedAttribute(attr);
519 } // namespace Webcore