| <!DOCTYPE HTML> | |
| <meta charset="UTF-8"> | |
| <title>CSS Toggles: toggle-visibility</title> | |
| <link rel="author" title="L. David Baron" href="https://dbaron.org/"> | |
| <link rel="author" title="Google" href="http://www.google.com/"> | |
| <link rel="help" href="https://tabatkins.github.io/css-toggle/#toggle-visibility-property"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="support/toggle-helpers.js"></script> | |
| <style id="style"> | |
| </style> | |
| <body> | |
| <div id="container"></div> | |
| <script> | |
| let style = document.getElementById("style"); | |
| let container = document.getElementById("container"); | |
| promise_test(async function() { | |
| style.innerText = ` | |
| #container { toggle-group: t self; } | |
| #t, #t2 { toggle-root: t 1 at 0 group; } | |
| #trigger, #t2 { toggle-trigger: t; } | |
| #vis { toggle-visibility: toggle t; } | |
| #child { height: 100px; } | |
| `; | |
| container.innerHTML = ` | |
| <div id="t"></div> | |
| <div id="vis"> | |
| <div id="child"></div> | |
| </div> | |
| <div id="trigger"></div> | |
| <div id="t2"></div> | |
| `; | |
| let t = document.getElementById("t"); | |
| let trigger = document.getElementById("trigger"); | |
| let t2 = document.getElementById("t2"); | |
| let vis = document.getElementById("vis"); | |
| await wait_for_toggle_creation(t); | |
| const kVisibleHeight = 100; | |
| const kHiddenHeight = 0; | |
| assert_equals(vis.clientHeight, kHiddenHeight, "before first click"); | |
| trigger.click(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "after first click"); | |
| trigger.click(); | |
| assert_equals(vis.clientHeight, kHiddenHeight, "after second click"); | |
| t.toggles.get("t").value = 1; | |
| assert_equals(vis.clientHeight, kVisibleHeight, "after toggle value setter"); | |
| t2.click(); | |
| assert_equals(vis.clientHeight, kHiddenHeight, "after click on other element in group"); | |
| }, "showing and hiding in response to toggle changes"); | |
| const action_tests = [ | |
| { | |
| name: "focus", | |
| markup: `<input type="checkbox" id="check">`, | |
| action: () => { | |
| document.getElementById("check").focus(); | |
| }, | |
| }, | |
| { | |
| name: "scrollIntoView", | |
| markup: `<input type="checkbox" id="check">`, | |
| action: () => { | |
| document.getElementById("check").scrollIntoView(); | |
| }, | |
| }, | |
| ]; | |
| for (let test of action_tests) { | |
| promise_test(async function() { | |
| style.innerText = ` | |
| #container { toggle-group: tab self; } | |
| #tab { toggle: tab 1 at 0 group; } | |
| #panel { toggle-visibility: toggle tab; } | |
| `; | |
| container.innerHTML = ` | |
| <div id="tab">Tab</div> | |
| <div id="panel"> | |
| ${test.markup} | |
| </div> | |
| `; | |
| let tab = document.getElementById("tab"); | |
| let panel = document.getElementById("panel"); | |
| await wait_for_toggle_creation(tab); | |
| let tab_toggle = tab.toggles.get("tab"); | |
| assert_equals(tab_toggle.value, 0, "toggle value before focus"); | |
| assert_equals(panel.clientHeight, 0, "panel height before focus"); | |
| test.action(); | |
| assert_equals(tab_toggle.value, 1, "toggle value after focus"); | |
| assert_not_equals(panel.clientHeight, 0, "panel height after focus"); | |
| }, `${test.name} inside hidden element changes a toggle to show it`); | |
| } | |
| const scope_tests = [ | |
| ` | |
| <div class="root-inactive"> | |
| <div class="vis expect-hidden"></div> | |
| </div> | |
| <div class="vis expect-hidden"></div> | |
| `, | |
| ` | |
| <div class="root-inactive-self"> | |
| <div class="vis expect-hidden"></div> | |
| </div> | |
| <div class="vis expect-shown"></div> | |
| `, | |
| ` | |
| <div class="root-active"> | |
| <div class="vis expect-shown"></div> | |
| </div> | |
| <div class="vis expect-shown"></div> | |
| `, | |
| ` | |
| <div class="root-active-self"> | |
| <div class="vis expect-shown"></div> | |
| </div> | |
| <div class="vis expect-shown"></div> | |
| `, | |
| ]; | |
| for (let test of scope_tests) { | |
| promise_test(async function() { | |
| container.innerHTML = test; | |
| style.innerText = ` | |
| .root-inactive { toggle-root: t 1 at 0; } | |
| .root-active { toggle-root: t 1 at 1; } | |
| .root-inactive-self { toggle-root: t 1 at 0 self; } | |
| .root-active-self { toggle-root: t 1 at 1 self; } | |
| .vis { | |
| toggle-visibility: toggle t; | |
| } | |
| .vis::before { | |
| content: ""; | |
| display: block; | |
| height: 100px; | |
| width: 100px; | |
| } | |
| `; | |
| await wait_for_toggle_creation(container.querySelector('[class^="root-"]')); | |
| for (let e of container.querySelectorAll('.expect-hidden')) { | |
| assert_equals(e.clientHeight, 0); | |
| } | |
| for (let e of container.querySelectorAll('.expect-shown')) { | |
| assert_equals(e.clientHeight, 100); | |
| } | |
| }, `scope test: ${test}`); | |
| } | |
| async function wait_for_content_visibility_auto() { | |
| return new Promise(resolve => { | |
| requestAnimationFrame(() => { | |
| requestAnimationFrame(resolve); | |
| }); | |
| }); | |
| } | |
| promise_test(async function() { | |
| style.innerText = ` | |
| #t { toggle-root: t 1 at 0; } | |
| #vis { | |
| toggle-visibility: toggle t; | |
| content-visibility: auto; | |
| min-height: 50px; | |
| } | |
| #child { height: 100px; } | |
| #spacer { height: 300vh; } | |
| `; | |
| // TODO (dbaron): Why doesn't padding-top on #container have the same effect | |
| // as this spacer? | |
| container.innerHTML = ` | |
| <div id="spacer"></div> | |
| <div id="t"></div> | |
| <div id="vis"> | |
| <div id="child"></div> | |
| </div> | |
| `; | |
| let t = document.getElementById("t"); | |
| let vis = document.getElementById("vis"); | |
| let spacer = document.getElementById("spacer"); | |
| await wait_for_toggle_creation(t); | |
| let toggle = t.toggles.get("t"); | |
| const kVisibleHeight = 100; | |
| const kHiddenHeight = 50; | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and offscreen"); | |
| toggle.value = 1; | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kHiddenHeight, "with toggle active and offscreen"); | |
| spacer.remove(); | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and onscreen"); | |
| toggle.value = 0; | |
| await wait_for_content_visibility_auto(); | |
| // Note that because content-visibility: auto implies contain-intrinsic-size: auto, | |
| // the rest of the expected heights are kVisibleHeight since that will be the last | |
| // remembered size. | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle inactive and onscreen"); | |
| toggle.value = 1; | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and onscreen (2)"); | |
| toggle.value = 0; | |
| t.before(spacer); | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle inactive and offscreen (2)"); | |
| spacer.remove(); | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle inactive and onscreen (2)"); | |
| toggle.value = 1; | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and onscreen (3)"); | |
| t.before(spacer); | |
| await wait_for_content_visibility_auto(); | |
| assert_equals(vis.clientHeight, kVisibleHeight, "with toggle active and offscreen (2)"); | |
| }, "interaction of toggle-visibility and content-visibility: auto"); | |
| promise_test(async function() { | |
| style.innerText = ` | |
| #t { toggle-root: t 1 at 0; } | |
| #vis { | |
| toggle-visibility: toggle t; | |
| content-visibility: hidden; | |
| } | |
| #child { height: 100px; } | |
| `; | |
| container.innerHTML = ` | |
| <div id="t"></div> | |
| <div id="vis"> | |
| <div id="child"></div> | |
| </div> | |
| `; | |
| let t = document.getElementById("t"); | |
| let vis = document.getElementById("vis"); | |
| await wait_for_toggle_creation(t); | |
| let toggle = t.toggles.get("t"); | |
| const kVisibleHeight = 100; | |
| const kHiddenHeight = 0; | |
| assert_equals(vis.clientHeight, kHiddenHeight, "with toggle inactive and offscreen"); | |
| toggle.value = 1; | |
| assert_equals(vis.clientHeight, kHiddenHeight, "with toggle active and offscreen"); | |
| }, "interaction of toggle-visibility and content-visibility: hidden"); | |
| </script> |