| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <title>Dynamic childlist of MathML elements</title> |
| <script src="/mathml/support/mathml-fragments.js"></script> |
| <link rel="help" href="https://w3c.github.io/mathml-core/#adjust-space-around-content-mpadded"> |
| <link rel="help" href="https://w3c.github.io/mathml-core/#dom-and-javascript"> |
| <meta name="assert" content="Dynamically modify DOM tree of some MathML elements by adding or removing children."> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/mathml/support/feature-detection.js"></script> |
| <script src="/mathml/support/layout-comparison.js"></script> |
| <script> |
| function generateMathForTag(tag, childCount) { |
| let math = FragmentHelper.createElement("math"); |
| let element = FragmentHelper.createElement(tag); |
| // Add the children with different sizes at odd positions and OOF |
| // mrow at even position. |
| for (let i = 0; i < childCount; i++) { |
| if (i % 2) { |
| let mspace = FragmentHelper.createElement("mspace"); |
| mspace.setAttribute("width", `10px`); |
| mspace.setAttribute("height", `${10*(i+1)}px`); |
| mspace.setAttribute("style", `background: black;`); |
| element.appendChild(mspace); |
| } else { |
| let mrow = FragmentHelper.createElement("mrow"); |
| mrow.setAttribute("style", "position: absolute"); |
| element.appendChild(mrow); |
| } |
| } |
| if (FragmentHelper.isValidChildOfMrow(tag)) { |
| math.appendChild(element); |
| } else if (tag === "mtd") { |
| let mtr = FragmentHelper.createElement("mtr"); |
| mtr.appendChild(element); |
| let mtable = FragmentHelper.createElement("mtable"); |
| mtable.appendChild(mtr); |
| math.appendChild(mtable); |
| } else { |
| throw `Invalid argument: ${tag}`; |
| } |
| return math; |
| } |
| |
| setup({ explicit_done: true }); |
| window.addEventListener("load", function() { |
| |
| for (tag in MathMLFragments) { |
| if (!FragmentHelper.isValidChildOfMrow(tag) || tag === "mtd") |
| continue; |
| |
| document.body.insertAdjacentHTML("beforeend", `<div style='display: none; background: pink;'>${tag}: <div></div><div></div><div></div></div>`); |
| |
| let container = document.body.lastElementChild; |
| let referenceDiv = container.children[0]; |
| const maxChild = 10; |
| const epsilon = 1; |
| |
| // Create the references for different number of children as well |
| // as the element that will get the children added / removed. |
| for (let i = 0; i <= maxChild; i++) |
| referenceDiv.append(generateMathForTag(tag, i)); |
| let fullReferenceMath = referenceDiv.lastElementChild; |
| let fullReferenceTag = fullReferenceMath.firstElementChild; |
| |
| let removeChildrenMath = generateMathForTag(tag, maxChild); |
| container.children[1].append(removeChildrenMath); |
| let removeChildrenTag = removeChildrenMath.firstElementChild; |
| |
| let appendChildrenMath = generateMathForTag(tag, 0); |
| container.children[2].append(appendChildrenMath); |
| let appendChildrenTag = appendChildrenMath.firstElementChild; |
| |
| // Make content visible after the DOM is ready so that the layout |
| // only happens now. |
| container.style.display = "block"; |
| |
| test(function() { |
| assert_true(MathMLFeatureDetection.has_mspace()); |
| assert_true(MathMLFeatureDetection[`has_${tag}`]()); |
| |
| for (let i = 0; i < maxChild; i++) { |
| // append and remove children. |
| appendChildrenTag.append(fullReferenceTag.children[i].cloneNode(true)); |
| removeChildrenTag.removeChild(removeChildrenTag.lastElementChild); |
| |
| // force layout so we're sure what we're testing against |
| container.getBoundingClientRect(); |
| |
| let appendCount = appendChildrenTag.children.length; |
| let removeCount = removeChildrenTag.children.length; |
| if (tag == "mspace") { |
| compareSize(appendChildrenTag, referenceDiv.children[appendCount].firstElementChild, epsilon); |
| childrenHaveEmptyBoundingClientRects(appendChildrenTag); |
| childrenHaveEmptyBoundingClientRects(referenceDiv.children[appendCount].firstElementChild); |
| childrenHaveEmptyBoundingClientRects(removeChildrenTag); |
| childrenHaveEmptyBoundingClientRects(referenceDiv.children[removeCount].firstElementChild); |
| } else { |
| compareLayout(appendChildrenTag, referenceDiv.children[appendCount].firstElementChild, epsilon, `appending ${appendCount}-th child`); |
| compareLayout(removeChildrenTag, referenceDiv.children[removeCount].firstElementChild, epsilon, `removing ${appendCount + 1}-th child`); |
| } |
| } |
| |
| // Hide back the div after successful testing. |
| container.style.display = "none"; |
| |
| }, `Appending and removing children to ${tag}`); |
| } |
| |
| done(); |
| }); |
| </script> |
| </head> |
| <body> |
| <div id="log"></div> |
| </body> |
| </html> |