tree-roles.html (5353B)
1 <!doctype html> 2 <html> 3 <head> 4 <title>Tree related Role Verification Tests</title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/resources/testdriver.js"></script> 8 <script src="/resources/testdriver-vendor.js"></script> 9 <script src="/resources/testdriver-actions.js"></script> 10 <script src="/wai-aria/scripts/aria-utils.js"></script> 11 </head> 12 <style> 13 /* Hide collapsed rows */ 14 [role="treegrid"] tr.hidden { 15 display: none; 16 } 17 18 /* Indents */ 19 [role="treegrid"] tr[aria-level="2"] > td:first-child { 20 padding-left: 2ch; 21 } 22 23 [role="treegrid"] tr[aria-level="3"] > td:first-child { 24 padding-left: 4ch; 25 } 26 27 /* Collapse/expand icons */ 28 [role="treegrid"] tr > td:first-child::before { 29 content: ""; 30 display: inline-block; 31 width: 2ch; 32 height: 11px; 33 transition: transform 0.3s; 34 transform-origin: 5px 5px; 35 } 36 37 [role="treegrid"] tr[aria-expanded] > td:first-child::before, 38 [role="treegrid"] td[aria-expanded]:first-child::before { 39 cursor: pointer; 40 41 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpolygon fill='black' points='2,0 2,10 10,5'%3E%3C/polygon%3E%3C/svg%3E%0A"); 42 background-repeat: no-repeat; 43 } 44 45 [role="treegrid"] tr[aria-expanded="true"] > td:first-child::before, 46 [role="treegrid"] td[aria-expanded="true"]:first-child::before { 47 transform: rotate(90deg); 48 } 49 </style> 50 <body> 51 52 <p>Tests <a href="https://w3c.github.io/aria/#tree">tree</a> and related roles.</p> 53 54 <ul role="tree" data-testname="role is tree" data-expectedrole="tree" class="ex"> 55 <li role="treeitem" data-testname="role is treeitem (in tree)" data-expectedrole="treeitem" class="ex"> 56 x 57 <ul role="group" data-testname="role is group (in treeitem)" data-expectedrole="group" class="ex"> 58 <li role="treeitem" data-testname="role is treeitem (in group, in treeitem)" data-expectedrole="treeitem" class="ex">x</li> 59 <li role="treeitem">x</li> 60 </ul> 61 </li> 62 <li role="treeitem">x</li> 63 </ul> 64 65 <table role="treegrid" data-testname="role is treegrid" data-expectedrole="treegrid" class="ex"> 66 <tbody> 67 <tr role="row" aria-expanded="true" aria-level="1" aria-posinset="1" aria-setsize="2" data-testname="role is row (in treegrid)" data-expectedrole="row" class="ex expander"> 68 <td role="gridcell" data-testname="role is gridcell (in row, in treegrid)" data-expectedrole="gridcell" class="ex">x</td> 69 <td role="gridcell">x</td> 70 <td role="gridcell">x</td> 71 </tr> 72 <tr role="row" aria-level="2" aria-posinset="1" aria-setsize="2"> 73 <td role="gridcell">x</td> 74 <td role="gridcell">x</td> 75 <td role="gridcell">x</td> 76 </tr> 77 <tr aria-expanded="false" aria-level="2" aria-posinset="2" aria-setsize="2" role="row" class="expander"> 78 <td role="gridcell">x</td> 79 <td role="gridcell">x</td> 80 <td role="gridcell">x</td> 81 </tr> 82 <tr role="row" aria-level="3" aria-posinset="1" aria-setsize="1" class="hidden"> 83 <td role="gridcell">x</td> 84 <td role="gridcell">x</td> 85 <td role="gridcell">x</td> 86 </tr> 87 <tr role="row" aria-expanded="false" aria-level="1" aria-posinset="2" aria-setsize="2" class="expander"> 88 <td role="gridcell">x</td> 89 <td role="gridcell">x</td> 90 <td role="gridcell">x</td> 91 </tr> 92 <tr role="row" aria-level="2" aria-posinset="1" aria-setsize="2" class="hidden"> 93 <td role="gridcell">x</td> 94 <td role="gridcell">x</td> 95 <td role="gridcell">x</td> 96 </tr> 97 <tr role="row" aria-level="2" aria-posinset="1" aria-setsize="2" class="hidden"> 98 <td role="gridcell">x</td> 99 <td role="gridcell">x</td> 100 <td role="gridcell">x</td> 101 </tr> 102 </tbody> 103 </table> 104 105 <script> 106 AriaUtils.verifyRolesBySelector(".ex"); 107 108 const expanders = document.querySelectorAll(".expander"); 109 expanders.forEach((expander) => { 110 expander.addEventListener("click", () => { 111 112 const expanderLevel = parseInt(expander.getAttribute("aria-level")) 113 let nextSibling = expander.nextElementSibling; 114 115 // Toggle aria-expanded for the row being expanded 116 let isExpanding = expander.getAttribute("aria-expanded") !== "true"; 117 expander.setAttribute("aria-expanded", isExpanding.toString()); 118 119 while (nextSibling) { 120 const nextSiblingLevel = parseInt(nextSibling.getAttribute("aria-level")); 121 122 // Don't expand rows found on the same level 123 if (nextSiblingLevel === expanderLevel) nextSibling = null; 124 125 if (isExpanding) { 126 // Don't expand rows beyond the next level if an ".expander" row is found as the nextSibling 127 if (nextSiblingLevel - expanderLevel === 1) { 128 nextSibling.classList.remove("hidden"); 129 // Don't expand sub rows found 130 if (nextSibling.hasAttribute("aria-expanded")) nextSibling.setAttribute("aria-expanded", "false"); 131 } 132 } else { 133 // Only expand rows that are more "indented" than the ".expander" row. A higher aria-level indicates a 134 // higher "level" 135 if (nextSiblingLevel > expanderLevel) { 136 nextSibling.classList.add("hidden"); 137 } 138 } 139 140 nextSibling = nextSibling.nextElementSibling; 141 } 142 }); 143 }); 144 </script> 145 146 </body> 147 </html>