| <!DOCTYPE html> | |
| <title>CSSOM View - getBoxQuads() during custom element connection</title> | |
| <link rel="help" href="https://drafts.csswg.org/cssom-view/#the-geometryutils-interface"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="resources/geometry-utils.js"></script> | |
| <style> | |
| geometry-source { | |
| display: block; | |
| position: absolute; | |
| width: 80px; | |
| height: 24px; | |
| border: 2px solid; | |
| } | |
| geometry-source > span { | |
| box-sizing: border-box; | |
| position: absolute; | |
| left: var(--x); | |
| top: var(--y); | |
| width: 8px; | |
| height: 6px; | |
| border: 1px solid; | |
| } | |
| geometry-overlay { | |
| display: block; | |
| position: absolute; | |
| inset: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| #canvas { | |
| position: relative; | |
| } | |
| </style> | |
| <div id="canvas"></div> | |
| <script> | |
| const markerPositions = [ | |
| [3, 4], | |
| [14, 5], | |
| [25, 6], | |
| [36, 7], | |
| [47, 8], | |
| [58, 9], | |
| ]; | |
| const observations = []; | |
| const sources = []; | |
| customElements.define("geometry-overlay", class extends HTMLElement { | |
| connectedCallback() { | |
| observations.push([...this.source.children].map(marker => | |
| marker.getBoxQuads({relativeTo: this.relativeTo})[0])); | |
| } | |
| }); | |
| test(() => { | |
| assert_equals(typeof Element.prototype.getBoxQuads, "function", | |
| "Element.prototype.getBoxQuads"); | |
| const itemCount = 300; | |
| const canvas = document.getElementById("canvas"); | |
| for (let i = 0; i < itemCount; ++i) { | |
| const source = document.createElement("geometry-source"); | |
| source.style.left = `${(i % 100) * 2}px`; | |
| source.style.top = `${Math.floor(i / 100) * 2}px`; | |
| for (const [x, y] of markerPositions) { | |
| const marker = document.createElement("span"); | |
| marker.style.setProperty("--x", `${x}px`); | |
| marker.style.setProperty("--y", `${y}px`); | |
| source.appendChild(marker); | |
| } | |
| canvas.appendChild(source); | |
| sources.push(source); | |
| } | |
| canvas.offsetTop; | |
| for (const source of sources) { | |
| const overlay = document.createElement("geometry-overlay"); | |
| overlay.source = source; | |
| overlay.relativeTo = canvas; | |
| canvas.appendChild(overlay); | |
| } | |
| assert_equals(observations.length, itemCount, | |
| "every connected callback collected geometry"); | |
| for (let itemIndex = 0; itemIndex < observations.length; ++itemIndex) { | |
| assert_equals(observations[itemIndex].length, markerPositions.length, | |
| `item ${itemIndex} has one quad per marker`); | |
| } | |
| const sampleIndices = [...new Set([ | |
| 0, | |
| Math.floor(itemCount / 2), | |
| itemCount - 1, | |
| ])]; | |
| for (const itemIndex of sampleIndices) { | |
| const source = sources[itemIndex]; | |
| const stableQuads = [...source.children].map(marker => | |
| marker.getBoxQuads({relativeTo: canvas})[0]); | |
| for (let markerIndex = 0; markerIndex < markerPositions.length; | |
| ++markerIndex) { | |
| assert_quad_approx_equals( | |
| observations[itemIndex][markerIndex], stableQuads[markerIndex], | |
| `item ${itemIndex}, marker ${markerIndex}`); | |
| } | |
| } | |
| }, "getBoxQuads() returns current geometry from connectedCallback"); | |
| test(() => { | |
| const container = document.createElement("div"); | |
| container.style.cssText = | |
| "position:relative; overflow:auto; width:100px; height:100px"; | |
| const oldChild = document.createElement("div"); | |
| oldChild.style.cssText = | |
| "position:absolute; right:0; bottom:0; width:20px; height:20px"; | |
| container.appendChild(oldChild); | |
| document.body.appendChild(container); | |
| oldChild.getBoxQuads(); | |
| const overflowChild = document.createElement("div"); | |
| overflowChild.style.cssText = | |
| "position:absolute; left:200px; top:200px; width:20px; height:20px"; | |
| container.appendChild(overflowChild); | |
| const quad = oldChild.getBoxQuads({relativeTo: container})[0]; | |
| assert_approx_equals(quad.p2.x, container.clientWidth, 0.01, | |
| "right edge follows the resized containing block"); | |
| assert_approx_equals(quad.p3.y, container.clientHeight, 0.01, | |
| "bottom edge follows the resized containing block"); | |
| }, "getBoxQuads() updates reused OOF geometry after scrollbars appear"); | |
| </script> |