mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Implement the form owner concept
This commit is contained in:
parent
f90e19f705
commit
38a61712e4
25 changed files with 1004 additions and 165 deletions
|
@ -0,0 +1,233 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<form id="f1"></form>
|
||||
<form id="f2">
|
||||
<input id="i1" />
|
||||
<input id="i2" form="f1" />
|
||||
<input id="i3" />
|
||||
</form>
|
||||
<script>
|
||||
test(function() {
|
||||
var i1 = document.getElementById("i1");
|
||||
var i2 = document.getElementById("i2");
|
||||
var i3 = document.getElementById("i3");
|
||||
var f1 = document.getElementById("f1");
|
||||
var f2 = document.getElementById("f2");
|
||||
|
||||
assert_equals(i1.form, f2,
|
||||
"i1 must be associated with f2 by the parser");
|
||||
assert_equals(i2.form, f1,
|
||||
"i2 is not associated with f2 by the parser " +
|
||||
"since it has the form attribute set to f1");
|
||||
|
||||
f1.appendChild(i1);
|
||||
i3.setAttribute("form", "f1");
|
||||
|
||||
assert_equals(i1.form, f1,
|
||||
"i1's form owner must be reset when parent changes");
|
||||
assert_equals(i3.form, f1,
|
||||
"i3's form owner must be reset when the form" +
|
||||
"attribute is set");
|
||||
|
||||
assert_equals(i2.form, f1);
|
||||
}, "Tests for parser inserted controls");
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div id="placeholder">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var reassociateableElements = [
|
||||
"button",
|
||||
"fieldset",
|
||||
"input",
|
||||
"object",
|
||||
"output",
|
||||
"select",
|
||||
"textarea",
|
||||
];
|
||||
|
||||
var form1 = null;
|
||||
var form2 = null;
|
||||
var placeholder = document.getElementById("placeholder");
|
||||
|
||||
reassociateableElements.forEach(function(localName) {
|
||||
function testControl(test_, desc) {
|
||||
test(function() {
|
||||
var control = document.createElement(localName);
|
||||
|
||||
while(placeholder.firstChild)
|
||||
placeholder.removeChild(placeholder.firstChild);
|
||||
|
||||
form1 = document.createElement("form");
|
||||
form2 = document.createElement("form");
|
||||
form1.id = "form1";
|
||||
form2.id = "form2";
|
||||
placeholder.appendChild(form1);
|
||||
placeholder.appendChild(form2);
|
||||
|
||||
test_.call(control);
|
||||
}, "[" + localName.toUpperCase() + "] " + desc);
|
||||
}
|
||||
|
||||
testControl(function() {
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
}, "Basic form association - control with no form attribute is associated with ancestor");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
form1.id = "form-one";
|
||||
assert_equals(this.form, null);
|
||||
}, "Form owner is reset to null when control's form attribute is set to an ID " +
|
||||
"that does not exist in the document");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "");
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, null);
|
||||
}, "Control whose form attribute is an empty string has no form owner");
|
||||
|
||||
testControl(function() {
|
||||
form1.id = "";
|
||||
this.setAttribute("form", "");
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, null);
|
||||
}, "Control whose form attribute is an empty string has no form owner " +
|
||||
"even when form with empty attribute is present");
|
||||
|
||||
testControl(function() {
|
||||
form1.id = "FORM1";
|
||||
this.setAttribute("form", "form1");
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, null);
|
||||
}, "Control's form attribute must be a case sensitive match for the form's id");
|
||||
|
||||
testControl(function() {
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
this.setAttribute("form", "form2");
|
||||
assert_equals(this.form, form2);
|
||||
}, "Setting the form attribute of a control to the id of a non-ancestor form works");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
|
||||
form2.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
this.removeAttribute("form");
|
||||
assert_equals(this.form, form2);
|
||||
}, "Removing form id from a control resets the form owner to ancestor");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
|
||||
form2.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
placeholder.removeChild(form1);
|
||||
|
||||
assert_equals(this.form, null);
|
||||
}, "Removing the form owner of a control with form attribute resets " +
|
||||
"the form owner to null");
|
||||
|
||||
testControl(function() {
|
||||
var form3 = document.createElement("form");
|
||||
form3.id = "form3";
|
||||
placeholder.appendChild(form3);
|
||||
form3.appendChild(this);
|
||||
assert_equals(this.form, form3);
|
||||
|
||||
this.setAttribute("form", "form2");
|
||||
assert_equals(this.form, form2);
|
||||
|
||||
this.setAttribute("form", "form1");
|
||||
assert_equals(this.form, form1);
|
||||
}, "Changing form attibute of control resets form owner to correct form");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
var form3 = document.createElement("form");
|
||||
form3.id = "form3";
|
||||
|
||||
placeholder.appendChild(form3);
|
||||
placeholder.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
form2.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
}, "Moving a control with form attribute within the document " +
|
||||
"does not change the form owner");
|
||||
|
||||
testControl(function() {
|
||||
form1.id = "form-one";
|
||||
this.setAttribute("form", "form1");
|
||||
form2.appendChild(this);
|
||||
assert_equals(this.form, null);
|
||||
|
||||
form1.id = "form1";
|
||||
assert_equals(this.form, form1);
|
||||
}, "When the id of a non-ancestor form changes from not being a match for the " +
|
||||
"form attribute to being a match, the control's form owner is reset");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
form2.id = "form1";
|
||||
form1.parentNode.insertBefore(form2, form1);
|
||||
assert_equals(this.form, form2);
|
||||
|
||||
form2.parentNode.removeChild(form2);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
form1.parentNode.appendChild(form2);
|
||||
assert_equals(this.form, form1);
|
||||
}, "When form element with same ID as the control's form attribute is inserted " +
|
||||
"earlier in tree order, the form owner is changed to the inserted form");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
form2.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
var span = document.createElement("span");
|
||||
span.id = "form1";
|
||||
form1.parentNode.insertBefore(span, form1);
|
||||
assert_equals(this.form, null);
|
||||
|
||||
form1.parentNode.appendChild(span);
|
||||
assert_equals(this.form, form1);
|
||||
}, "When non-form element with same ID as the control's form attribute is " +
|
||||
"inserted earlier in tree order, the control does not have a form owner");
|
||||
|
||||
testControl(function() {
|
||||
this.setAttribute("form", "form1");
|
||||
form1.appendChild(this);
|
||||
assert_equals(this.form, form1);
|
||||
|
||||
form1.parentNode.removeChild(form1);
|
||||
assert_equals(this.form, form1);
|
||||
}, "A control that is not in the document but has the form attribute set " +
|
||||
"is associated with the nearest ancestor form if one exists");
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">
|
||||
<form id='form1'></form>
|
||||
<table id='table1'>
|
||||
<form id='form2'>
|
||||
<tr><td><input id='input1'></td></tr>
|
||||
<tr><td><input id='input2' form='form1'></td></tr>
|
||||
</table>
|
||||
<form id="form3">
|
||||
<input id="input3" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
var input1 = document.getElementById('input1');
|
||||
var input2 = document.getElementById('input2');
|
||||
var input3 = document.getElementById('input3');
|
||||
var form1 = document.getElementById('form1');
|
||||
var form2 = document.getElementById('form2');
|
||||
var form3 = document.getElementById('form3');
|
||||
|
||||
var root = document.getElementById('root');
|
||||
|
||||
assert_equals(input1.form, form2,
|
||||
"input1's form owner must be form2 as per the parsing rules");
|
||||
assert_equals(input2.form, form1,
|
||||
"input2's form owner must be the form with id 'form1'");
|
||||
assert_equals(input3.form, form2,
|
||||
"input3's form owner must be form2 as per the parsing rules");
|
||||
|
||||
root.parentNode.removeChild(root);
|
||||
|
||||
assert_equals(input1.form, form2,
|
||||
"input1's form owner must not have changed since they are both in the same subtree");
|
||||
assert_equals(input2.form, null,
|
||||
"input2 must not have a form owner since it has the form attribute set");
|
||||
assert_equals(input3.form, form2,
|
||||
"input3's form owner must not have changed since they are both in the same subtree");
|
||||
|
||||
}, "Form element and form controls nested inside a table are correctly handled");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<form id='form1'></form>
|
||||
<table id='table1'>
|
||||
<form id='form2'>
|
||||
<script>
|
||||
var t = document.getElementById('table1');
|
||||
var f = document.getElementById('form2');
|
||||
t.removeChild(f);
|
||||
</script>
|
||||
<tr><td><input id='input1'></td></tr>
|
||||
<tr><td><input id='input2' form='form1'></td></tr>
|
||||
</table>
|
||||
<form id="form3">
|
||||
<input id="input3" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
var form1 = document.getElementById('form1');
|
||||
|
||||
assert_equals(document.getElementById('input1').form, null,
|
||||
"input1's form owner must be null since form2 is not in the" +
|
||||
"same home subtree");
|
||||
|
||||
assert_equals(document.getElementById('input2').form, form1,
|
||||
"input2's form owner must be the form with id 'form1'");
|
||||
|
||||
assert_equals(document.getElementById('input3').form, null,
|
||||
"input3's form owner must be null instead of form2 (as per parsing rules)" +
|
||||
"since form2 is not in the same home subtree");
|
||||
|
||||
}, "Controls nested in tables are not associated with form element inside the " +
|
||||
"table if the form had been removed by script before the controls were " +
|
||||
"inserted by the parser");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue