input-pseudo-classes-in-has.html (6739B)
1 <!DOCTYPE html> 2 <meta charset="utf-8" /> 3 <title>CSS Selectors Invalidation: input pseudo classes in :has() argument</title> 4 <link rel="author" title="Byungwoo Lee" href="blee@igalia.com"> 5 <link rel="help" href="https://drafts.csswg.org/selectors/#relational"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <style> 9 .ancestor:has(#checkme:checked) { color: green } 10 .ancestor:has(#checkme:indeterminate) { color: yellowgreen } 11 .ancestor:has(#checkme:disabled) { color: blue } 12 .ancestor:has(#textinput:read-only) { color: skyblue } 13 .ancestor:has(#textinput:placeholder-shown) { color: navy } 14 .ancestor:has(#radioinput:default) { color: lightblue } 15 .ancestor:has(#textinput:valid) { color: lightgreen } 16 .ancestor:has(#numberinput:out-of-range) { color: darkgreen } 17 .ancestor:has(#numberinput:required) { color: pink } 18 .ancestor:has(#progress:indeterminate) { color: orange } 19 .ancestor:has(#checkboxinput:default) { color: purple; } 20 </style> 21 <div id=subject class=ancestor> 22 <input type="checkbox" name="my-checkbox" id="checkme"> 23 <label for="checkme">Check me!</label> 24 <input type="text" id="textinput" required> 25 <input id="radioinput" checked> 26 <input id="numberinput" type="number" min="1" max="10" value="5"> 27 <progress id="progress" value="50" max="100"></progress> 28 <input id="checkboxinput" type="checkbox"> 29 </div> 30 <script> 31 test(function() { 32 let input = null; 33 this.add_cleanup(() => { 34 if (input) { 35 // Need to put the input back for the rest of the tests. 36 subject.prepend(input); 37 } 38 checkme.checked = false; 39 }); 40 checkme.checked = false; 41 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 42 "ancestor should be black"); 43 checkme.checked = true; 44 assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)", 45 "ancestor should be green"); 46 checkme.indeterminate = true; 47 assert_equals(getComputedStyle(subject).color, "rgb(154, 205, 50)", 48 "ancestor should be yellowgreen"); 49 input = checkme; 50 checkme.remove(); 51 input.indeterminate = false; 52 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 53 "ancestor should be black"); 54 55 subject.prepend(input); 56 input = null; 57 checkme.checked = true; 58 assert_equals(getComputedStyle(subject).color, "rgb(0, 128, 0)", 59 "ancestor should be green"); 60 }, ":checked & :indeterminate invalidation on <input>"); 61 62 test(function() { 63 this.add_cleanup(() => { 64 progress.setAttribute("value", "50"); 65 }); 66 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 67 "ancestor should be black"); 68 progress.removeAttribute("value"); 69 assert_equals(getComputedStyle(subject).color, "rgb(255, 165, 0)", 70 "ancestor should be orange"); 71 }, ":indeterminate invalidation on <progress>"); 72 73 test(function() { 74 this.add_cleanup(() => { 75 checkme.disabled = false; 76 }); 77 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 78 "ancestor should be black"); 79 checkme.disabled = true; 80 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 255)", 81 "ancestor should be blue"); 82 }, ":disabled invalidation"); 83 84 test(function() { 85 this.add_cleanup(() => { 86 textinput.readOnly = false; 87 }); 88 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 89 "ancestor should be black"); 90 textinput.readOnly = true; 91 assert_equals(getComputedStyle(subject).color, "rgb(135, 206, 235)", 92 "ancestor should be skyblue"); 93 }, ":read-only invalidation"); 94 95 test(function() { 96 this.add_cleanup(() => { 97 textinput.value = ""; 98 }); 99 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 100 "ancestor should be black"); 101 textinput.value = "text input"; 102 assert_equals(getComputedStyle(subject).color, "rgb(144, 238, 144)", 103 "ancestor should be lightgreen"); 104 }, ":valid invalidation"); 105 106 test(function() { 107 this.add_cleanup(() => { 108 radioinput.removeAttribute("type"); 109 }); 110 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 111 "ancestor should be black"); 112 radioinput.type = 'radio'; 113 assert_equals(getComputedStyle(subject).color, "rgb(173, 216, 230)", 114 "ancestor should be lightblue"); 115 }, ":default invalidation with input[type=radio]"); 116 117 test(function() { 118 this.add_cleanup(() => { 119 numberinput.required = false; 120 }); 121 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 122 "ancestor should be black"); 123 numberinput.required = true; 124 assert_equals(getComputedStyle(subject).color, "rgb(255, 192, 203)", 125 "ancestor should be pink"); 126 }, ":required invalidation"); 127 128 test(function() { 129 this.add_cleanup(() => { 130 numberinput.value = 5; 131 }); 132 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 133 "ancestor should be black"); 134 numberinput.value = 12; 135 assert_equals(getComputedStyle(subject).color, "rgb(0, 100, 0)", 136 "ancestor should be darkgreen"); 137 }, ":out-of-range invalidation"); 138 139 test(function() { 140 this.add_cleanup(() => { 141 textinput.removeAttribute("placeholder"); 142 }); 143 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 144 "ancestor should be black"); 145 textinput.placeholder = 'placeholder text'; 146 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 128)", 147 "ancestor should be navy"); 148 }, ":placeholder-shown invalidation"); 149 150 test(function() { 151 this.add_cleanup(() => { 152 checkboxinput.checked = false; 153 checkboxinput.removeAttribute("checked"); 154 }); 155 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 156 "ancestor should be black"); 157 checkboxinput.checked = true; 158 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 159 "ancestor should still be black"); 160 checkboxinput.setAttribute("checked", ""); 161 assert_equals(getComputedStyle(subject).color, "rgb(128, 0, 128)", 162 "ancestor should be purple"); 163 checkboxinput.checked = false; 164 assert_equals(getComputedStyle(subject).color, "rgb(128, 0, 128)", 165 "ancestor should still be purple"); 166 checkboxinput.removeAttribute("checked"); 167 assert_equals(getComputedStyle(subject).color, "rgb(0, 0, 0)", 168 "ancestor should be black"); 169 }, ":default invalidation with input[type=checkbox] and assignment to .checked"); 170 </script>