Bug 589696 - Implement formnovalidate attribute for submit controls. r=smaug a2.0=blocking

This commit is contained in:
Mounir Lamouri 2010-09-15 01:38:07 +02:00
parent 5dd54baa6b
commit 028a464466
7 changed files with 177 additions and 2 deletions

View File

@ -393,6 +393,7 @@ GK_ATOM(format, "format")
GK_ATOM(formatNumber, "format-number")
GK_ATOM(formenctype, "formenctype")
GK_ATOM(formmethod, "formmethod")
GK_ATOM(formnovalidate, "formnovalidate")
GK_ATOM(formtarget, "formtarget")
GK_ATOM(frame, "frame")
GK_ATOM(frameborder, "frameborder")

View File

@ -218,6 +218,7 @@ NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormEnctype, formenctype,
kFormDefaultEnctype->tag)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, FormMethod, formmethod,
kFormDefaultMethod->tag)
NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, FormNoValidate, formnovalidate)
NS_IMPL_STRING_ATTR(nsHTMLButtonElement, FormTarget, formtarget)
NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Name, name)
NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLButtonElement, TabIndex, tabindex, 0)
@ -508,6 +509,9 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
// event is not handled if the window is being destroyed.
if (presShell && (event.message != NS_FORM_SUBMIT ||
mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
// We know the element is a submit control, if this check is moved,
// make sure formnovalidate is used only if it's a submit control.
HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
mForm->CheckValidFormSubmission())) {
// TODO: removing this code and have the submit event sent by the form
// see bug 592124.

View File

@ -973,6 +973,7 @@ NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype,
kFormDefaultEnctype->tag)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod,
kFormDefaultMethod->tag)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, FormNoValidate, formnovalidate)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormTarget, formtarget)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Multiple, multiple)
NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLInputElement, MaxLength, maxlength)
@ -2442,6 +2443,9 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
// form, see bug 592124.
if (presShell && (event.message != NS_FORM_SUBMIT ||
mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
// We know the element is a submit control, if this check is moved,
// make sure formnovalidate is used only if it's a submit control.
HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
mForm->CheckValidFormSubmission())) {
// Hold a strong ref while dispatching
nsRefPtr<nsHTMLFormElement> form(mForm);

View File

@ -224,6 +224,7 @@ _TEST_FILES = \
test_bug557628-1.html \
test_bug557628-2.html \
test_bug592802.html \
test_bug589696.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,163 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=589696
-->
<head>
<title>Test for Bug 589696</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=589696">Mozilla Bug 589696</a>
<p id="display"></p>
<iframe style='width:50px; height: 50px;' name='t'></iframe>
<div id="content">
<!-- Next forms should not submit because formnovalidate isn't set on the
element used for the submission. -->
<form target='t' action='data:text/html,'>
<input id='av' required>
<input type='submit' formnovalidate>
<input id='a' type='submit'>
</form>
<form target='t' action='data:text/html,'>
<input id='bv' type='checkbox' required>
<button type='submit' formnovalidate></button>
<button id='b' type='submit'></button>
</form>
<!-- Next form should not submit because formnovalidate only applies for
submit controls. -->
<form target='t' action='data:text/html,'>
<input id='c' required formnovalidate>
</form>
<!--- Next forms should submit without any validation check. -->
<form target='t' action='data:text/html,'>
<input id='dv' required>
<input id='d' type='submit' formnovalidate>
</form>
<form target='t' action='data:text/html,'>
<input id='ev' type='checkbox' required>
<button id='e' type='submit' formnovalidate></button>
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 589696 **/
function checkFormNoValidateAttribute(aElementName)
{
var element = document.createElement(aElementName);
ok("formNoValidate" in element, "formNoValidate should be a " + aElementName +
" element IDL attribute");
ok(!element.formNoValidate, "formnovalidate attribute should be disabled");
is(element.getAttribute('formnovalidate'), null,
"formnovalidate attribute should be disabled");
element.formNoValidate = true;
ok(element.formNoValidate, "formnovalidate attribute should be enabled");
isnot(element.getAttribute('formnovalidate'), null,
"formnovalidate attribute should be enabled");
element.removeAttribute('formnovalidate');
element.setAttribute('formnovalidate', '');
ok(element.formNoValidate, "formnovalidate attribute should be enabled");
isnot(element.getAttribute('formnovalidate'), null,
"formnovalidate attribute should be enabled");
element.removeAttribute('formnovalidate');
ok(!element.formNoValidate, "formnovalidate attribute should be disabled");
is(element.getAttribute('formnovalidate'), null,
"formnovalidate attribute should be disabled");
}
checkFormNoValidateAttribute('input');
checkFormNoValidateAttribute('button');
/**
* formnovalidate should prevent form validation if set on the submit control
* used to submit the form.
*
* NOTE: if there is no invalidformsubmit observer, the form submission will
* never be blocked and this test might be a false-positive but that should not
* be a problem.
*/
document.getElementById('av').addEventListener("invalid", function(aEvent) {
aEvent.target.removeAttribute("invalid", arguments.callee, false);
ok(true, "formnovalidate should not apply on if not set on the submit " +
"control used for the submission");
document.getElementById('b').click();
}, false);
document.getElementById('bv').addEventListener("invalid", function(aEvent) {
aEvent.target.removeAttribute("invalid", arguments.callee, false);
ok(true, "formnovalidate should not apply on if not set on the submit " +
"control used for the submission");
var c = document.getElementById('c');
c.focus(); synthesizeKey("VK_RETURN", {type: "keypress"});
}, false);
document.getElementById('c').addEventListener("invalid", function(aEvent) {
aEvent.target.removeAttribute("invalid", arguments.callee, false);
ok(true, "formnovalidate should only apply on submit controls");
document.getElementById('d').click();
}, false);
document.forms[3].addEventListener("submit", function(aEvent) {
aEvent.target.removeAttribute("submit", arguments.callee, false);
ok(true, "formnovalidate applies if set on the submit control used for the submission");
document.getElementById('e').click();
}, false);
document.forms[4].addEventListener("submit", function(aEvent) {
aEvent.target.removeAttribute("submit", arguments.callee, false);
ok(true, "formnovalidate applies if set on the submit control used for the submission");
SimpleTest.executeSoon(SimpleTest.finish);
}, false);
/**
* We have to be sure invalid events behave as expected.
* They should be sent before the submit event so we can just create a test
* failure if we got one when unexpected. All of them should be catched if sent.
* At worst, we got random green which isn't harmful.
* If expected, they will be part of the chain reaction.
*/
function unexpectedInvalid(aEvent)
{
aEvent.target.removeAttribute("invalid", unexpectedInvalid, false);
ok(false, "invalid event should not be sent");
}
document.getElementById('dv').addEventListener("invalid", unexpectedInvalid, false);
document.getElementById('ev').addEventListener("invalid", unexpectedInvalid, false);
/**
* Some submission have to be canceled. In that case, the submit events should
* not be sent.
* Same behavior as unexpected invalid events.
*/
function unexpectedSubmit(aEvent)
{
aEvent.target.removeAttribute("submit", unexpectedSubmit, false);
ok(false, "submit event should not be sent");
}
document.forms[0].addEventListener("submit", unexpectedSubmit, false);
document.forms[1].addEventListener("submit", unexpectedSubmit, false);
document.forms[2].addEventListener("submit", unexpectedSubmit, false);
SimpleTest.waitForExplicitFinish();
// This is going to call all the tests (with a chain reaction).
SimpleTest.waitForFocus(function() {
document.getElementById('a').click();
});
</script>
</pre>
</body>
</html>

View File

@ -49,7 +49,7 @@
interface nsIDOMValidityState;
[scriptable, uuid(d76a7412-f70b-43fe-becb-d30dac13cc7b)]
[scriptable, uuid(bcae78a1-9f9b-46bf-abb5-a3fe410d97ae)]
interface nsIDOMHTMLButtonElement : nsIDOMHTMLElement
{
attribute boolean autofocus;
@ -58,6 +58,7 @@ interface nsIDOMHTMLButtonElement : nsIDOMHTMLElement
attribute DOMString formAction;
attribute DOMString formEnctype;
attribute DOMString formMethod;
attribute boolean formNoValidate;
attribute DOMString formTarget;
attribute DOMString name;

View File

@ -51,7 +51,7 @@ interface nsIDOMValidityState;
* http://www.w3.org/TR/DOM-Level-2-HTML/
*/
[scriptable, uuid(2f79a4be-8143-45fc-ac42-67cd16b2322f)]
[scriptable, uuid(0805059d-f18f-4095-ae6b-0bf6df80b7b8)]
interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
{
attribute DOMString accept;
@ -66,6 +66,7 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
attribute DOMString formAction;
attribute DOMString formEnctype;
attribute DOMString formMethod;
attribute boolean formNoValidate;
attribute DOMString formTarget;
readonly attribute nsIDOMFileList files;