| <!doctype HTML> |
| <html> |
| <meta charset="utf8"> |
| <title>Content Visibility: intersection observer interactions</title> |
| <link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> |
| <link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> |
| <meta name="assert" content="content-visibility hidden is not intersecting from IO perspective"> |
| |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| |
| <style> |
| div { |
| width: 100px; |
| height: 100px; |
| } |
| #spacer { |
| height: 3000px; |
| } |
| .hidden { |
| content-visibility: hidden; |
| } |
| </style> |
| |
| <div id="target1"> |
| <div id="target2"></div> |
| </div> |
| <div id="target3"> |
| <div id="target4"></div> |
| </div> |
| <div id="spacer"></div> |
| <div id="find_me"></div> |
| |
| <script> |
| async_test((t) => { |
| let target1, target2, target3, target4; |
| let observer; |
| let entries = []; |
| |
| // Set everything up. |
| function enqueueStep1() { |
| target1 = document.getElementById("target1"); |
| target2 = document.getElementById("target2"); |
| target3 = document.getElementById("target3"); |
| target4 = document.getElementById("target4"); |
| |
| observer = new IntersectionObserver((new_entries) => { |
| entries = entries.concat(new_entries); |
| }); |
| observer.observe(target1); |
| observer.observe(target2); |
| observer.observe(target3); |
| observer.observe(target4); |
| |
| entries = entries.concat(observer.takeRecords()); |
| t.step(() => { assert_equals(entries.length, 0, "No initial notifications") }); |
| requestAnimationFrame(() => { |
| requestAnimationFrame(() => { |
| runStep1(); |
| }); |
| }); |
| } |
| |
| // Verify that all elements are visible at the start, with intersection events. |
| function runStep1() { |
| const step = arguments.callee.name; |
| t.step(() => { |
| assert_equals(entries.length, 4, step); |
| // Clear the observed visible targets. |
| for (let i = 0; i < entries.length; ++i) { |
| assert_true(entries[i].isIntersecting); |
| assert_true(entries[i].target === target1 || |
| entries[i].target === target2 || |
| entries[i].target === target3 || |
| entries[i].target === target4, step); |
| } |
| }); |
| |
| entries = []; |
| enqueueStep2(); |
| } |
| |
| // Lock target3. |
| async function enqueueStep2() { |
| target3.classList.add("hidden"); |
| requestAnimationFrame(() => { |
| requestAnimationFrame(() => { |
| runStep2(); |
| }); |
| }); |
| } |
| |
| // Verify that the hidden element received a not-intersecting event. |
| function runStep2() { |
| const step = arguments.callee.name; |
| t.step(() => { |
| assert_equals(entries.length, 1, step); |
| assert_false(entries[0].isIntersecting, step); |
| assert_equals(entries[0].target, target4, step); |
| }); |
| |
| entries = []; |
| enqueueStep3(); |
| } |
| |
| // Scroll all elements off screen. |
| function enqueueStep3() { |
| document.getElementById("find_me").scrollIntoView(); |
| requestAnimationFrame(() => { |
| requestAnimationFrame(() => { |
| runStep3(); |
| }); |
| }); |
| } |
| |
| // Verify that all elements received not intersecting event, except |
| // target4, which was already not intersecting due to being hidden. |
| function runStep3() { |
| const step = arguments.callee.name; |
| t.step(() => { |
| assert_equals(entries.length, 3, step); |
| for (let i = 0; i < entries.length; ++i) { |
| assert_false(entries[i].isIntersecting, step); |
| assert_not_equals(entries[i].target, target4, step); |
| } |
| }); |
| |
| entries = []; |
| enqueueStep4(); |
| } |
| |
| // Scroll the elements back on screen. |
| function enqueueStep4() { |
| target1.scrollIntoView(); |
| requestAnimationFrame(() => { |
| requestAnimationFrame(() => { |
| runStep4(); |
| }); |
| }); |
| } |
| |
| // Verify that all elements received not intersecting event, except |
| // target4, which remains not intersecting. |
| function runStep4() { |
| const step = arguments.callee.name; |
| t.step(() => { |
| assert_equals(entries.length, 3, step); |
| for (let i = 0; i < entries.length; ++i) { |
| assert_true(entries[i].isIntersecting); |
| assert_not_equals(entries[i].target, target4, step); |
| } |
| }); |
| |
| entries = []; |
| enqueueStep5(); |
| } |
| |
| // Unlock target3. |
| async function enqueueStep5() { |
| target3.classList.remove("hidden"); |
| requestAnimationFrame(() => { |
| requestAnimationFrame(() => { |
| runStep5(); |
| }); |
| }); |
| } |
| |
| function runStep5() { |
| const step = arguments.callee.name; |
| t.step(() => { |
| assert_equals(entries.length, 1, step); |
| assert_true(entries[0].isIntersecting, step); |
| assert_equals(entries[0].target, target4, step); |
| }); |
| t.done(); |
| } |
| |
| |
| window.onload = () => { |
| requestAnimationFrame(enqueueStep1); |
| }; |
| }, "IntersectionObserver interactions"); |
| </script> |