2010-12-09 Dai Mikurube <dmikurube@google.com>
Reviewed by Kent Tamura.
Implement "required" attribute for select tags
https://bugs.webkit.org/show_bug.cgi?id=50380
Added tests for require attributes, valueMissing and vadility check for select elements.
* fast/forms/ValidityState-valueMissing-001-expected.txt:
* fast/forms/ValidityState-valueMissing-001.html:
* fast/forms/ValidityState-valueMissing-002-expected.txt:
* fast/forms/ValidityState-valueMissing-002.html:
* fast/forms/ValidityState-valueMissing-003-expected.txt:
* fast/forms/ValidityState-valueMissing-003.html:
* fast/forms/checkValidity-002-expected.txt:
* fast/forms/checkValidity-002.html:
* fast/forms/required-attribute-001-expected.txt:
* fast/forms/required-attribute-001.html:
* fast/forms/required-attribute-002-expected.txt:
* fast/forms/required-attribute-002.html:
* fast/forms/resources/select-live-pseudo-selectors.js: Added.
(makeInvalid):
(appendOption):
(backgroundOf):
* fast/forms/script-tests/validationMessage.js:
* fast/forms/select-live-pseudo-selectors-expected.txt: Added.
* fast/forms/select-live-pseudo-selectors.html: Added.
* fast/forms/validationMessage-expected.txt:
* platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html: Added.
* platform/mac/fast/objc/dom-html-select-live-pseudo-selectors-expected.txt: Added.
2010-12-09 Dai Mikurube <dmikurube@google.com>
Reviewed by Kent Tamura.
Implement "required" attribute for select tags
https://bugs.webkit.org/show_bug.cgi?id=50380
Test: fast/forms/select-live-pseudo-selectors.html
platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html
* dom/SelectElement.cpp:
(WebCore::SelectElement::updateValidity): Added. It's a pure virtual function which is prepared so that HTMLSelectElement::updateValidity() calls HTMLSelectElement::setNeedsValidityCheck().
(WebCore::SelectElement::parseMultipleAttribute): Added calling updateValidity().
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::deselectItems): Added calling setNeedsValidityCheck() to enable validity check after changing. No tests for this change since this function is not exposed to JavaScript or any web interface.
(WebCore::HTMLSelectElement::setSelectedIndex): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::setSelectedIndexByUser): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::valueMissing): Added valueMissing() to check if selecting an invalid or placeholder label option when a valid required attribute is specified.
(WebCore::HTMLSelectElement::listBoxSelectItem): Added calling setNeedsValidityCheck(). No tests for this change since it is not called yet. Look at the bug 36177 and the changeset 56180.
(WebCore::HTMLSelectElement::add): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::remove): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::restoreFormControlState): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::parseMappedAttribute): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::selectAll): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::reset): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::updateListBoxSelection): Added calling setNeedsValidityCheck(). Skipped adding tests for this change as too complicated..
(WebCore::HTMLSelectElement::setLength): Added calling setNeedsValidityCheck().
(WebCore::HTMLSelectElement::isRequiredFormControl): Check if required or not.
(WebCore::HTMLSelectElement::hasPlaceholderLabelOption): Added.
(WebCore::HTMLSelectElement::updateValidity): Added. It calls setNeedsValidityCheck().
* html/HTMLSelectElement.h:
(WebCore::HTMLSelectElement::isOptionalFormControl): Check if not required.
* html/HTMLSelectElement.idl: Added a required attribute to select elements..
* html/ValidityState.cpp:
(WebCore::ValidityState::valueMissing): Added valueMissing check for select elements into the global checker, ValidityState::valueMissing().
* wml/WMLSelectElement.h:
(WebCore::WMLSelectElement::updateValidity): Added. It does nothing.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73606 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 6bb06da..18287ef 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,35 @@
+2010-12-09 Dai Mikurube <dmikurube@google.com>
+
+ Reviewed by Kent Tamura.
+
+ Implement "required" attribute for select tags
+ https://bugs.webkit.org/show_bug.cgi?id=50380
+
+ Added tests for require attributes, valueMissing and vadility check for select elements.
+
+ * fast/forms/ValidityState-valueMissing-001-expected.txt:
+ * fast/forms/ValidityState-valueMissing-001.html:
+ * fast/forms/ValidityState-valueMissing-002-expected.txt:
+ * fast/forms/ValidityState-valueMissing-002.html:
+ * fast/forms/ValidityState-valueMissing-003-expected.txt:
+ * fast/forms/ValidityState-valueMissing-003.html:
+ * fast/forms/checkValidity-002-expected.txt:
+ * fast/forms/checkValidity-002.html:
+ * fast/forms/required-attribute-001-expected.txt:
+ * fast/forms/required-attribute-001.html:
+ * fast/forms/required-attribute-002-expected.txt:
+ * fast/forms/required-attribute-002.html:
+ * fast/forms/resources/select-live-pseudo-selectors.js: Added.
+ (makeInvalid):
+ (appendOption):
+ (backgroundOf):
+ * fast/forms/script-tests/validationMessage.js:
+ * fast/forms/select-live-pseudo-selectors-expected.txt: Added.
+ * fast/forms/select-live-pseudo-selectors.html: Added.
+ * fast/forms/validationMessage-expected.txt:
+ * platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html: Added.
+ * platform/mac/fast/objc/dom-html-select-live-pseudo-selectors-expected.txt: Added.
+
2010-12-07 Jeremy Orlow <jorlow@chromium.org>
Reviewed by Steve Block.
diff --git a/LayoutTests/fast/forms/ValidityState-valueMissing-001-expected.txt b/LayoutTests/fast/forms/ValidityState-valueMissing-001-expected.txt
index b069a74..11f45af 100644
--- a/LayoutTests/fast/forms/ValidityState-valueMissing-001-expected.txt
+++ b/LayoutTests/fast/forms/ValidityState-valueMissing-001-expected.txt
@@ -1,4 +1,24 @@
-There are two form control elements below, both required and blank: validity.valueMissing should be true in both cases.
+This test checks validity.valueMissing with blank values, blank options selected, or nothing selected.
-
-SUCCESS
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS valueMissingFor("input") is true
+PASS valueMissingFor("textarea") is true
+PASS valueMissingFor("select-no-option") is true
+PASS valueMissingFor("select-placeholder-selected") is true
+PASS valueMissingFor("select-without-placeholder") is false
+PASS valueMissingFor("select-placeholder-selected-size2") is false
+PASS valueMissingFor("select-without-placeholder-size2") is false
+PASS valueMissingFor("select-none-selected-multiple") is true
+PASS valueMissingFor("select-fake-placeholder-selected-multiple") is false
+PASS valueMissingFor("select-without-fake-placeholder-multiple") is false
+PASS valueMissingFor("select-none-selected-size2-multiple") is true
+PASS valueMissingFor("select-fake-placeholder-selected-size2-multiple") is false
+PASS valueMissingFor("select-without-fake-placeholder-size2-multiple") is false
+PASS valueMissingFor("select-optgroup") is false
+PASS valueMissingFor("select-disabled-option") is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/ValidityState-valueMissing-001.html b/LayoutTests/fast/forms/ValidityState-valueMissing-001.html
index dc88879..608c89e 100644
--- a/LayoutTests/fast/forms/ValidityState-valueMissing-001.html
+++ b/LayoutTests/fast/forms/ValidityState-valueMissing-001.html
@@ -1,27 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>required and basic valueMissing</title>
-<script language="JavaScript" type="text/javascript">
- function log(message) {
- document.getElementById("console").innerHTML += "<li>"+message+"</li>";
- }
-
- function test() {
- if (window.layoutTestController)
- layoutTestController.dumpAsText();
-
- v = document.getElementsByName("victim");
-
- log((v[0].validity.valueMissing && v[1].validity.valueMissing) ? "SUCCESS" : "FAILURE");
- }
-</script>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
</head>
-<body onload="test()">
-<p>There are two form control elements below, both required and blank:
-validity.valueMissing should be true in both cases.</p>
-<input name="victim" required/>
-<textarea name="victim" required></textarea>
-<hr>
-<ol id="console"></ol>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<input id="input" name="victim" required/>
+<textarea id="textarea" name="victim" required></textarea>
+<select id="select-no-option" name="victim" required>
+</select>
+<select id="select-placeholder-selected" name="victim" required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-placeholder" name="victim" required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-placeholder-selected-size2" name="victim" size="2" required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-placeholder-size2" name="victim" size="2" required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-none-selected-multiple" name="victim" multiple required>
+ <option value="" />
+ <option value="X">X</option>
+</select>
+<select id="select-fake-placeholder-selected-multiple" name="victim" multiple required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-fake-placeholder-multiple" name="victim" multiple required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-none-selected-size2-multiple" name="victim" multiple size="2" required>
+ <option value="" />
+ <option value="X">X</option>
+</select>
+<select id="select-fake-placeholder-selected-size2-multiple" name="victim" multiple size="2" required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-fake-placeholder-size2-multiple" name="victim" multiple size="2" required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-optgroup" name="victim" required>
+ <optgroup label="1">
+ <option value="" selected />
+ </optgroup>
+ <option value="X">X</option>
+</select>
+<select id="select-disabled-option" name="victim" required>
+ <option value="" disabled selected />
+ <option value="X">X</option>
+</select>
+<script language="JavaScript" type="text/javascript">
+ function valueMissingFor(id) {
+ return document.getElementById(id).validity.valueMissing;
+ }
+
+ description("This test checks validity.valueMissing with blank values, blank options selected, or nothing selected.");
+
+ v = document.getElementsByName("victim");
+
+ shouldBeTrue('valueMissingFor("input")');
+ shouldBeTrue('valueMissingFor("textarea")');
+ shouldBeTrue('valueMissingFor("select-no-option")');
+ shouldBeTrue('valueMissingFor("select-placeholder-selected")');
+ shouldBeFalse('valueMissingFor("select-without-placeholder")');
+ shouldBeFalse('valueMissingFor("select-placeholder-selected-size2")');
+ shouldBeFalse('valueMissingFor("select-without-placeholder-size2")');
+ shouldBeTrue('valueMissingFor("select-none-selected-multiple")');
+ shouldBeFalse('valueMissingFor("select-fake-placeholder-selected-multiple")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-multiple")');
+ shouldBeTrue('valueMissingFor("select-none-selected-size2-multiple")');
+ shouldBeFalse('valueMissingFor("select-fake-placeholder-selected-size2-multiple")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-size2-multiple")');
+ shouldBeFalse('valueMissingFor("select-optgroup")');
+ shouldBeFalse('valueMissingFor("select-disabled-option")');
+
+ var successfullyParsed = true;
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
</body>
</html>
diff --git a/LayoutTests/fast/forms/ValidityState-valueMissing-002-expected.txt b/LayoutTests/fast/forms/ValidityState-valueMissing-002-expected.txt
index 36069b8..bcb2a84 100644
--- a/LayoutTests/fast/forms/ValidityState-valueMissing-002-expected.txt
+++ b/LayoutTests/fast/forms/ValidityState-valueMissing-002-expected.txt
@@ -1,4 +1,19 @@
-There are two form control elements below, both required and with some value: validity.valueMissing should be false in both cases.
+This test checks validity.valueMissing with some values or options with some values selected.
-
-SUCCESS
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS valueMissingFor("input") is false
+PASS valueMissingFor("textarea") is false
+PASS valueMissingFor("select-with-placeholder") is false
+PASS valueMissingFor("select-without-placeholder") is false
+PASS valueMissingFor("select-with-fake-placeholder-size2") is false
+PASS valueMissingFor("select-without-fake-placeholder-size2") is false
+PASS valueMissingFor("select-with-fake-placeholder-multiple") is false
+PASS valueMissingFor("select-without-fake-placeholder-multiple") is false
+PASS valueMissingFor("select-with-fake-placeholder-size2-multiple") is false
+PASS valueMissingFor("select-without-fake-placeholder-size2-multiple") is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/ValidityState-valueMissing-002.html b/LayoutTests/fast/forms/ValidityState-valueMissing-002.html
index 6f06f9f..705f022 100644
--- a/LayoutTests/fast/forms/ValidityState-valueMissing-002.html
+++ b/LayoutTests/fast/forms/ValidityState-valueMissing-002.html
@@ -1,27 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>required and basic valueMissing 2</title>
-<script language="JavaScript" type="text/javascript">
- function log(message) {
- document.getElementById("console").innerHTML += "<li>"+message+"</li>";
- }
-
- function test() {
- if (window.layoutTestController)
- layoutTestController.dumpAsText();
-
- v = document.getElementsByName("victim");
-
- log((!v[0].validity.valueMissing && !v[1].validity.valueMissing) ? "SUCCESS" : "FAILURE");
- }
-</script>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
</head>
-<body onload="test()">
-<p>There are two form control elements below, both required and with some value:
-validity.valueMissing should be false in both cases.</p>
-<input name="victim" value="something" required/>
-<textarea name="victim" required>something</textarea>
-<hr>
-<ol id="console"></ol>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<input id="input" name="victim" value="something" required/>
+<textarea id="textarea" name="victim" required>something</textarea>
+<select id="select-with-placeholder" name="victim" required>
+ <option value="" />
+ <option value="X" selected>X</option>
+</select>
+<select id="select-without-placeholder" name="victim" required>
+ <option value="X" selected>X</option>
+ <option value="" />
+</select>
+<select id="select-with-fake-placeholder-size2" name="victim" size="2" required>
+ <option value="" />
+ <option value="X" selected>X</option>
+</select>
+<select id="select-without-fake-placeholder-size2" name="victim" size="2" required>
+ <option value="X" selected>X</option>
+ <option value="" />
+</select>
+<select id="select-with-fake-placeholder-multiple" name="victim" multiple required>
+ <option value="" />
+ <option value="X" selected>X</option>
+</select>
+<select id="select-without-fake-placeholder-multiple" name="victim" multiple required>
+ <option value="X" selected>X</option>
+ <option value="" />
+</select>
+<select id="select-with-fake-placeholder-size2-multiple" name="victim" multiple size="2" required>
+ <option value="" />
+ <option value="X" selected>X</option>
+</select>
+<select id="select-without-fake-placeholder-size2-multiple" name="victim" multiple size="2" required>
+ <option value="X" selected>X</option>
+ <option value="" />
+</select>
+<script language="JavaScript" type="text/javascript">
+ function valueMissingFor(id) {
+ return document.getElementById(id).validity.valueMissing;
+ }
+
+ description("This test checks validity.valueMissing with some values or options with some values selected.");
+
+ v = document.getElementsByName("victim");
+
+ shouldBeFalse('valueMissingFor("input")');
+ shouldBeFalse('valueMissingFor("textarea")');
+ shouldBeFalse('valueMissingFor("select-with-placeholder")');
+ shouldBeFalse('valueMissingFor("select-without-placeholder")');
+ shouldBeFalse('valueMissingFor("select-with-fake-placeholder-size2")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-size2")');
+ shouldBeFalse('valueMissingFor("select-with-fake-placeholder-multiple")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-multiple")');
+ shouldBeFalse('valueMissingFor("select-with-fake-placeholder-size2-multiple")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-size2-multiple")');
+
+ var successfullyParsed = true;
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
</body>
</html>
diff --git a/LayoutTests/fast/forms/ValidityState-valueMissing-003-expected.txt b/LayoutTests/fast/forms/ValidityState-valueMissing-003-expected.txt
index dfe3398..63bdcc1 100644
--- a/LayoutTests/fast/forms/ValidityState-valueMissing-003-expected.txt
+++ b/LayoutTests/fast/forms/ValidityState-valueMissing-003-expected.txt
@@ -1,4 +1,22 @@
-There are two disabled form control elements below, both required and with some value: validity.valueMissing should be false in both cases.
+This test checks validity.valueMissing of disabled form controls with blank values, blank options selected, or nothing selected.
-
-SUCCESS
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS valueMissingFor("input") is false
+PASS valueMissingFor("textarea") is false
+PASS valueMissingFor("select-no-option") is false
+PASS valueMissingFor("select-placeholder-selected") is false
+PASS valueMissingFor("select-without-placeholder") is false
+PASS valueMissingFor("select-placeholder-selected-size2") is false
+PASS valueMissingFor("select-without-placeholder-size2") is false
+PASS valueMissingFor("select-none-selected-multiple") is false
+PASS valueMissingFor("select-fake-placeholder-selected-multiple") is false
+PASS valueMissingFor("select-without-fake-placeholder-multiple") is false
+PASS valueMissingFor("select-none-selected-size2-multiple") is false
+PASS valueMissingFor("select-fake-placeholder-selected-size2-multiple") is false
+PASS valueMissingFor("select-without-fake-placeholder-size2-multiple") is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/ValidityState-valueMissing-003.html b/LayoutTests/fast/forms/ValidityState-valueMissing-003.html
index 9d92ffb..9eb0f63 100644
--- a/LayoutTests/fast/forms/ValidityState-valueMissing-003.html
+++ b/LayoutTests/fast/forms/ValidityState-valueMissing-003.html
@@ -1,27 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>required and valueMissing on disabled elements</title>
-<script language="JavaScript" type="text/javascript">
- function log(message) {
- document.getElementById("console").innerHTML += "<li>"+message+"</li>";
- }
-
- function test() {
- if (window.layoutTestController)
- layoutTestController.dumpAsText();
-
- v = document.getElementsByName("victim");
-
- log((!v[0].validity.valueMissing && !v[1].validity.valueMissing) ? "SUCCESS" : "FAILURE");
- }
-</script>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
</head>
-<body onload="test()">
-<p>There are two disabled form control elements below, both required and with some value:
-validity.valueMissing should be false in both cases.</p>
-<input name="victim" disabled required />
-<textarea name="victim" disabled required></textarea>
-<hr>
-<ol id="console"></ol>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<input id="input" name="victim" disabled required />
+<textarea id="textarea" name="victim" disabled required></textarea>
+<select id="select-no-option" name="victim" disabled required>
+</select>
+<select id="select-placeholder-selected" name="victim" disabled required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-placeholder" name="victim" disabled required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-placeholder-selected-size2" name="victim" size="2" disabled required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-placeholder-size2" name="victim" size="2" disabled required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-none-selected-multiple" name="victim" multiple disabled required>
+ <option value="" />
+ <option value="X">X</option>
+</select>
+<select id="select-fake-placeholder-selected-multiple" name="victim" multiple disabled required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-fake-placeholder-multiple" name="victim" multiple disabled required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<select id="select-none-selected-size2-multiple" name="victim" multiple size="2" disabled required>
+ <option value="" />
+ <option value="X">X</option>
+</select>
+<select id="select-fake-placeholder-selected-size2-multiple" name="victim" multiple size="2" disabled required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-without-fake-placeholder-size2-multiple" name="victim" multiple size="2" disabled required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
+<script language="JavaScript" type="text/javascript">
+ function valueMissingFor(id) {
+ return document.getElementById(id).validity.valueMissing;
+ }
+
+ description("This test checks validity.valueMissing of disabled form controls with blank values, blank options selected, or nothing selected.");
+
+ v = document.getElementsByName("victim");
+
+ shouldBeFalse('valueMissingFor("input")');
+ shouldBeFalse('valueMissingFor("textarea")');
+ shouldBeFalse('valueMissingFor("select-no-option")');
+ shouldBeFalse('valueMissingFor("select-placeholder-selected")');
+ shouldBeFalse('valueMissingFor("select-without-placeholder")');
+ shouldBeFalse('valueMissingFor("select-placeholder-selected-size2")');
+ shouldBeFalse('valueMissingFor("select-without-placeholder-size2")');
+ shouldBeFalse('valueMissingFor("select-none-selected-multiple")');
+ shouldBeFalse('valueMissingFor("select-fake-placeholder-selected-multiple")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-multiple")');
+ shouldBeFalse('valueMissingFor("select-none-selected-size2-multiple")');
+ shouldBeFalse('valueMissingFor("select-fake-placeholder-selected-size2-multiple")');
+ shouldBeFalse('valueMissingFor("select-without-fake-placeholder-size2-multiple")');
+
+ var successfullyParsed = true;
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
</body>
</html>
diff --git a/LayoutTests/fast/forms/checkValidity-002-expected.txt b/LayoutTests/fast/forms/checkValidity-002-expected.txt
index 1857944..8388828 100644
--- a/LayoutTests/fast/forms/checkValidity-002-expected.txt
+++ b/LayoutTests/fast/forms/checkValidity-002-expected.txt
@@ -1,12 +1,14 @@
-This test checks if checkValidity() returns correctly a false (meaning error) result on invalid elements.
+This test checks if checkValidity() returns correctly a false (meaning error) result on invalid elements, and returns a true result on a blank but valid elements. Blank but non-placeholder label options are valid.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-PASS v[i].checkValidity() is false
-PASS v[i].checkValidity() is false
-PASS v[i].checkValidity() is false
+
+PASS checkValidityFor("input-empty") is false
+PASS checkValidityFor("input-pattern-mismatch") is false
+PASS checkValidityFor("textarea") is false
+PASS checkValidityFor("select-placeholder") is false
+PASS checkValidityFor("select-non-placeholder") is true
PASS successfullyParsed is true
TEST COMPLETE
diff --git a/LayoutTests/fast/forms/checkValidity-002.html b/LayoutTests/fast/forms/checkValidity-002.html
index 2872fad..662f6eb 100644
--- a/LayoutTests/fast/forms/checkValidity-002.html
+++ b/LayoutTests/fast/forms/checkValidity-002.html
@@ -7,19 +7,33 @@
<body>
<p id="description"></p>
<form method="get">
-<input name="victim" type="text" required/>
-<input name="victim" type="text" pattern="Lorem ipsum" value="Loremipsum"/>
-<textarea name="victim" required></textarea>
+<input id="input-empty" name="victim" type="text" required/>
+<input id="input-pattern-mismatch" name="victim" type="text" pattern="Lorem ipsum" value="Loremipsum"/>
+<textarea id="textarea" name="victim" required></textarea>
+<select id="select-placeholder" name="victim" required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<select id="select-non-placeholder" name="victim" required>
+ <option value="X">X</option>
+ <option value="" selected />
+</select>
</form>
<div id="console"></div>
<script>
-description("This test checks if checkValidity() returns correctly a false (meaning error) result on invalid elements.");
+ function checkValidityFor(id) {
+ return document.getElementById(id).checkValidity();
+ }
-v = document.getElementsByName("victim");
-for (i = 0; i < v.length; i++)
- shouldBe("v[i].checkValidity()", "false");
+ description("This test checks if checkValidity() returns correctly a false (meaning error) result on invalid elements, and returns a true result on a blank but valid elements. Blank but non-placeholder label options are valid.");
-var successfullyParsed = true;
+ shouldBeFalse('checkValidityFor("input-empty")');
+ shouldBeFalse('checkValidityFor("input-pattern-mismatch")');
+ shouldBeFalse('checkValidityFor("textarea")');
+ shouldBeFalse('checkValidityFor("select-placeholder")');
+ shouldBeTrue('checkValidityFor("select-non-placeholder")');
+
+ var successfullyParsed = true;
</script>
<script src="../js/resources/js-test-post.js"></script>
</body>
diff --git a/LayoutTests/fast/forms/required-attribute-001-expected.txt b/LayoutTests/fast/forms/required-attribute-001-expected.txt
index 9b20143..b9b54b8 100644
--- a/LayoutTests/fast/forms/required-attribute-001-expected.txt
+++ b/LayoutTests/fast/forms/required-attribute-001-expected.txt
@@ -1,4 +1,12 @@
-There are two form control elements below, both required.
+There are three form control elements below, all required.
-
-SUCCESS
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS requiredFor("input") is true
+PASS requiredFor("textarea") is true
+PASS requiredFor("select") is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/required-attribute-001.html b/LayoutTests/fast/forms/required-attribute-001.html
index 2f34c16..8aea57c 100644
--- a/LayoutTests/fast/forms/required-attribute-001.html
+++ b/LayoutTests/fast/forms/required-attribute-001.html
@@ -1,26 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>required attribute presence test</title>
-<script language="JavaScript" type="text/javascript">
- function log(message) {
- document.getElementById("console").innerHTML += "<li>"+message+"</li>";
- }
-
- function test() {
- if (window.layoutTestController)
- layoutTestController.dumpAsText();
-
- v = document.getElementsByName("victim");
-
- log((v[0].required && v[1].required) ? "SUCCESS" : "FAILURE");
- }
-</script>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
</head>
-<body onload="test()">
-<p>There are two form control elements below, both required.</p>
-<input name="victim" required />
-<textarea name="victim" required></textarea>
-<hr>
-<ol id="console"></ol>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<input id="input" name="victim" required />
+<textarea id="textarea" name="victim" required></textarea>
+<select id="select" name="victim" required>
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<script language="JavaScript" type="text/javascript">
+ function requiredFor(id) {
+ return document.getElementById(id).required;
+ }
+
+ description("There are three form control elements below, all required.");
+
+ v = document.getElementsByName("victim");
+
+ shouldBeTrue('requiredFor("input")');
+ shouldBeTrue('requiredFor("textarea")');
+ shouldBeTrue('requiredFor("select")');
+
+ var successfullyParsed = true;
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
</body>
</html>
diff --git a/LayoutTests/fast/forms/required-attribute-002-expected.txt b/LayoutTests/fast/forms/required-attribute-002-expected.txt
index ac5c0ff..c25561d 100644
--- a/LayoutTests/fast/forms/required-attribute-002-expected.txt
+++ b/LayoutTests/fast/forms/required-attribute-002-expected.txt
@@ -1,4 +1,19 @@
-There are two form control elements below, both optional. They're set as required via required DOM attribute.
+There are three form control elements below, all optional. They're set as required via required DOM attribute.
-
-SUCCESS
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Before set:
+PASS requiredFor("input") is false
+PASS requiredFor("textarea") is false
+PASS requiredFor("select") is false
+
+After set:
+PASS requiredFor("input") is true
+PASS requiredFor("textarea") is true
+PASS requiredFor("select") is true
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/required-attribute-002.html b/LayoutTests/fast/forms/required-attribute-002.html
index aa85e89..928e33f 100644
--- a/LayoutTests/fast/forms/required-attribute-002.html
+++ b/LayoutTests/fast/forms/required-attribute-002.html
@@ -1,32 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>required attribute JS set</title>
-<script language="JavaScript" type="text/javascript">
- function log(message) {
- document.getElementById("console").innerHTML += "<li>"+message+"</li>";
- }
-
- function test() {
- if (window.layoutTestController)
- layoutTestController.dumpAsText();
-
- v = document.getElementsByName("victim");
-
- if (v[0].required == false && v[1].required == false) {
- v[0].required = true;
- v[1].required = true;
- log ((v[0].required && v[1].required) ? "SUCCESS" : "FAILURE");
- }
- else
- log("FAILURE");
- }
-</script>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
</head>
-<body onload="test()">
-<p>There are two form control elements below, both optional. They're set as required via required DOM attribute.</p>
-<input name="victim" />
-<textarea name="victim"></textarea>
-<hr>
-<ol id="console"></ol>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<input id="input" name="victim" />
+<textarea id="textarea" name="victim"></textarea>
+<select id="select" name="victim">
+ <option value="" selected />
+ <option value="X">X</option>
+</select>
+<script language="JavaScript" type="text/javascript">
+ function requiredFor(id) {
+ return document.getElementById(id).required;
+ }
+
+ description("There are three form control elements below, all optional. They're set as required via required DOM attribute.");
+
+ v = document.getElementsByName("victim");
+
+ debug("Before set:");
+ shouldBeFalse('requiredFor("input")');
+ shouldBeFalse('requiredFor("textarea")');
+ shouldBeFalse('requiredFor("select")');
+ debug("");
+
+ v[0].required = true;
+ v[1].required = true;
+ v[2].required = true;
+
+ debug("After set:");
+ shouldBeTrue('requiredFor("input")');
+ shouldBeTrue('requiredFor("textarea")');
+ shouldBeTrue('requiredFor("select")');
+ debug("");
+
+ var successfullyParsed = true;
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
</body>
</html>
diff --git a/LayoutTests/fast/forms/resources/select-live-pseudo-selectors.js b/LayoutTests/fast/forms/resources/select-live-pseudo-selectors.js
new file mode 100644
index 0000000..c22133c
--- /dev/null
+++ b/LayoutTests/fast/forms/resources/select-live-pseudo-selectors.js
@@ -0,0 +1,183 @@
+description("This test performs a check that :valid/:invalid CSS psudo selectors are lively applied.");
+
+// Setup for static elements.
+var form = document.createElement('form');
+document.body.appendChild(form);
+var nonForm = document.createElement('div');
+document.body.appendChild(nonForm);
+
+function makeInvalid() {
+ var select = document.createElement('select');
+ select.name = 'foo';
+ select.required = true;
+ select.value = '';
+ form.appendChild(select);
+ return select;
+}
+
+function appendOption(value, select) {
+ var option = document.createElement('option');
+ option.value = value;
+ option.innerText = value;
+ select.add(option);
+ return option;
+}
+
+function insertOptionBefore(value, select, before) {
+ var option = document.createElement('option');
+ option.value = value;
+ option.innerText = value;
+ select.add(option, before);
+ return option;
+}
+
+function removeOption(option, select) {
+ select.remove(option);
+ return option;
+}
+
+function backgroundOf(el) {
+ return document.defaultView.getComputedStyle(el, null).getPropertyValue('background-color');
+}
+
+var elBackground = 'backgroundOf(el)';
+var invalidColor = 'rgb(255, 0, 0)';
+var normalColor = 'rgb(255, 255, 255)';
+var disabledColor = 'rgb(0, 0, 0)';
+var readOnlyColor = 'rgb(0, 255, 0)'
+var validColor = 'rgb(0, 0, 255)';
+
+// --------------------------------
+// willValidate change
+// --------------------------------
+var el = makeInvalid();
+var o1 = appendOption('', el);
+var o2 = appendOption('X', el);
+o1.selected = true;
+// Confirm this element is invalid.
+debug('Check the initial state:');
+shouldBe(elBackground, 'invalidColor');
+
+debug('Change name:');
+el.name = '';
+shouldBe(elBackground, 'invalidColor');
+el.name = 'bar';
+shouldBe(elBackground, 'invalidColor');
+
+debug('Change disabled:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = true;
+el.disabled = true;
+shouldBe(elBackground, 'disabledColor');
+el.disabled = false;
+shouldBe(elBackground, 'invalidColor');
+
+debug('Inside/outside of a form:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = true;
+nonForm.appendChild(el);
+shouldBe(elBackground, 'invalidColor');
+form.appendChild(el);
+shouldBe(elBackground, 'invalidColor');
+
+// --------------------------------
+// value change
+// --------------------------------
+debug('Change the value with a placeholder label option:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o2.selected = true;
+shouldBe(elBackground, 'validColor');
+o1.selected = true;
+shouldBe(elBackground, 'invalidColor');
+
+debug('Change the value without a placeholder label option:');
+el = makeInvalid();
+o1 = appendOption('X', el);
+o2 = appendOption('', el);
+o2.selected = true;
+shouldBe(elBackground, 'validColor');
+o1.selected = true;
+shouldBe(elBackground, 'validColor');
+
+debug('Insert/remove options:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = true;
+shouldBe(elBackground, 'invalidColor');
+o3 = insertOptionBefore('Y', el, el.firstChild);
+shouldBe(elBackground, 'validColor');
+removeOption(o3, el);
+shouldBe(elBackground, 'invalidColor');
+o3 = appendOption('Z', el);
+o3.selected = true;
+shouldBe(elBackground, 'validColor');
+el.length = 2;
+shouldBe(elBackground, 'invalidColor');
+
+debug('Set an attribute: multiple:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = true;
+shouldBe(elBackground, 'invalidColor');
+el.multiple = true;
+shouldBe(elBackground, 'validColor');
+el.removeAttribute('multiple');
+shouldBe(elBackground, 'invalidColor');
+
+debug('Set an attribute: size:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = true;
+shouldBe(elBackground, 'invalidColor');
+el.size = 2;
+shouldBe(elBackground, 'validColor');
+el.removeAttribute('size');
+shouldBe(elBackground, 'invalidColor');
+
+debug('SelectAll:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+el.multiple = true;
+o1.selected = false;
+o2.selected = false;
+shouldBe(elBackground, 'invalidColor');
+el.focus();
+document.execCommand("SelectAll");
+shouldBe(elBackground, 'validColor');
+el.multiple = false;
+o1.selected = false;
+o2.selected = true;
+
+debug('Reset:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o2.selected = true;
+shouldBe(elBackground, 'validColor');
+form.reset();
+shouldBe(elBackground, 'invalidColor');
+
+// --------------------------------
+// Constraints change
+// --------------------------------
+debug('Change required:');
+el = makeInvalid();
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = true;
+el.required = false;
+shouldBe(elBackground, 'validColor');
+el.required = true;
+shouldBe(elBackground, 'invalidColor');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/forms/script-tests/validationMessage.js b/LayoutTests/fast/forms/script-tests/validationMessage.js
index d6826de..5c56542 100644
--- a/LayoutTests/fast/forms/script-tests/validationMessage.js
+++ b/LayoutTests/fast/forms/script-tests/validationMessage.js
@@ -24,6 +24,13 @@
form.appendChild(requiredTextArea);
shouldBe("requiredTextArea.validationMessage", "'value missing'");
+// A required select with an empty value
+var requiredSelect = document.createElement("select");
+requiredSelect.name = "requiredSelect";
+requiredSelect.required = true;
+form.appendChild(requiredSelect);
+shouldBe("requiredSelect.validationMessage", "'value missing'");
+
// A type=email input for the "type mismatch" flag
var emailInput = document.createElement("input");
emailInput.name = "emailInput";
diff --git a/LayoutTests/fast/forms/select-live-pseudo-selectors-expected.txt b/LayoutTests/fast/forms/select-live-pseudo-selectors-expected.txt
new file mode 100644
index 0000000..4d7cb73
--- /dev/null
+++ b/LayoutTests/fast/forms/select-live-pseudo-selectors-expected.txt
@@ -0,0 +1,50 @@
+This test performs a check that :valid/:invalid CSS psudo selectors are lively applied.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Check the initial state:
+PASS backgroundOf(el) is invalidColor
+Change name:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is invalidColor
+Change disabled:
+PASS backgroundOf(el) is disabledColor
+PASS backgroundOf(el) is invalidColor
+Inside/outside of a form:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is invalidColor
+Change the value with a placeholder label option:
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+Change the value without a placeholder label option:
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is validColor
+Insert/remove options:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+Set an attribute: multiple:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+Set an attribute: size:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+SelectAll:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is validColor
+Reset:
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+Change required:
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
diff --git a/LayoutTests/fast/forms/select-live-pseudo-selectors.html b/LayoutTests/fast/forms/select-live-pseudo-selectors.html
new file mode 100644
index 0000000..02e9f876
--- /dev/null
+++ b/LayoutTests/fast/forms/select-live-pseudo-selectors.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<link rel="stylesheet" href="resources/live-pseudo-selectors.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/select-live-pseudo-selectors.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/validationMessage-expected.txt b/LayoutTests/fast/forms/validationMessage-expected.txt
index 0e12d8a..e91961d 100644
--- a/LayoutTests/fast/forms/validationMessage-expected.txt
+++ b/LayoutTests/fast/forms/validationMessage-expected.txt
@@ -6,6 +6,7 @@
PASS patternInput.validationMessage is 'pattern mismatch'
PASS requiredInput.validationMessage is 'value missing'
PASS requiredTextArea.validationMessage is 'value missing'
+PASS requiredSelect.validationMessage is 'value missing'
PASS emailInput.validationMessage is 'type mismatch'
PASS but.validationMessage is ''
PASS anoninput.validationMessage is ''
diff --git a/LayoutTests/platform/mac/fast/objc/dom-html-select-live-pseudo-selectors-expected.txt b/LayoutTests/platform/mac/fast/objc/dom-html-select-live-pseudo-selectors-expected.txt
new file mode 100644
index 0000000..fa89fa5
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/objc/dom-html-select-live-pseudo-selectors-expected.txt
@@ -0,0 +1,15 @@
+This test performs a check that :valid/:invalid CSS psudo selectors are lively applied by HTMLSelectElement::setSelectedIndexByUser.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Change the value of a menulist select by setSelectedIndexByUser:
+PASS backgroundOf(el) is validColor
+PASS backgroundOf(el) is invalidColor
+Change the value of a listbox select by setSelectedIndexByUser:
+PASS backgroundOf(el) is invalidColor
+PASS backgroundOf(el) is validColor
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html b/LayoutTests/platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html
new file mode 100644
index 0000000..e194166
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title></title>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<link rel="stylesheet" href="../../../../fast/forms/resources/live-pseudo-selectors.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+description("This test performs a check that :valid/:invalid CSS psudo selectors are lively applied by HTMLSelectElement::setSelectedIndexByUser.");
+
+// Setup for static elements.
+var form = document.createElement('form');
+document.body.appendChild(form);
+
+function makeInvalid(id) {
+ var select = document.createElement('select');
+ select.name = 'foo';
+ select.required = true;
+ if (id != undefined)
+ select.id = id;
+ select.value = '';
+ form.appendChild(select);
+ return select;
+}
+
+function appendOption(value, select) {
+ var option = document.createElement('option');
+ option.value = value;
+ option.innerText = value;
+ select.add(option);
+ return option;
+}
+
+function backgroundOf(el) {
+ return document.defaultView.getComputedStyle(el, null).getPropertyValue('background-color');
+}
+
+var elBackground = 'backgroundOf(el)';
+var invalidColor = 'rgb(255, 0, 0)';
+var normalColor = 'rgb(255, 255, 255)';
+var disabledColor = 'rgb(0, 0, 0)';
+var readOnlyColor = 'rgb(0, 255, 0)'
+var validColor = 'rgb(0, 0, 255)';
+
+debug('Change the value of a menulist select by setSelectedIndexByUser:');
+el = makeInvalid('menulist');
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+objCController.setSelectElementSelectedIndexAllowingMultiple(el, 1, false);
+shouldBe(elBackground, 'validColor');
+objCController.setSelectElementSelectedIndexAllowingMultiple(el, 0, false);
+shouldBe(elBackground, 'invalidColor');
+
+debug('Change the value of a listbox select by setSelectedIndexByUser:');
+el = makeInvalid('listbox');
+el.multiple = true;
+o1 = appendOption('', el);
+o2 = appendOption('X', el);
+o1.selected = false;
+o2.selected = false;
+shouldBe(elBackground, 'invalidColor');
+objCController.setSelectElementSelectedIndexAllowingMultiple(el, 0, false);
+shouldBe(elBackground, 'validColor');
+
+var successfullyParsed = true;
+</script>
+<script src="../../../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 43e5bbc..6ded679 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,41 @@
+2010-12-09 Dai Mikurube <dmikurube@google.com>
+
+ Reviewed by Kent Tamura.
+
+ Implement "required" attribute for select tags
+ https://bugs.webkit.org/show_bug.cgi?id=50380
+
+ Test: fast/forms/select-live-pseudo-selectors.html
+ platform/mac/fast/objc/dom-html-select-live-pseudo-selectors.html
+
+ * dom/SelectElement.cpp:
+ (WebCore::SelectElement::updateValidity): Added. It's a pure virtual function which is prepared so that HTMLSelectElement::updateValidity() calls HTMLSelectElement::setNeedsValidityCheck().
+ (WebCore::SelectElement::parseMultipleAttribute): Added calling updateValidity().
+ * html/HTMLSelectElement.cpp:
+ (WebCore::HTMLSelectElement::deselectItems): Added calling setNeedsValidityCheck() to enable validity check after changing. No tests for this change since this function is not exposed to JavaScript or any web interface.
+ (WebCore::HTMLSelectElement::setSelectedIndex): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::setSelectedIndexByUser): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::valueMissing): Added valueMissing() to check if selecting an invalid or placeholder label option when a valid required attribute is specified.
+ (WebCore::HTMLSelectElement::listBoxSelectItem): Added calling setNeedsValidityCheck(). No tests for this change since it is not called yet. Look at the bug 36177 and the changeset 56180.
+ (WebCore::HTMLSelectElement::add): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::remove): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::restoreFormControlState): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::parseMappedAttribute): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::selectAll): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::reset): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::updateListBoxSelection): Added calling setNeedsValidityCheck(). Skipped adding tests for this change as too complicated..
+ (WebCore::HTMLSelectElement::setLength): Added calling setNeedsValidityCheck().
+ (WebCore::HTMLSelectElement::isRequiredFormControl): Check if required or not.
+ (WebCore::HTMLSelectElement::hasPlaceholderLabelOption): Added.
+ (WebCore::HTMLSelectElement::updateValidity): Added. It calls setNeedsValidityCheck().
+ * html/HTMLSelectElement.h:
+ (WebCore::HTMLSelectElement::isOptionalFormControl): Check if not required.
+ * html/HTMLSelectElement.idl: Added a required attribute to select elements..
+ * html/ValidityState.cpp:
+ (WebCore::ValidityState::valueMissing): Added valueMissing check for select elements into the global checker, ValidityState::valueMissing().
+ * wml/WMLSelectElement.h:
+ (WebCore::WMLSelectElement::updateValidity): Added. It does nothing.
+
2010-12-07 Jeremy Orlow <jorlow@chromium.org>
Reviewed by Steve Block.
diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp
index 99e0c29..bfa1b93 100644
--- a/WebCore/dom/SelectElement.cpp
+++ b/WebCore/dom/SelectElement.cpp
@@ -453,6 +453,7 @@
{
bool oldUsesMenuList = data.usesMenuList();
data.setMultiple(!attribute->isNull());
+ toSelectElement(element)->updateValidity();
if (oldUsesMenuList != data.usesMenuList() && element->attached()) {
element->detach();
element->attach();
diff --git a/WebCore/dom/SelectElement.h b/WebCore/dom/SelectElement.h
index 53815f2..222a1bb 100644
--- a/WebCore/dom/SelectElement.h
+++ b/WebCore/dom/SelectElement.h
@@ -63,6 +63,8 @@
virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) = 0;
+ virtual void updateValidity() = 0;
+
protected:
virtual ~SelectElement() { }
diff --git a/WebCore/html/HTMLSelectElement.cpp b/WebCore/html/HTMLSelectElement.cpp
index c680e92..968f629 100644
--- a/WebCore/html/HTMLSelectElement.cpp
+++ b/WebCore/html/HTMLSelectElement.cpp
@@ -78,11 +78,13 @@
void HTMLSelectElement::deselectItems(HTMLOptionElement* excludeElement)
{
SelectElement::deselectItems(m_data, this, excludeElement);
+ setNeedsValidityCheck();
}
void HTMLSelectElement::setSelectedIndex(int optionIndex, bool deselect)
{
SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, false, false);
+ setNeedsValidityCheck();
}
void HTMLSelectElement::setSelectedIndexByUser(int optionIndex, bool deselect, bool fireOnChangeNow, bool allowMultipleSelection)
@@ -91,6 +93,7 @@
// mousedown events. This allows that same behavior programmatically.
if (!m_data.usesMenuList()) {
updateSelectedState(m_data, this, optionIndex, allowMultipleSelection, false);
+ setNeedsValidityCheck();
if (fireOnChangeNow)
listBoxOnChange();
return;
@@ -104,6 +107,42 @@
return;
SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, fireOnChangeNow, true);
+ setNeedsValidityCheck();
+}
+
+bool HTMLSelectElement::hasPlaceholderLabelOption() const
+{
+ // The select element has no placeholder label option if it has an attribute "multiple" specified or a display size of non-1.
+ //
+ // The condition "size() > 1" is actually not compliant with the HTML5 spec as of Dec 3, 2010. "size() != 1" is correct.
+ // Using "size() > 1" here because size() may be 0 in WebKit.
+ // See the discussion at https://bugs.webkit.org/show_bug.cgi?id=43887
+ //
+ // "0 size()" happens when an attribute "size" is absent or an invalid size attribute is specified.
+ // In this case, the display size should be assumed as the default.
+ // The default display size is 1 for non-multiple select elements, and 4 for multiple select elements.
+ //
+ // Finally, if size() == 0 and non-multiple, the display size can be assumed as 1.
+ if (multiple() || size() > 1)
+ return false;
+
+ int listIndex = optionToListIndex(0);
+ ASSERT(listIndex >= 0);
+ if (listIndex < 0)
+ return false;
+ HTMLOptionElement* option = static_cast<HTMLOptionElement*>(listItems()[listIndex]);
+ return !option->disabled() && !listIndex && option->value().isEmpty();
+}
+
+bool HTMLSelectElement::valueMissing() const
+{
+ if (!isRequiredFormControl())
+ return false;
+
+ int firstSelectionIndex = selectedIndex();
+
+ // If a non-placeholer label option is selected (firstSelectionIndex > 0), it's not value-missing.
+ return firstSelectionIndex < 0 || (!firstSelectionIndex && hasPlaceholderLabelOption());
}
void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow)
@@ -112,6 +151,7 @@
setSelectedIndexByUser(listToOptionIndex(listIndex), true, fireOnChangeNow);
else {
updateSelectedState(m_data, this, listIndex, allowMultiplySelections, shift);
+ setNeedsValidityCheck();
if (fireOnChangeNow)
listBoxOnChange();
}
@@ -144,6 +184,7 @@
return;
insertBefore(element, before, ec);
+ setNeedsValidityCheck();
}
void HTMLSelectElement::remove(int index)
@@ -156,6 +197,7 @@
ASSERT(item->parentNode());
ExceptionCode ec;
item->parentNode()->removeChild(item, ec);
+ setNeedsValidityCheck();
}
String HTMLSelectElement::value()
@@ -195,6 +237,7 @@
void HTMLSelectElement::restoreFormControlState(const String& state)
{
SelectElement::restoreFormControlState(m_data, this, state);
+ setNeedsValidityCheck();
}
void HTMLSelectElement::parseMappedAttribute(Attribute* attr)
@@ -215,6 +258,7 @@
recalcListItemsIfNeeded();
m_data.setSize(size);
+ setNeedsValidityCheck();
if ((oldUsesMenuList != m_data.usesMenuList() || (!oldUsesMenuList && m_data.size() != oldSize)) && attached()) {
detach();
attach();
@@ -255,6 +299,7 @@
void HTMLSelectElement::selectAll()
{
SelectElement::selectAll(m_data, this);
+ setNeedsValidityCheck();
}
RenderObject* HTMLSelectElement::createRenderer(RenderArena* arena, RenderStyle*)
@@ -315,6 +360,7 @@
void HTMLSelectElement::reset()
{
SelectElement::reset(m_data, this);
+ setNeedsValidityCheck();
}
void HTMLSelectElement::dispatchFocusEvent()
@@ -350,6 +396,7 @@
void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions)
{
SelectElement::updateListBoxSelection(m_data, this, deselectOtherOptions);
+ setNeedsValidityCheck();
}
void HTMLSelectElement::menuListOnChange()
@@ -458,6 +505,7 @@
}
}
}
+ setNeedsValidityCheck();
}
void HTMLSelectElement::scrollToSelection()
@@ -471,4 +519,9 @@
HTMLFormControlElementWithState::insertedIntoTree(deep);
}
+bool HTMLSelectElement::isRequiredFormControl() const
+{
+ return required();
+}
+
} // namespace
diff --git a/WebCore/html/HTMLSelectElement.h b/WebCore/html/HTMLSelectElement.h
index a3b4460..0bfb6a0 100644
--- a/WebCore/html/HTMLSelectElement.h
+++ b/WebCore/html/HTMLSelectElement.h
@@ -43,6 +43,9 @@
virtual void setSelectedIndex(int index, bool deselect = true);
virtual void setSelectedIndexByUser(int index, bool deselect = true, bool fireOnChangeNow = false, bool allowMultipleSelection = false);
+ // For ValidityState
+ bool valueMissing() const;
+
unsigned length() const;
virtual int size() const { return m_data.size(); }
@@ -82,6 +85,8 @@
void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
+ virtual void updateValidity() { setNeedsValidityCheck(); }
+
protected:
HTMLSelectElement(const QualifiedName&, Document*, HTMLFormElement*);
@@ -134,7 +139,10 @@
virtual void insertedIntoTree(bool);
- virtual bool isOptionalFormControl() const { return true; }
+ virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
+ virtual bool isRequiredFormControl() const;
+
+ bool hasPlaceholderLabelOption() const;
SelectElementData m_data;
CollectionCache m_collectionInfo;
diff --git a/WebCore/html/HTMLSelectElement.idl b/WebCore/html/HTMLSelectElement.idl
index 2e53bca..f5ac69b 100644
--- a/WebCore/html/HTMLSelectElement.idl
+++ b/WebCore/html/HTMLSelectElement.idl
@@ -49,6 +49,7 @@
attribute [Reflect] boolean autofocus;
attribute boolean multiple;
attribute [ConvertNullToNullString] DOMString name;
+ attribute [Reflect] boolean required;
attribute long size;
[OldStyleObjC] void add(in HTMLElement element, in HTMLElement before) raises(DOMException);
diff --git a/WebCore/html/ValidityState.cpp b/WebCore/html/ValidityState.cpp
index 2fb1e2c..0565035 100644
--- a/WebCore/html/ValidityState.cpp
+++ b/WebCore/html/ValidityState.cpp
@@ -26,6 +26,7 @@
#include "HTMLInputElement.h"
#include "HTMLNames.h"
+#include "HTMLSelectElement.h"
#include "HTMLTextAreaElement.h"
#include "HTMLTreeBuilder.h"
#include "LocalizedStrings.h"
@@ -105,6 +106,9 @@
bool ValidityState::valueMissing() const
{
HTMLElement* element = toHTMLElement(m_control);
+ if (!element->willValidate())
+ return false;
+
if (element->hasTagName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
return input->valueMissing(input->value());
@@ -113,6 +117,10 @@
HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(element);
return textArea->valueMissing(textArea->value());
}
+ if (element->hasTagName(selectTag)) {
+ HTMLSelectElement* select = static_cast<HTMLSelectElement*>(element);
+ return select->valueMissing();
+ }
return false;
}
diff --git a/WebCore/wml/WMLSelectElement.h b/WebCore/wml/WMLSelectElement.h
index 16bb382..3d8c726 100644
--- a/WebCore/wml/WMLSelectElement.h
+++ b/WebCore/wml/WMLSelectElement.h
@@ -103,6 +103,8 @@
String optionIndicesToValueString() const;
String optionIndicesToString() const;
+ virtual void updateValidity() {}
+
String name() const;
String value() const;
String iname() const;