summaryrefslogtreecommitdiffstats
path: root/WebCore/html/HTMLFormControlElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html/HTMLFormControlElement.cpp')
-rw-r--r--WebCore/html/HTMLFormControlElement.cpp190
1 files changed, 177 insertions, 13 deletions
diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp
index 09d91df..ea46980 100644
--- a/WebCore/html/HTMLFormControlElement.cpp
+++ b/WebCore/html/HTMLFormControlElement.cpp
@@ -27,6 +27,7 @@
#include "ChromeClient.h"
#include "Document.h"
+#include "Event.h"
#include "EventHandler.h"
#include "EventNames.h"
#include "Frame.h"
@@ -38,7 +39,9 @@
#include "MappedAttribute.h"
#include "Page.h"
#include "RenderBox.h"
+#include "RenderTextControl.h"
#include "RenderTheme.h"
+#include "ScriptEventListener.h"
#include "ValidityState.h"
namespace WebCore {
@@ -50,6 +53,7 @@ HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Doc
, m_form(f)
, m_disabled(false)
, m_readOnly(false)
+ , m_required(false)
, m_valueMatchesRenderer(false)
{
if (!m_form)
@@ -64,6 +68,16 @@ HTMLFormControlElement::~HTMLFormControlElement()
m_form->removeFormElement(this);
}
+bool HTMLFormControlElement::formNoValidate() const
+{
+ return !getAttribute(formnovalidateAttr).isNull();
+}
+
+void HTMLFormControlElement::setFormNoValidate(bool formnovalidate)
+{
+ setAttribute(formnovalidateAttr, formnovalidate ? "" : 0);
+}
+
ValidityState* HTMLFormControlElement::validity()
{
if (!m_validityState)
@@ -74,9 +88,9 @@ ValidityState* HTMLFormControlElement::validity()
void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
{
- if (attr->name() == nameAttr) {
- // Do nothing.
- } else if (attr->name() == disabledAttr) {
+ if (attr->name() == nameAttr)
+ setNeedsStyleRecalc();
+ else if (attr->name() == disabledAttr) {
bool oldDisabled = m_disabled;
m_disabled = !attr->isNull();
if (oldDisabled != m_disabled) {
@@ -92,6 +106,11 @@ void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
if (renderer() && renderer()->style()->hasAppearance())
renderer()->theme()->stateChanged(renderer(), ReadOnlyState);
}
+ } else if (attr->name() == requiredAttr) {
+ bool oldRequired = m_required;
+ m_required = !attr->isNull();
+ if (oldRequired != m_required)
+ setNeedsStyleRecalc();
} else
HTMLElement::parseMappedAttribute(attr);
}
@@ -176,7 +195,7 @@ void HTMLFormControlElement::setName(const AtomicString &value)
void HTMLFormControlElement::dispatchFormControlChangeEvent()
{
- dispatchEvent(eventNames().changeEvent, true, false);
+ dispatchEvent(Event::create(eventNames().changeEvent, true, false));
}
bool HTMLFormControlElement::disabled() const
@@ -206,7 +225,7 @@ void HTMLFormControlElement::setAutofocus(bool b)
bool HTMLFormControlElement::required() const
{
- return hasAttribute(requiredAttr);
+ return m_required;
}
void HTMLFormControlElement::setRequired(bool b)
@@ -222,13 +241,19 @@ void HTMLFormControlElement::recalcStyle(StyleChange change)
renderer()->updateFromElement();
}
+bool HTMLFormControlElement::supportsFocus() const
+{
+ return !disabled();
+}
+
bool HTMLFormControlElement::isFocusable() const
{
- if (disabled() || !renderer() ||
- (renderer()->style() && renderer()->style()->visibility() != VISIBLE) ||
+ if (!renderer() ||
!renderer()->isBox() || toRenderBox(renderer())->size().isEmpty())
return false;
- return true;
+ // HTMLElement::isFocusable handles visibility and calls suportsFocus which
+ // will cover the disabled case.
+ return HTMLElement::isFocusable();
}
bool HTMLFormControlElement::isKeyboardFocusable(KeyboardEvent* event) const
@@ -260,7 +285,25 @@ bool HTMLFormControlElement::willValidate() const
// The control does not have a repetition template as an ancestor.
// The control does not have a datalist element as an ancestor.
// The control is not an output element.
- return form() && name().length() && !disabled() && !isReadOnlyFormControl();
+ return form() && !name().isEmpty() && !disabled() && !isReadOnlyFormControl();
+}
+
+bool HTMLFormControlElement::checkValidity()
+{
+ if (willValidate() && !isValidFormControlElement()) {
+ dispatchEvent(Event::create(EventNames().invalidEvent, false, true));
+ return false;
+ }
+
+ return true;
+}
+
+void HTMLFormControlElement::updateValidity()
+{
+ if (willValidate()) {
+ // Update style for pseudo classes such as :valid :invalid.
+ setNeedsStyleRecalc();
+ }
}
void HTMLFormControlElement::setCustomValidity(const String& error)
@@ -284,14 +327,19 @@ void HTMLFormControlElement::dispatchBlurEvent()
HTMLElement::dispatchBlurEvent();
}
-bool HTMLFormControlElement::supportsFocus() const
+HTMLFormElement* HTMLFormControlElement::virtualForm() const
{
- return isFocusable() || (!disabled() && !document()->haveStylesheetsLoaded());
+ return m_form;
}
-HTMLFormElement* HTMLFormControlElement::virtualForm() const
+bool HTMLFormControlElement::isDefaultButtonForForm() const
{
- return m_form;
+ return isSuccessfulSubmitButton() && m_form && m_form->defaultButton() == this;
+}
+
+bool HTMLFormControlElement::isValidFormControlElement()
+{
+ return validity()->valid();
}
void HTMLFormControlElement::removeFromForm()
@@ -336,4 +384,120 @@ void HTMLFormControlElementWithState::finishParsingChildren()
}
}
+HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* form)
+ : HTMLFormControlElementWithState(tagName, doc, form)
+{
+}
+
+HTMLTextFormControlElement::~HTMLTextFormControlElement()
+{
+}
+
+void HTMLTextFormControlElement::dispatchFocusEvent()
+{
+ if (supportsPlaceholder())
+ updatePlaceholderVisibility(false);
+ handleFocusEvent();
+ HTMLFormControlElementWithState::dispatchFocusEvent();
+}
+
+void HTMLTextFormControlElement::dispatchBlurEvent()
+{
+ if (supportsPlaceholder())
+ updatePlaceholderVisibility(false);
+ handleBlurEvent();
+ HTMLFormControlElementWithState::dispatchBlurEvent();
+}
+
+bool HTMLTextFormControlElement::placeholderShouldBeVisible() const
+{
+ return supportsPlaceholder()
+ && isEmptyValue()
+ && document()->focusedNode() != this
+ && !getAttribute(placeholderAttr).isEmpty();
+}
+
+void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
+{
+ if (supportsPlaceholder() && renderer())
+ toRenderTextControl(renderer())->updatePlaceholderVisibility(placeholderShouldBeVisible(), placeholderValueChanged);
+}
+
+RenderTextControl* HTMLTextFormControlElement::textRendererAfterUpdateLayout()
+{
+ if (!isTextFormControl())
+ return 0;
+ document()->updateLayoutIgnorePendingStylesheets();
+ return toRenderTextControl(renderer());
+}
+
+void HTMLTextFormControlElement::setSelectionStart(int start)
+{
+ if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
+ renderer->setSelectionStart(start);
+}
+
+void HTMLTextFormControlElement::setSelectionEnd(int end)
+{
+ if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
+ renderer->setSelectionEnd(end);
+}
+
+void HTMLTextFormControlElement::select()
+{
+ if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
+ renderer->select();
+}
+
+void HTMLTextFormControlElement::setSelectionRange(int start, int end)
+{
+ if (RenderTextControl* renderer = textRendererAfterUpdateLayout())
+ renderer->setSelectionRange(start, end);
+}
+
+int HTMLTextFormControlElement::selectionStart()
+{
+ if (!isTextFormControl())
+ return 0;
+ if (document()->focusedNode() != this && cachedSelectionStart() >= 0)
+ return cachedSelectionStart();
+ if (!renderer())
+ return 0;
+ return toRenderTextControl(renderer())->selectionStart();
+}
+
+int HTMLTextFormControlElement::selectionEnd()
+{
+ if (!isTextFormControl())
+ return 0;
+ if (document()->focusedNode() != this && cachedSelectionEnd() >= 0)
+ return cachedSelectionEnd();
+ if (!renderer())
+ return 0;
+ return toRenderTextControl(renderer())->selectionEnd();
+}
+
+VisibleSelection HTMLTextFormControlElement::selection() const
+{
+ if (!renderer() || !isTextFormControl() || cachedSelectionStart() < 0 || cachedSelectionEnd() < 0)
+ return VisibleSelection();
+ return toRenderTextControl(renderer())->selection(cachedSelectionStart(), cachedSelectionEnd());
+}
+
+void HTMLTextFormControlElement::parseMappedAttribute(MappedAttribute* attr)
+{
+ if (attr->name() == placeholderAttr)
+ updatePlaceholderVisibility(true);
+ else if (attr->name() == onfocusAttr)
+ setAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(this, attr));
+ else if (attr->name() == onblurAttr)
+ setAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(this, attr));
+ else if (attr->name() == onselectAttr)
+ setAttributeEventListener(eventNames().selectEvent, createAttributeEventListener(this, attr));
+ else if (attr->name() == onchangeAttr)
+ setAttributeEventListener(eventNames().changeEvent, createAttributeEventListener(this, attr));
+ else
+ HTMLFormControlElementWithState::parseMappedAttribute(attr);
+}
+
} // namespace Webcore