dir-pseudo-on-input-element.html (7449B)
1 <!DOCTYPE html> 2 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> 3 <link rel="help" href="https://html.spec.whatwg.org/multipage/dom.html#the-directionality"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <body> 7 <script> 8 test(() => { 9 const input = document.createElement('input'); 10 input.type = 'tel'; 11 assert_true(input.matches(':dir(ltr)')); 12 assert_false(input.matches(':dir(rtl)')); 13 14 input.setAttribute('dir', 'foo'); 15 assert_true(input.matches(':dir(ltr)')); 16 assert_false(input.matches(':dir(rtl)')); 17 18 input.setAttribute('dir', 'rtl'); 19 assert_false(input.matches(':dir(ltr)')); 20 assert_true(input.matches(':dir(rtl)')); 21 22 input.setAttribute('dir', 'RTL'); 23 assert_false(input.matches(':dir(ltr)')); 24 assert_true(input.matches(':dir(rtl)')); 25 26 input.setAttribute('dir', 'ltr'); 27 assert_true(input.matches(':dir(ltr)')); 28 assert_false(input.matches(':dir(rtl)')); 29 30 input.setAttribute('dir', 'LTR'); 31 assert_true(input.matches(':dir(ltr)')); 32 assert_false(input.matches(':dir(rtl)')); 33 34 input.setAttribute('dir', 'auto'); 35 assert_true(input.matches(':dir(ltr)')); 36 assert_false(input.matches(':dir(rtl)')); 37 38 input.value = '\u05EA'; 39 assert_false(input.matches(':dir(ltr)')); 40 assert_true(input.matches(':dir(rtl)')); 41 42 input.setAttribute('dir', 'AUTO'); 43 assert_false(input.matches(':dir(ltr)')); 44 assert_true(input.matches(':dir(rtl)')); 45 46 input.removeAttribute('dir'); 47 assert_true(input.matches(':dir(ltr)')); 48 assert_false(input.matches(':dir(rtl)')); 49 }, 'input element whose type attribute is in the telephone state'); 50 51 test(() => { 52 const input = document.createElement('input'); 53 input.type = 'tel'; 54 55 const container = document.createElement('div'); 56 container.setAttribute('dir', 'rtl'); 57 container.appendChild(input); 58 59 // Insert the element into the document so that we can also check for 60 // 'direction' in computed style. 61 document.body.appendChild(container); 62 63 assert_true(input.matches(':dir(ltr)')); 64 assert_false(input.matches(':dir(rtl)')); 65 // Per https://html.spec.whatwg.org/multipage/rendering.html#bidi-rendering: 66 assert_equals(getComputedStyle(input).direction, 'ltr'); 67 68 // Changing to a different type causes the special type=tel rule to no longer apply. 69 input.type = 'text'; 70 assert_false(input.matches(':dir(ltr)')); 71 assert_true(input.matches(':dir(rtl)')); 72 assert_equals(getComputedStyle(input).direction, 'rtl'); 73 74 // And restoring type=tel brings back that behavior. 75 input.type = 'tel'; 76 assert_true(input.matches(':dir(ltr)')); 77 assert_false(input.matches(':dir(rtl)')); 78 assert_equals(getComputedStyle(input).direction, 'ltr'); 79 80 document.body.removeChild(container); 81 }, 'input element whose type attribute is in the telephone state in a RTL block'); 82 83 for (const type of ['password', 'text', 'search', 'url', 'email', 'submit', 'reset', 'button', 'hidden']) { 84 test(() => { 85 const input = document.createElement('input'); 86 input.type = type; 87 assert_true(input.matches(':dir(ltr)')); 88 assert_false(input.matches(':dir(rtl)')); 89 90 input.setAttribute('dir', 'foo'); 91 assert_true(input.matches(':dir(ltr)')); 92 assert_false(input.matches(':dir(rtl)')); 93 94 input.setAttribute('dir', 'rtl'); 95 assert_false(input.matches(':dir(ltr)')); 96 assert_true(input.matches(':dir(rtl)')); 97 98 input.setAttribute('dir', 'RTL'); 99 assert_false(input.matches(':dir(ltr)')); 100 assert_true(input.matches(':dir(rtl)')); 101 102 input.setAttribute('dir', 'ltr'); 103 assert_true(input.matches(':dir(ltr)')); 104 assert_false(input.matches(':dir(rtl)')); 105 106 input.setAttribute('dir', 'LTR'); 107 assert_true(input.matches(':dir(ltr)')); 108 assert_false(input.matches(':dir(rtl)')); 109 110 input.setAttribute('dir', 'auto'); 111 assert_true(input.matches(':dir(ltr)')); 112 assert_false(input.matches(':dir(rtl)')); 113 114 input.value = '\u05EA'; 115 assert_false(input.matches(':dir(ltr)')); 116 assert_true(input.matches(':dir(rtl)')); 117 118 input.setAttribute('dir', 'AUTO'); 119 assert_false(input.matches(':dir(ltr)')); 120 assert_true(input.matches(':dir(rtl)')) 121 122 input.removeAttribute('dir'); 123 assert_true(input.matches(':dir(ltr)')); 124 assert_false(input.matches(':dir(rtl)')); 125 }, `input element whose type attribute is in the ${type} state`); 126 } 127 128 test(() => { 129 const input = document.createElement('input'); 130 input.type = 'text'; 131 // bidirectional character type R 132 input.value = '\u05EA'; 133 input.setAttribute('dir', 'auto'); 134 135 const container = document.createElement('div'); 136 container.appendChild(input); 137 138 assert_false(input.matches(':dir(ltr)')); 139 assert_true(input.matches(':dir(rtl)')); 140 141 // Changing to a different type that does't use value causes the bidi rule to no longer apply. 142 input.type = 'radio'; 143 assert_true(input.matches(':dir(ltr)')); 144 assert_false(input.matches(':dir(rtl)')); 145 146 // And restoring type=text brings back that behavior. 147 input.type = 'text'; 148 assert_false(input.matches(':dir(ltr)')); 149 assert_true(input.matches(':dir(rtl)')); 150 }, 'dynamic changes to type of input elements affect whether value is used for dir=auto'); 151 152 for (const type of ['date', 'time', 'number', 'range', 'color', 'checkbox', 'radio', 'image']) { 153 test(() => { 154 const input = document.createElement('input'); 155 input.type = type; 156 assert_true(input.matches(':dir(ltr)')); 157 assert_false(input.matches(':dir(rtl)')); 158 159 input.setAttribute('dir', 'foo'); 160 assert_true(input.matches(':dir(ltr)')); 161 assert_false(input.matches(':dir(rtl)')); 162 163 input.setAttribute('dir', 'rtl'); 164 assert_false(input.matches(':dir(ltr)')); 165 assert_true(input.matches(':dir(rtl)')); 166 167 input.setAttribute('dir', 'RTL'); 168 assert_false(input.matches(':dir(ltr)')); 169 assert_true(input.matches(':dir(rtl)')); 170 171 input.setAttribute('dir', 'ltr'); 172 assert_true(input.matches(':dir(ltr)')); 173 assert_false(input.matches(':dir(rtl)')); 174 175 input.setAttribute('dir', 'LTR'); 176 assert_true(input.matches(':dir(ltr)')); 177 assert_false(input.matches(':dir(rtl)')); 178 179 input.setAttribute('dir', 'auto'); 180 assert_true(input.matches(':dir(ltr)')); 181 assert_false(input.matches(':dir(rtl)')); 182 183 input.value = '\u05EA'; 184 assert_true(input.matches(':dir(ltr)')); 185 assert_false(input.matches(':dir(rtl)')); 186 187 input.setAttribute('dir', 'AUTO'); 188 assert_true(input.matches(':dir(ltr)')); 189 assert_false(input.matches(':dir(rtl)')) 190 191 input.removeAttribute('dir'); 192 assert_true(input.matches(':dir(ltr)')); 193 assert_false(input.matches(':dir(rtl)')); 194 195 let rtlParent = document.createElement("div"); 196 rtlParent.dir = "rtl"; 197 input.dir = "auto"; 198 rtlParent.appendChild(input); 199 document.body.appendChild(rtlParent); // Just for good measure. 200 assert_true(input.matches(':dir(ltr)')); 201 assert_false(input.matches(':dir(rtl)')); 202 rtlParent.remove(); 203 }, `input element whose type attribute is in the ${type} state`); 204 } 205 206 </script> 207 </body>