prefer-targeted-element-main-frame-target.html (5257B)
1 <!DOCTYPE html> 2 <html> 3 <body> 4 <style> 5 #space { 6 height: 300vh; 7 width: 300vw; 8 position: absolute; 9 } 10 #scroller { 11 overflow-y: scroll; 12 scroll-snap-type: y mandatory; 13 width: 450px; 14 height: 450px; 15 border: solid 1px black; 16 position: relative; 17 } 18 .box { 19 height: 200px; 20 width: 200px; 21 position: absolute; 22 background-color: green; 23 scroll-snap-align: start; 24 } 25 .box:target { 26 background-color: red; 27 } 28 .toprow { top: 0px; } 29 .midrow { top: 210px; } 30 .bottomrow { top: 420px; } 31 .leftcol { left: 0px; } 32 .midcol { left: 210px; } 33 .rightcol { left: 420px; } 34 </style> 35 <div id="scroller"> 36 <div id="space"></div> 37 <div class="leftcol toprow box" id="box1"></div> 38 <div class="midcol toprow box" id="box2"></div> 39 <div class="rightcol toprow box" id="box3"></div> 40 <div class="leftcol midrow box" id="box4"></div> 41 <div class="midcol midrow box" id="box5"></div> 42 <div class="rightcol midrow box" id="box6"></div> 43 <div class="leftcol bottomrow box" id="box7"></div> 44 <div class="midcol bottomrow box" id="box8"></div> 45 <div class="rightcol bottomrow box" id="box9"></div> 46 </div> 47 <script> 48 // This test sets up a 3x3 grid within scroller: 49 // ------------------------- 50 // | Box 1 | Box 2 | Box 3 | 51 // ------------------------ 52 // | Box 4 | Box 5 | Box 6 | 53 // ------------------------- 54 // | Box 7 | Box 8 | Box 9 | 55 // ------------------------- 56 // This function just gets the boxes beside boxn on each row. 57 // E.g. box4: 4%3 = 1; so the boxes we want are box5 (4+1) and box6 (4+2). 58 function getAlignedBoxes(n) { 59 n = parseInt(n); 60 const mod_3 = n % 3; 61 let n1 = n - 1, n2 = n - 2; 62 if (mod_3 == 1) { 63 n1 = n + 1; 64 n2 = n + 2; 65 } else if (mod_3 == 2) { 66 n1 = n - 1; 67 n2 = n + 1; 68 } 69 return [document.getElementById(`box${n1}`), 70 document.getElementById(`box${n2}`)]; 71 } 72 73 function stashResult(key, result) { 74 fetch(`/css/css-scroll-snap/snap-after-relayout` + 75 `/multiple-aligned-targets/stash.py?key=${key}`, { 76 method: "POST", 77 body: JSON.stringify(result) 78 }).then(() => { 79 window.close(); 80 }); 81 } 82 83 function assert_equals(test_number, v1, v2, description) { 84 if (v1 != v2) { 85 throw new Error( 86 `Test ${n} expected equality of ${v1} and ${v2}, ` + 87 `Description: ${description}`); 88 } 89 } 90 91 async function waitForScrollReset(scroller, x = 0, y = 0) { 92 return new Promise((resolve) => { 93 if (scroller.scrollLeft == x && scroller.scrollTop == y) { 94 resolve(); 95 } else { 96 scroller.addEventListener("scrollend", resolve); 97 scroller.scrollTo(x, y); 98 } 99 }); 100 } 101 102 async function setLocationHash(id) { 103 return new Promise((resolve) => { 104 if (location.hash === `#${id}`) { 105 resolve(); 106 } else { 107 window.addEventListener("hashchange", resolve); 108 location.hash = `#${id}`; 109 } 110 }); 111 } 112 113 let result = { 114 passed: 0, 115 errors: "", 116 }; 117 118 async function test(n) { 119 try { 120 const target_id = `box${n}`; 121 const target = document.getElementById(target_id); 122 123 // Make boxn the targeted element. 124 await setLocationHash(target_id); 125 126 // Reset the scroll position. 127 await waitForScrollReset(scroller); 128 129 const aligned_boxes = getAlignedBoxes(n); 130 // Make sure all the boxes are equally aligned. 131 assert_equals(n, aligned_boxes[0].offsetTop, target.offsetTop, 132 `${aligned_boxes[0].id} is at offset ${target.offsetTop}`); 133 assert_equals(n, aligned_boxes[1].offsetTop, target.offsetTop, 134 `${aligned_boxes[1].id} is at offset ${target.offsetTop}`); 135 136 // Scroll to the aligned boxes. 137 await waitForScrollReset(scroller, 0, target.offsetTop); 138 assert_equals(n, scroller.scrollTop, target.offsetTop, 139 `scrolled to ${target.id} at offset ${target.offsetTop}`); 140 141 // Save target's original top. 142 const original_top = getComputedStyle(target).top; 143 const original_offset_top = target.offsetTop; 144 145 // Move target along the y axis. 146 target.style.top = `${target.offsetTop + 100}px`; 147 148 // Assert that scroller followed target as it moved down. 149 assert_equals(n, scroller.scrollTop, target.offsetTop, 150 `scrolled followed ${target.id} to offset ${target.offsetTop}`); 151 152 // Cleanup: undo style change. 153 target.style.top = original_top; 154 assert_equals(n, target.offsetTop, original_offset_top, 155 `${target.id} is put back to offset ${original_offset_top}`); 156 157 // Record the result. 158 result.passed += 1; 159 } catch (error) { 160 result.errors = [result.errors, error.message].join(); 161 } 162 } 163 164 window.onload = async () => { 165 let key = (new URL(document.location)).searchParams.get("key"); 166 167 for (const n of [1, 2, 3, 4, 5, 6, 7, 8, 9]) { 168 await test(n); 169 } 170 171 stashResult(key, result); 172 } 173 </script> 174 </body> 175 176 </html>