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.
26 #include "HTMLFormControlElement.h"
28 #include "ChromeClient.h"
31 #include "EventHandler.h"
32 #include "EventNames.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"
41 #include "RenderBox.h"
42 #include "RenderTextControl.h"
43 #include "RenderTheme.h"
44 #include "ScriptEventListener.h"
45 #include "ValidityState.h"
49 using namespace HTMLNames
;
51 HTMLFormControlElement::HTMLFormControlElement(const QualifiedName
& tagName
, Document
* doc
, HTMLFormElement
* f
)
52 : HTMLElement(tagName
, doc
)
57 , m_valueMatchesRenderer(false)
60 m_form
= findFormAncestor();
62 m_form
->registerFormElement(this);
65 HTMLFormControlElement::~HTMLFormControlElement()
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()
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();
115 HTMLElement::parseMappedAttribute(attr
);
118 void HTMLFormControlElement::attach()
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
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
)))
143 void HTMLFormControlElement::insertedIntoTree(bool deep
)
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();
152 m_form
->registerFormElement(this);
154 document()->checkedRadioButtons().addButton(this);
157 HTMLElement::insertedIntoTree(deep
);
160 static inline Node
* findRoot(Node
* n
)
163 for (; n
; n
= n
->parentNode())
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);
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
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
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.
252 queuePostAttachCallback(updateFromElementCallback
, this);
255 bool HTMLFormControlElement::supportsFocus() const
260 bool HTMLFormControlElement::isFocusable() const
263 !renderer()->isBox() || toRenderBox(renderer())->size().isEmpty())
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
273 if (document()->frame())
274 return document()->frame()->eventHandler()->tabsToAllControls(event
);
278 bool HTMLFormControlElement::isMouseFocusable() const
281 return HTMLElement::isMouseFocusable();
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));
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
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()
365 m_form
->removeFormElement(this);
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()) {
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);
417 HTMLFormControlElementWithState::dispatchFocusEvent();
420 void HTMLTextFormControlElement::dispatchBlurEvent()
422 if (supportsPlaceholder())
423 updatePlaceholderVisibility(false);
425 HTMLFormControlElementWithState::dispatchBlurEvent();
428 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const
430 return supportsPlaceholder()
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())
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())
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())
478 if (document()->focusedNode() != this && cachedSelectionStart() >= 0)
479 return cachedSelectionStart();
482 return toRenderTextControl(renderer())->selectionStart();
485 int HTMLTextFormControlElement::selectionEnd()
487 if (!isTextFormControl())
489 if (document()->focusedNode() != this && cachedSelectionEnd() >= 0)
490 return cachedSelectionEnd();
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
));
516 HTMLFormControlElementWithState::parseMappedAttribute(attr
);
519 } // namespace Webcore