Commit 8a6d7d4f authored by tkent@chromium.org's avatar tkent@chromium.org

2010-02-02 Kent Tamura <tkent@chromium.org>

        Reviewed by Darin Adler.

        Fix a bug that changes for some constraint attributes doesn't
        update validation CSS selectors.
        https://bugs.webkit.org/show_bug.cgi?id=31716

        Add tests for maxLength changes and step changes.

        * fast/forms/input-live-pseudo-selectors-expected.txt:
        * fast/forms/resources/input-live-pseudo-selectors.js:
        * fast/forms/resources/textarea-live-pseudo-selectors.js:
        * fast/forms/textarea-live-pseudo-selectors-expected.txt:

2010-02-02  Kent Tamura  <tkent@chromium.org>

        Reviewed by Darin Adler.

        Fix a bug that changes for some constraint attributes doesn't
        update validation CSS selectors.
        https://bugs.webkit.org/show_bug.cgi?id=31716

        - Rename HTMLFormControlElement::updateValidity() to setNeedsValidityCheck()
        - Introduce HTMLFormControlElement::setNeedsWillValidate()
        - Introduce HTMLFormControlElement::m_hasName to make willValidate()
          work in parseMappedAttribute().
        - We need to call setNeedsValidityCheck() when HTMLInputElement::step or
          HTMLTextAreaElement::maxLength is changed.

        * html/HTMLFormControlElement.cpp:
        (WebCore::HTMLFormControlElement::HTMLFormControlElement):
        (WebCore::HTMLFormControlElement::parseMappedAttribute):
        (WebCore::HTMLFormControlElement::insertedIntoTree):
        (WebCore::HTMLFormControlElement::removedFromTree):
        (WebCore::HTMLFormControlElement::formDestroyed):
        (WebCore::HTMLFormControlElement::willValidate): Avoids function calls.
        (WebCore::HTMLFormControlElement::setNeedsWillValidateCheck):
        (WebCore::HTMLFormControlElement::setNeedsValidityCheck):
        * html/HTMLFormControlElement.h:
        (WebCore::HTMLFormControlElement::disabled): Move the code from .cpp.
        * html/HTMLInputElement.cpp:
        (WebCore::HTMLInputElement::setInputType):
        (WebCore::HTMLInputElement::parseMappedAttribute):
        (WebCore::HTMLInputElement::setValue):
        (WebCore::HTMLInputElement::setValueFromRenderer):
        (WebCore::HTMLInputElement::setFileListFromRenderer):
        * html/HTMLTextAreaElement.cpp:
        (WebCore::HTMLTextAreaElement::parseMappedAttribute):
        (WebCore::HTMLTextAreaElement::setValue):
        * rendering/RenderTextControlMultiLine.cpp:
        (WebCore::RenderTextControlMultiLine::subtreeHasChanged):

