diff options
Diffstat (limited to 'WebCore/html/HTMLFormControlElement.cpp')
-rw-r--r-- | WebCore/html/HTMLFormControlElement.cpp | 190 |
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 |