Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE HTML>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
</head>
<body>
<div>
<template shadowrootmode="open">
<!-- This button shouldn't link to the real form in fancy-form-1 as it's in a different tree scope -->
<button id="button-in-shadow" form="fancy-form-1"></button>
</template>
</div>
<button id="reset-button-1" type="reset" form="fancy-form-1"></button>
<fancy-form-1 id="fancy-form-1">
<template shadowrootmode="open" shadowrootreferencetarget="real-form">
<form id="real-form">
<input type="text" value="default value">
</form>
</template>
</fancy-form-1>
<button id="reset-button-2" type="reset" form="fancy-form-2"></button>
<fancy-form-2 id="fancy-form-2"></fancy-form-2>
<script>
const fancyForm2 = document.querySelector('fancy-form-2');
fancyForm2.attachShadow({ mode: 'open', referenceTarget: 'real-form' });
fancyForm2.shadowRoot.innerHTML = '<form id="real-form"><input type="text" value="default value"></form>';
</script>
<button id="reset-button-3" type="reset"></button>
<fancy-form-3 id="fancy-form-3">
<template shadowrootmode="open" shadowrootreferencetarget="real-form">
<form id="real-form">
<input type="text" value="default value">
</form>
</template>
</fancy-form-3>
<script>
function testFormWithReferenceTarget(formId, resetButtonId, name) {
test(function () {
const fancyForm = document.getElementById(formId);
const realForm = fancyForm.shadowRoot.getElementById("real-form");
const input = realForm.firstElementChild;
input.value = "new value";
const resetButton = document.getElementById(resetButtonId);
assert_equals(realForm.elements.length, 2, "The .elements property should have 2 elements.");
assert_equals(realForm.elements[0], resetButton, "The first element should be the referencing element.");
assert_equals(realForm.elements[1], input, "The 2nd element should be the input inside the real form.");
assert_equals(input.value, "new value", "The input value should be updated to the new value.");
resetButton.click();
assert_equals(input.value, "default value", "The input value should be reset to the default value.");
}, name);
}
testFormWithReferenceTarget('fancy-form-1', 'reset-button-1', "Reference target works with form attribute.");
testFormWithReferenceTarget('fancy-form-2', 'reset-button-2', "Reference target works with form attribute via options.");
document.getElementById('reset-button-3').setAttribute('form', "fancy-form-3");
testFormWithReferenceTarget('fancy-form-3', 'reset-button-3', "Reference target works with setAttribute('form')");
</script>
<form-associated-custom-button id="custom-button" form="fancy-form-4"></form-associated-custom-button>
<fancy-form-4 id="fancy-form-4">
<template shadowrootmode="open" shadowrootreferencetarget="real-form">
<form id="real-form">
<input type="text" value="default value">
<!-- The internal button of the custom button below shouldn't be associated with real-form -->
<form-associated-custom-button id="custom-button-in-shadow"></form-associated-custom-button>
</form>
</template>
</fancy-form-4>
<script>
class FormAssociatedCustomButton extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals_ = this.attachInternals();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `<button>fancy button</button>`;
}
}
window.customElements.define("form-associated-custom-button", FormAssociatedCustomButton);
test(function () {
const customElement = document.getElementById("custom-button");
const fancyForm = document.getElementById("fancy-form-4");
const realForm = fancyForm.shadowRoot.getElementById("real-form");
const customElementInShadow = fancyForm.shadowRoot.getElementById("custom-button-in-shadow");
const input = realForm.firstElementChild;
assert_equals(realForm.elements.length, 3, "The .elements property should have 3 elements.");
assert_equals(realForm.elements[0], customElement, "The first element should be the form-associated custom element.");
assert_equals(realForm.elements[1], input, "The 2nd element should be the input inside the real form.");
assert_equals(realForm.elements[2], customElementInShadow, "The 3rd element should be the custom element inside the real form.");
// Swap the input and the custom element in real-form.
realForm.moveBefore(customElementInShadow, input);
assert_equals(realForm.elements.length, 3, "The .elements property should have 3 elements.");
assert_equals(realForm.elements[0], customElement, "The first element should be the form-associated custom element.");
assert_equals(realForm.elements[1], customElementInShadow, "The 2nd element should be the custom element inside the real form.");
assert_equals(realForm.elements[2], input, "The 3rd element should be the input inside the real form.");
// Swap the referencing element and the fancy form
customElement.parentNode.moveBefore(fancyForm, customElement);
assert_equals(realForm.elements.length, 3, "The .elements property should have 3 elements.");
assert_equals(realForm.elements[0], customElementInShadow, "The first element should be the custom element inside the real form.");
assert_equals(realForm.elements[1], input, "The 2nd element should be the input inside the real form.");
assert_equals(realForm.elements[2], customElement, "The 3rd element should be the form-associated custom element.");
}, "Reference target works with form-associated custom element.");
</script>
<button id="reset-button-5" type="reset" form="fancy-form-5"></button>
<fancy-form-5 id="fancy-form-5">
<template shadowrootmode="open" shadowrootreferencetarget="nested-element">
<nested-element id="nested-element">
<template shadowrootmode="open" shadowrootreferencetarget="real-form">
<form id="real-form">
<input type="text" value="default value">
</form>
</template>
</nested-element>
<button id="button-in-shadow" form="nested-element"></button>
<div>
<template shadowrootmode="open">
<!-- This button shouldn't link to the real form in nested-element as it's in a different tree scope -->
<button id="button-in-different-shadow" form="nested-element"></button>
</template>
</div>
</template>
</fancy-form-5>
<script>
test(function () {
const fancyForm = document.getElementById("fancy-form-5");
const nestedElement = fancyForm.shadowRoot.getElementById("nested-element");
const buttonInShadow = fancyForm.shadowRoot.getElementById("button-in-shadow");
const realForm = nestedElement.shadowRoot.getElementById("real-form");
const input = realForm.firstElementChild;
input.value = "new value";
const resetButton = document.getElementById("reset-button-5");
assert_equals(realForm.elements.length, 3, "The .elements property should have 3 elements.");
// The elements in .elements property should be in tree order (preorder, depth-first).
assert_equals(realForm.elements[0], resetButton, "The first element should be the referencing element.");
assert_equals(realForm.elements[1], input, "The 2nd element should be the input inside the real form.");
assert_equals(realForm.elements[2], buttonInShadow, "The 3rd element should be the button in the shadow dom.");
assert_equals(input.value, "new value", "The input value should be updated to the new value.");
resetButton.click();
assert_equals(input.value, "default value", "The input value should be reset to the default value.");
// Remove the button that's using reference target in the 1st level shadow.
buttonInShadow.remove();
assert_equals(realForm.elements.length, 2, "The .elements property should have 2 elements after removing the button.");
// Add a new button using reference target in the 1st level shadow.
const newButtonInShadow = document.createElement("button");
newButtonInShadow.setAttribute("form", "nested-element");
nestedElement.parentNode.insertBefore(newButtonInShadow, nestedElement);
assert_equals(realForm.elements.length, 3, "The .elements property should have 3 elements after a new button is inserted.");
assert_equals(realForm.elements[0], resetButton, "The first element should be the referencing element.");
assert_equals(realForm.elements[1], newButtonInShadow, "The 2nd element should be the button in the shadow dom.");
assert_equals(realForm.elements[2], input, "The 3rd element should be the input inside the real form.");
}, "Reference target works with nested shadow trees.");
</script>
</body>
</html>