git-svn-id: svn://svn.chromium.org/blink/trunk@54274 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent fc1b7e3b
2010-02-02 Kent Tamura <tkent@chromium.org>
Reviewed by Darin Adler.
Fix a bug that changes for some constraint attributes doesn't
update validation CSS selectors.
https://bugs.webkit.org/show_bug.cgi?id=31716
Add tests for maxLength changes and step changes.
* fast/forms/input-live-pseudo-selectors-expected.txt:
* fast/forms/resources/input-live-pseudo-selectors.js:
* fast/forms/resources/textarea-live-pseudo-selectors.js:
* fast/forms/textarea-live-pseudo-selectors-expected.txt:
2010-02-02 Roland Steiner <rolandsteiner@chromium.org>
Reviewed by Adele Peterson.
......
......@@ -30,6 +30,10 @@ Change pattern:
PASS backgroundOf(el) is validColor
PASS backgroundOf(el) is invalidColor
PASS backgroundOf(el) is validColor
Change step:
PASS backgroundOf(el) is validColor
PASS backgroundOf(el) is invalidColor
PASS backgroundOf(el) is validColor
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -98,5 +98,14 @@ shouldBe(elBackground, 'invalidColor');
el.pattern = 'a.c';
shouldBe(elBackground, 'validColor');
debug('Change step:');
el = makeInvalid();
el.value = '1';
el.type = 'number';
shouldBe(elBackground, 'validColor');
el.step = '2';
shouldBe(elBackground, 'invalidColor');
el.step = '0.5';
shouldBe(elBackground, 'validColor');
var successfullyParsed = true;
......@@ -89,5 +89,17 @@ shouldBe(elBackground, 'validColor');
el.required = true;
shouldBe(elBackground, 'invalidColor');
debug('Change maxlength:');
el = makeInvalid();
el.value = '1234567890';
shouldBe(elBackground, 'validColor');
// Make the value dirty by deleting the last character.
el.focus();
el.setSelectionRange(10, 10);
document.execCommand('delete');
el.maxLength = 5;
shouldBe(elBackground, 'invalidColor');
el.maxLength = 10;
shouldBe(elBackground, 'validColor');
var successfullyParsed = true;
......@@ -26,6 +26,10 @@ PASS backgroundOf(el) is invalidColor
Change required:
PASS backgroundOf(el) is validColor
PASS backgroundOf(el) is invalidColor
Change maxlength:
PASS backgroundOf(el) is validColor
PASS backgroundOf(el) is invalidColor
PASS backgroundOf(el) is validColor
PASS successfullyParsed is true
TEST COMPLETE
......
2010-02-02 Kent Tamura <tkent@chromium.org>
Reviewed by Darin Adler.
Fix a bug that changes for some constraint attributes doesn't
update validation CSS selectors.
https://bugs.webkit.org/show_bug.cgi?id=31716
- Rename HTMLFormControlElement::updateValidity() to setNeedsValidityCheck()
- Introduce HTMLFormControlElement::setNeedsWillValidate()
- Introduce HTMLFormControlElement::m_hasName to make willValidate()
work in parseMappedAttribute().
- We need to call setNeedsValidityCheck() when HTMLInputElement::step or
HTMLTextAreaElement::maxLength is changed.
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::HTMLFormControlElement):
(WebCore::HTMLFormControlElement::parseMappedAttribute):
(WebCore::HTMLFormControlElement::insertedIntoTree):
(WebCore::HTMLFormControlElement::removedFromTree):
(WebCore::HTMLFormControlElement::formDestroyed):
(WebCore::HTMLFormControlElement::willValidate): Avoids function calls.
(WebCore::HTMLFormControlElement::setNeedsWillValidateCheck):
(WebCore::HTMLFormControlElement::setNeedsValidityCheck):
* html/HTMLFormControlElement.h:
(WebCore::HTMLFormControlElement::disabled): Move the code from .cpp.
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setInputType):
(WebCore::HTMLInputElement::parseMappedAttribute):
(WebCore::HTMLInputElement::setValue):
(WebCore::HTMLInputElement::setValueFromRenderer):
(WebCore::HTMLInputElement::setFileListFromRenderer):
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::parseMappedAttribute):
(WebCore::HTMLTextAreaElement::setValue):
* rendering/RenderTextControlMultiLine.cpp:
(WebCore::RenderTextControlMultiLine::subtreeHasChanged):
2010-02-02 Roland Steiner <rolandsteiner@chromium.org>
Reviewed by Adele Peterson.
......
......@@ -52,6 +52,7 @@ using namespace HTMLNames;
HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLElement(tagName, doc)
, m_form(f)
, m_hasName(false)
, m_disabled(false)
, m_readOnly(false)
, m_required(false)
......@@ -89,8 +90,9 @@ ValidityState* HTMLFormControlElement::validity()
void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
{
bool oldWillValidate = willValidate();
if (attr->name() == nameAttr)
setNeedsStyleRecalc();
m_hasName = !attr->isEmpty();
else if (attr->name() == disabledAttr) {
bool oldDisabled = m_disabled;
m_disabled = !attr->isNull();
......@@ -114,6 +116,8 @@ void HTMLFormControlElement::parseMappedAttribute(MappedAttribute *attr)
setNeedsStyleRecalc();
} else
HTMLElement::parseMappedAttribute(attr);
if (oldWillValidate != willValidate())
setNeedsWillValidateCheck();
}
void HTMLFormControlElement::attach()
......@@ -149,9 +153,10 @@ void HTMLFormControlElement::insertedIntoTree(bool deep)
// setting a form, we will already have a non-null value for m_form,
// and so we don't need to do anything.
m_form = findFormAncestor();
if (m_form)
if (m_form) {
m_form->registerFormElement(this);
else
setNeedsWillValidateCheck();
} else
document()->checkedRadioButtons().addButton(this);
}
......@@ -178,11 +183,19 @@ void HTMLFormControlElement::removedFromTree(bool deep)
if (m_form && !(parser && parser->isHandlingResidualStyleAcrossBlocks()) && findRoot(this) != findRoot(m_form)) {
m_form->removeFormElement(this);
m_form = 0;
setNeedsWillValidateCheck();
}
HTMLElement::removedFromTree(deep);
}
void HTMLFormControlElement::formDestroyed()
{
if (m_form)
setNeedsWillValidateCheck();
m_form = 0;
}
const AtomicString& HTMLFormControlElement::formControlName() const
{
const AtomicString& n = getAttribute(nameAttr);
......@@ -199,11 +212,6 @@ void HTMLFormControlElement::dispatchFormControlChangeEvent()
dispatchEvent(Event::create(eventNames().changeEvent, true, false));
}
bool HTMLFormControlElement::disabled() const
{
return m_disabled;
}
void HTMLFormControlElement::setDisabled(bool b)
{
setAttribute(disabledAttr, b ? "" : 0);
......@@ -297,7 +305,7 @@ 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().isEmpty() && !disabled() && !isReadOnlyFormControl();
return m_form && m_hasName && !m_disabled && !m_readOnly;
}
String HTMLFormControlElement::validationMessage()
......@@ -305,6 +313,12 @@ String HTMLFormControlElement::validationMessage()
return validity()->validationMessage();
}
void HTMLFormControlElement::setNeedsWillValidateCheck()
{
setNeedsStyleRecalc();
// FIXME: Show/hide a validation message.
}
bool HTMLFormControlElement::checkValidity()
{
if (willValidate() && !isValidFormControlElement()) {
......@@ -315,12 +329,13 @@ bool HTMLFormControlElement::checkValidity()
return true;
}
void HTMLFormControlElement::updateValidity()
void HTMLFormControlElement::setNeedsValidityCheck()
{
if (willValidate()) {
// Update style for pseudo classes such as :valid :invalid.
setNeedsStyleRecalc();
}
// FIXME: show/hide a validation message.
}
void HTMLFormControlElement::setCustomValidity(const String& error)
......
......@@ -63,7 +63,7 @@ public:
virtual void dispatchFormControlChangeEvent();
bool disabled() const;
bool disabled() const { return m_disabled; }
void setDisabled(bool);
virtual bool supportsFocus() const;
......@@ -109,19 +109,22 @@ public:
virtual bool willValidate() const;
String validationMessage();
bool checkValidity();
void updateValidity();
// This must be called when a validation constraint or control value is changed.
void setNeedsValidityCheck();
void setCustomValidity(const String&);
virtual bool valueMissing() const { return false; }
virtual bool patternMismatch() const { return false; }
virtual bool tooLong() const { return false; }
void formDestroyed() { m_form = 0; }
void formDestroyed();
virtual void dispatchFocusEvent();
virtual void dispatchBlurEvent();
protected:
void removeFromForm();
// This must be called any time the result of willValidate() has changed.
void setNeedsWillValidateCheck();
private:
virtual HTMLFormElement* virtualForm() const;
......@@ -130,6 +133,7 @@ private:
HTMLFormElement* m_form;
OwnPtr<ValidityState> m_validityState;
bool m_hasName : 1;
bool m_disabled : 1;
bool m_readOnly : 1;
bool m_required : 1;
......
......@@ -713,6 +713,7 @@ void HTMLInputElement::setInputType(const String& t)
// type change, otherwise a JavaScript programmer would be able to set a text
// field's value to something like /etc/passwd and then change it to a file field.
if (inputType() != newType) {
bool oldWillValidate = willValidate();
if (newType == FILE && m_haveType)
// Set the attribute back to the old value.
// Useful in case we were called from inside parseMappedAttribute.
......@@ -769,8 +770,10 @@ void HTMLInputElement::setInputType(const String& t)
checkedRadioButtons(this).addButton(this);
}
setNeedsValidityCheck();
if (oldWillValidate != willValidate())
setNeedsWillValidateCheck();
InputElement::notifyFormStateChanged(this);
updateValidity();
}
m_haveType = true;
......@@ -992,17 +995,18 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
if (m_data.value().isNull())
setNeedsStyleRecalc();
setFormControlValueMatchesRenderer(false);
updateValidity();
setNeedsValidityCheck();
} else if (attr->name() == checkedAttr) {
m_defaultChecked = !attr->isNull();
if (m_useDefaultChecked) {
setChecked(m_defaultChecked);
m_useDefaultChecked = true;
}
updateValidity();
} else if (attr->name() == maxlengthAttr)
setNeedsValidityCheck();
} else if (attr->name() == maxlengthAttr) {
InputElement::parseMaxLengthAttribute(m_data, this, this, attr);
else if (attr->name() == sizeAttr)
setNeedsValidityCheck();
} else if (attr->name() == sizeAttr)
InputElement::parseSizeAttribute(m_data, this, attr);
else if (attr->name() == altAttr) {
if (renderer() && inputType() == IMAGE)
......@@ -1046,15 +1050,16 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
attach();
}
setNeedsStyleRecalc();
} else if (attr->name() == autosaveAttr ||
attr->name() == incrementalAttr ||
attr->name() == minAttr ||
attr->name() == maxAttr ||
attr->name() == multipleAttr ||
attr->name() == precisionAttr)
} else if (attr->name() == autosaveAttr
|| attr->name() == incrementalAttr)
setNeedsStyleRecalc();
else if (attr->name() == patternAttr)
updateValidity();
else if (attr->name() == minAttr
|| attr->name() == maxAttr
|| attr->name() == multipleAttr
|| attr->name() == patternAttr
|| attr->name() == precisionAttr
|| attr->name() == stepAttr)
setNeedsValidityCheck();
#if ENABLE(DATALIST)
else if (attr->name() == listAttr)
m_hasNonEmptyList = !attr->isEmpty();
......@@ -1496,7 +1501,7 @@ void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
dispatchFormControlChangeEvent();
InputElement::notifyFormStateChanged(this);
updateValidity();
setNeedsValidityCheck();
}
double HTMLInputElement::parseToDouble(const String& src, double defaultValue) const
......@@ -1770,7 +1775,7 @@ void HTMLInputElement::setValueFromRenderer(const String& value)
m_data.setSuggestedValue(String());
updatePlaceholderVisibility(false);
InputElement::setValueFromRenderer(m_data, this, this, value);
updateValidity();
setNeedsValidityCheck();
}
void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
......@@ -1782,7 +1787,7 @@ void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
setFormControlValueMatchesRenderer(true);
InputElement::notifyFormStateChanged(this);
updateValidity();
setNeedsValidityCheck();
}
bool HTMLInputElement::storesValueSeparateFromAttribute() const
......
......@@ -150,7 +150,9 @@ void HTMLTextAreaElement::parseMappedAttribute(MappedAttribute* attr)
} else if (attr->name() == alignAttr) {
// Don't map 'align' attribute. This matches what Firefox, Opera and IE do.
// See http://bugs.webkit.org/show_bug.cgi?id=7075
} else
} else if (attr->name() == maxlengthAttr)
setNeedsValidityCheck();
else
HTMLTextFormControlElement::parseMappedAttribute(attr);
}
......@@ -297,9 +299,8 @@ void HTMLTextAreaElement::setValue(const String& value)
setSelectionRange(endOfString, endOfString);
}
setNeedsStyleRecalc();
setNeedsValidityCheck();
notifyFormStateChanged(this);
updateValidity();
}
String HTMLTextAreaElement::defaultValue() const
......
......@@ -47,7 +47,7 @@ void RenderTextControlMultiLine::subtreeHasChanged()
RenderTextControl::subtreeHasChanged();
HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(node());
textArea->setFormControlValueMatchesRenderer(false);
textArea->updateValidity();
textArea->setNeedsValidityCheck();
if (!node()->focused())
return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment