| <!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(); |
| assert_equals(vis.clientHeight, kHiddenHeight, "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, kHiddenHeight, "with toggle inactive and offscreen (2)"); |
| spacer.remove(); |
| await wait_for_content_visibility_auto(); |
| assert_equals(vis.clientHeight, kHiddenHeight, "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, kHiddenHeight, "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> |