checkable.html (11594B)
1 <!DOCTYPE html> 2 <html> 3 <link rel=author href=mailto:dom@chromium.org> 4 <link rel=help href=https://open-ui.org/components/menu.explainer> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 8 <menubar> 9 <fieldset checkable=single> 10 <menuitem id=menubar-menuitem></menuitem> 11 </fieldset> 12 </menubar> 13 14 <menulist> 15 <menuitem id=menulist-menuitem-not-checkable></menuitem> 16 <fieldset checkable=single> 17 <menuitem id=menulist-menuitem-checkable></menuitem> 18 </fieldset> 19 <fieldset checkable=single> 20 <menuitem id=single1></menuitem> 21 <menuitem id=single2></menuitem> 22 <menuitem id=single3></menuitem> 23 </fieldset> 24 <fieldset checkable=multiple> 25 <menuitem id=multiple1></menuitem> 26 <menuitem id=multiple2></menuitem> 27 <menuitem id=multiple3></menuitem> 28 </fieldset> 29 <fieldset checkable=multiple> 30 <menuitem defaultchecked id=defaultCheckedItem>Default checked</menuitem> 31 </fieldset> 32 </menulist> 33 34 <script> 35 test(() => { 36 const mi = document.createElement('menuitem'); 37 assert_false(mi.checked, "defaults to unchecked when detached"); 38 assert_false(mi.matches(":checked")); 39 mi.checked = true; 40 assert_equals(mi.checked, false, "cannot be checked when detached"); 41 assert_false(mi.matches(":checked")); 42 43 document.body.append(mi); 44 45 assert_equals(mi.checked, false, "defaults to unchecked when connected"); 46 assert_false(mi.matches(":checked")); 47 mi.checked = true; 48 assert_equals(mi.checked, false, 49 "cannot be checked when not attached in a menulist"); 50 assert_false(mi.matches(":checked")); 51 52 mi.remove(); 53 }, "menuitem is not checkable on its own"); 54 55 test(() => { 56 const mi = document.querySelector("#menubar-menuitem"); 57 assert_equals(mi.checked, false, "menuitem in menubar is not checked"); 58 assert_false(mi.matches(":checked")); 59 mi.checked = true; 60 assert_equals(mi.checked, false, "menuitem in menubar cannot be checked"); 61 assert_false(mi.matches(":checked")); 62 }, "menuitem in menubar is not checkable"); 63 64 test(() => { 65 const nonCheckable = 66 document.querySelector("#menulist-menuitem-not-checkable"); 67 assert_equals(nonCheckable.checked, false, 68 "menuitem direct child of menulist is not checked"); 69 assert_false(nonCheckable.matches(":checked")); 70 nonCheckable.checked = true; 71 assert_equals(nonCheckable.checked, false, 72 "menuitem direct child of menulist cannot be checked"); 73 assert_false(nonCheckable.matches(":checked")); 74 75 const checkable = document.querySelector("#menulist-menuitem-checkable"); 76 assert_equals(nonCheckable.checked, false, 77 "checkable menuitem is not checked"); 78 assert_false(nonCheckable.matches(":checked")); 79 checkable.checked = true; 80 assert_equals(checkable.checked, true, "checkable menuitem is checked"); 81 assert_true(checkable.matches(":checked")); 82 }, "menuitem in menulist"); 83 84 test(() => { 85 assert_false(single1.checked, "single1 not checked"); 86 assert_false(single1.matches(":checked"), "single1 not :checked"); 87 assert_false(single2.checked, "single2 not checked"); 88 assert_false(single2.matches(":checked"), "single2 not :checked"); 89 assert_false(single3.checked, "single3 not checked"); 90 assert_false(single3.matches(":checked"), "single3 not :checked"); 91 92 single1.checked = true; 93 assert_true(single1.checked, "single1 IS checked [after single1 checked]"); 94 assert_true(single1.matches(":checked"), 95 "single1 IS :checked [after single1 checked]"); 96 assert_false(single2.checked, "single2 not checked [after single1 checked]"); 97 assert_false(single2.matches(":checked"), 98 "single2 not :checked [after single1 checked]"); 99 assert_false(single3.checked, "single3 not checked [after single1 checked]"); 100 assert_false(single3.matches(":checked"), 101 "single3 not :checked [after single1 checked]"); 102 103 single2.checked = true; 104 assert_false(single1.checked, "single1 not checked [after single2 checked]"); 105 assert_false(single1.matches(":checked"), 106 "single1 not :checked [after single2 checked]"); 107 assert_true(single2.checked, "single2 IS checked [after single1 checked]"); 108 assert_true(single2.matches(":checked"), 109 "single2 IS :checked [after single2 checked]"); 110 assert_false(single3.checked, "single3 not checked [after single2 checked]"); 111 assert_false(single3.matches(":checked"), 112 "single3 not :checked [after single2 checked]"); 113 114 single3.checked = true; 115 assert_false(single1.checked, "single1 not checked [after single3 checked]"); 116 assert_false(single1.matches(":checked"), 117 "single1 not :checked [after single3 checked]"); 118 assert_false(single2.checked, "single2 not checked [after single3 checked]"); 119 assert_false(single2.matches(":checked"), 120 "single2 not :checked [after single3 checked]"); 121 assert_true(single3.checked, "single3 IS checked [after single3 checked]"); 122 assert_true(single3.matches(":checked"), 123 "single3 IS :checked [after single3 checked]"); 124 }, "checkable menuitem exclusivity"); 125 126 test(() => { 127 assert_false(multiple1.checked, "multiple1 not checked"); 128 assert_false(multiple1.matches(":checked"), "multiple1 not :checked"); 129 assert_false(multiple2.checked, "multiple2 not checked"); 130 assert_false(multiple2.matches(":checked"), "multiple2 not :checked"); 131 assert_false(multiple3.checked, "multiple3 not checked"); 132 assert_false(multiple3.matches(":checked"), "multiple2 not :checked"); 133 134 multiple1.checked = true; 135 assert_true(multiple1.checked, "multiple1 checked [after multiple1 checked]"); 136 assert_true(multiple1.matches(":checked"), 137 "multiple1 IS :checked [after multiple1 checked]"); 138 assert_false(multiple2.checked, "multiple2 not checked [after multiple1 checked]"); 139 assert_false(multiple2.matches(":checked"), 140 "multiple2 not :checked [after multiple1 checked]"); 141 assert_false(multiple3.checked, "multiple3 not checked [after multiple1 checked]"); 142 assert_false(multiple3.matches(":checked"), 143 "multiple3 not :checked [after multiple1 checked]"); 144 145 multiple2.checked = true; 146 assert_true(multiple1.checked, "multiple1 checked [after multiple2 checked]"); 147 assert_true(multiple1.matches(":checked"), 148 "multiple1 IS :checked [after multiple2 checked]"); 149 assert_true(multiple2.checked, "multiple2 checked [after multiple2 checked]"); 150 assert_true(multiple2.matches(":checked"), 151 "multiple2 IS :checked [after multiple2 checked]"); 152 assert_false(multiple3.checked, "multiple3 not checked [after multiple2 checked]"); 153 assert_false(multiple3.matches(":checked"), 154 "multiple3 not :checked [after multiple2 checked]"); 155 156 multiple3.checked = true; 157 assert_true(multiple1.checked, "multiple1 checked [after multiple3 checked]"); 158 assert_true(multiple1.matches(":checked"), 159 "multiple1 IS :checked [after multiple3 checked]"); 160 assert_true(multiple2.checked, "multiple2 checked [after multiple3 checked]"); 161 assert_true(multiple2.matches(":checked"), 162 "multiple2 IS :checked [after multiple3 checked]"); 163 assert_true(multiple3.checked, "multiple3 checked [after multiple3 checked]"); 164 assert_true(multiple3.matches(":checked"), 165 "multiple3 IS checked [after multiple3 checked]"); 166 }, "checkable multiple"); 167 168 test(() => { 169 const menulist = document.createElement('menulist'); 170 const fieldset = menulist.appendChild(document.createElement('fieldset')); 171 fieldset.setAttribute("checkable", "single"); 172 const single1 = fieldset.appendChild(document.createElement('menuitem')); 173 const single2 = fieldset.appendChild(document.createElement('menuitem')); 174 175 single1.checked = true; 176 single2.checked = true; 177 178 assert_false(single1.checked, "single1 is unchecked"); 179 assert_true(single2.checked, "single2 is checked"); 180 }, "checkable menuitem exclusivity when disconnected"); 181 182 test(() => { 183 const menulist = document.createElement('menulist'); 184 const fieldset = menulist.appendChild(document.createElement('fieldset')); 185 fieldset.setAttribute("checkable", "single"); 186 const single1 = fieldset.appendChild(document.createElement('menuitem')); 187 188 single1.checked = true; 189 assert_true(single1.checked, true); 190 fieldset.removeAttribute('checkable'); 191 assert_false(single1.checked, 192 "menuitem gets unchecked after fieldset becomes uncheckable"); 193 single1.checked = true; 194 assert_false(single1.checked, 195 "menuitem cannot become checked after fieldset becomes uncheckable"); 196 }, "when fieldset becomes uncheckable, so do its menuitems"); 197 198 test(() => { 199 const menulist = document.createElement('menulist'); 200 const fieldset = menulist.appendChild(document.createElement('fieldset')); 201 fieldset.setAttribute("checkable", "multiple"); 202 const single1 = fieldset.appendChild(document.createElement('menuitem')); 203 const single2 = fieldset.appendChild(document.createElement('menuitem')); 204 205 single1.checked = true; 206 single2.checked = true; 207 fieldset.setAttribute("checkable", "single"); 208 assert_true(single1.checked, "first menuitem stays checked"); 209 assert_false(single2.checked, "second menuitem becomes unchecked"); 210 }, "fieldset multiple => single; all but the first checked menuitem gets " + 211 "reset"); 212 213 // Testing the `defaultchecked` content attribute and `defaultChecked` IDL 214 // attribute. 215 test(() => { 216 assert_true(defaultCheckedItem.checked, 217 "defaultchecked makes the menu item checked by default"); 218 assert_true(defaultCheckedItem.matches(":default"), 219 ":default matches when the defaultchecked attribute is present"); 220 221 // Unset the default while checkedness is still clean. 222 defaultCheckedItem.removeAttribute('defaultchecked'); 223 assert_false(defaultCheckedItem.defaultChecked, 224 "defaultChecked IDL attribute reflects the content attribute"); 225 assert_false(defaultCheckedItem.checked, 226 "Unsetting defaultchecked when checkedness is clean unchecks the item"); 227 assert_false(defaultCheckedItem.matches(":default"), 228 ":default does not match when defaultchecked attribute is missing or false (1/2)"); 229 230 // Toggle it again while checkedness is clean, but this time with the IDL 231 // attribute, which should reflect the content attribute. 232 defaultCheckedItem.defaultChecked = true; 233 assert_true(defaultCheckedItem.checked, 234 "Setting defaultChecked to true when checkedness is clean checks the item"); 235 assert_true(defaultCheckedItem.matches(":default"), 236 ":default matches when the defaultchecked attribute is set, even via IDL"); 237 238 // Unset checkedness, dirtying the default checkedness. 239 defaultCheckedItem.checked = false; 240 assert_true(defaultCheckedItem.defaultChecked, 241 "Default checkedness is still true"); 242 assert_false(defaultCheckedItem.checked, "checked becomes false"); 243 assert_true(defaultCheckedItem.matches(":default"), 244 "still matches the default checkedness"); 245 246 // Unset default checkedness. This will only have the effect of changing the 247 // :default pseudo-class matching. 248 defaultCheckedItem.defaultChecked = false; 249 assert_false(defaultCheckedItem.matches(":default"), 250 ":default no longer matches"); 251 252 // Set default checkedness back to true. Since the checkedness is now dirty, 253 // this won't change the actual checked state anymore, as the menu item has 254 // had its default checkedness overridden. 255 defaultCheckedItem.defaultChecked = true; 256 assert_false(defaultCheckedItem.checked, 257 "checked state is no longer dictated by default checkedness any"); 258 assert_true(defaultCheckedItem.matches(":default"), 259 ":default matches again, following the default checkedness, even " + 260 "though the checkedness is dirty"); 261 }, "Default checkedness and checkedness dirtying are wired up correctly"); 262 </script>