Document-caretPositionFromPoint.tentative.html (16317B)
1 <!DOCTYPE html> 2 <html> 3 <body> 4 <meta name="author" title="Siye Liu" href="mailto:siliu@microsoft.com"> 5 <meta name="assert" content="Document's caretPositionFromPoint should return a CaretPosition inside Shadow Root which is provided as argument."> 6 <link rel="help" href="https://www.w3.org/TR/cssom-view-1/#dom-document-caretpositionfrompoint"> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <link rel="stylesheet" href="/fonts/ahem.css"> 10 <style> 11 textarea { 12 font: 20px/1 Ahem; 13 border: none; 14 padding: 0; 15 } 16 </style> 17 18 <div id="container"></div> 19 <script> 20 21 test(() => { 22 assert_throws_js(TypeError, () => { document.caretPositionFromPoint(5, 5, "foo"); }); 23 assert_throws_js(TypeError, () => { document.caretPositionFromPoint(5, 5, 6); }); 24 }, "document.caretPositionFromPoint() throws when called without the correct parameters"); 25 26 test(() => { 27 container.setHTMLUnsafe(`<span>hello, world</span>`); 28 const rect = container.firstChild.getBoundingClientRect(); 29 const characterWidth = rect.width / container.textContent.length; 30 const characterIndex = 2 31 // Get x and y coordinate at `he|llo, world`. 32 const x = rect.left + characterWidth * characterIndex; 33 const y = rect.top + rect.height / 2; 34 const caretPosition = document.caretPositionFromPoint(x, y, {}); 35 assert_true(caretPosition instanceof CaretPosition); 36 assert_true(caretPosition.offsetNode instanceof Text); 37 assert_equals(typeof(caretPosition.offset), "number"); 38 assert_equals(caretPosition.offsetNode, container.firstChild.firstChild); 39 assert_equals(caretPosition.offset, characterIndex); 40 }, "document.caretPositionFromPoint() should return a CaretPosition at the specified location"); 41 42 test(() => { 43 container.setHTMLUnsafe(`<input value='text inside input' />`); 44 const rect = container.firstChild.getBoundingClientRect(); 45 // Get x and y coordinate at left-most location inside input element. 46 const x = rect.left + 1; 47 const y = rect.top + rect.height / 2; 48 const caretPosition = document.caretPositionFromPoint(x, y); 49 assert_true(caretPosition instanceof CaretPosition); 50 assert_true(caretPosition.offsetNode instanceof Node); 51 assert_equals(typeof(caretPosition.offset), "number"); 52 assert_equals(caretPosition.offsetNode, container.firstChild); 53 assert_equals(caretPosition.offset, 0); 54 }, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to an input element which is the offsetNode."); 55 56 promise_test(async () => { 57 container.setHTMLUnsafe(`<textarea rows="3" cols="4">12345678\n901234567890</textarea>`); 58 await document.fonts.ready; 59 const rect = container.firstChild.getBoundingClientRect(); 60 // Get x and y coordinate at "1234|5678..." 61 const x = rect.left + 1; 62 const y = rect.top + rect.height * 0.5; 63 const caretPosition = document.caretPositionFromPoint(x, y); 64 assert_true(caretPosition instanceof CaretPosition); 65 assert_true(caretPosition.offsetNode instanceof Node); 66 assert_equals(typeof(caretPosition.offset), "number"); 67 assert_equals(caretPosition.offsetNode, container.firstChild); 68 assert_equals(caretPosition.offset, 4); 69 }, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to a textarea element which is the offsetNode."); 70 71 promise_test(async () => { 72 container.setHTMLUnsafe(`<textarea rows="3" cols="4">12345678\n901234567890</textarea>`); 73 await document.fonts.ready; 74 const element = container.firstChild; 75 const rect = element.getBoundingClientRect(); 76 const fontSize = parseInt(getComputedStyle(element).fontSize.match(/\d+/)[0]); 77 78 // Check a position after a forced break. 79 const caretPosition = document.caretPositionFromPoint( 80 rect.left + fontSize + 2, rect.bottom - fontSize / 2); 81 // caretPosition should point between '9' and '0'. 82 assert_equals(caretPosition.offsetNode, element); 83 assert_equals(caretPosition.offset, 10, 'offset'); 84 const caretRect = caretPosition.getClientRect(); 85 assert_equals(caretRect.left, rect.left + fontSize, 'caretRect.left'); 86 assert_greater_than(caretRect.bottom, rect.top + rect.height * 0.9, 87 'caretRect.bottom'); 88 }, "document.caretPositionFromPoint() for a point after a forced break should return a CaretPosition at the specified location pointing to a textarea element which is the offsetNode."); 89 90 test(() => { 91 container.setHTMLUnsafe(`a<div id="host"></div>b`); 92 const shadowRoot = host.attachShadow({mode: 'closed'}); 93 shadowRoot.setHTMLUnsafe(`<span>hello, world</span>`); 94 const rect = shadowRoot.firstChild.getBoundingClientRect(); 95 const characterWidth = rect.width / shadowRoot.textContent.length; 96 const characterIndex = 2 97 // Get x and y coordinate at `he|llo, world`. 98 const x = rect.left + characterWidth * characterIndex; 99 const y = rect.top + rect.height / 2; 100 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: [shadowRoot]}); 101 assert_true(caretPosition instanceof CaretPosition); 102 assert_true(caretPosition.offsetNode instanceof Text); 103 assert_equals(typeof(caretPosition.offset), "number"); 104 assert_equals(caretPosition.offsetNode, shadowRoot.firstChild.firstChild); 105 assert_equals(caretPosition.offset, characterIndex); 106 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to a closed shadow tree when the shadow tree is specified as an argument'); 107 108 test(() => { 109 container.setHTMLUnsafe(` 110 <span>abcd</span> 111 <div id="host"> 112 <template shadowrootmode=open> 113 <span>hello, world</span> 114 </template> 115 </div>efg`); 116 const shadowRoot = host.shadowRoot; 117 const spanElement = document.querySelector("span"); 118 const rect = spanElement.getBoundingClientRect(); 119 const characterWidth = rect.width / spanElement.textContent.length; 120 const characterIndex = 2 121 // Get x and y coordinate at `ab|cd`. 122 const x = rect.left + characterWidth * characterIndex; 123 const y = rect.top + rect.height / 2; 124 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: [shadowRoot]}); 125 assert_true(caretPosition instanceof CaretPosition); 126 assert_true(caretPosition.offsetNode instanceof Text); 127 assert_equals(typeof(caretPosition.offset), "number"); 128 assert_equals(caretPosition.offsetNode, spanElement.firstChild); 129 assert_equals(caretPosition.offset, characterIndex); 130 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location when the non-intersecting shadow tree is specified as an argument'); 131 132 test(() => { 133 container.setHTMLUnsafe(` 134 a<div id="host"> 135 <template shadowrootmode=open> 136 <input value='text inside input' /> 137 </template> 138 </div>efg`); 139 const shadowRoot = host.shadowRoot; 140 const shadowRootInputElement = shadowRoot.querySelector("input"); 141 const rect = shadowRootInputElement.getBoundingClientRect(); 142 // Get x and y coordinate at left-most location inside input element. 143 const x = rect.left + 1; 144 const y = rect.top + rect.height / 2; 145 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: [shadowRoot]}); 146 assert_true(caretPosition instanceof CaretPosition); 147 assert_true(caretPosition.offsetNode instanceof Node); 148 assert_equals(typeof(caretPosition.offset), "number"); 149 assert_equals(caretPosition.offsetNode, shadowRootInputElement); 150 assert_equals(caretPosition.offset, 0); 151 }, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to an input element when the shadow tree is specified as an argument."); 152 153 test(() => { 154 container.setHTMLUnsafe(` 155 a<div id="host"> 156 <template shadowrootmode=open> 157 <input value='text inside input' /> 158 </template> 159 </div>efg`); 160 const shadowRoot = host.shadowRoot; 161 const shadowRootInputElement = shadowRoot.querySelector("input"); 162 const rect = shadowRootInputElement.getBoundingClientRect(); 163 // Get x and y coordinate at left-most location inside input element. 164 const x = rect.left + 1; 165 const y = rect.top + rect.height / 2; 166 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: []}); 167 assert_true(caretPosition instanceof CaretPosition); 168 assert_true(caretPosition.offsetNode instanceof Node); 169 assert_equals(typeof(caretPosition.offset), "number"); 170 assert_equals(caretPosition.offsetNode, container); 171 assert_equals(caretPosition.offset, 1); 172 }, "document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the input element's shadow host\'s parent when the shadow tree is not specified as an argument."); 173 174 test(() => { 175 container.setHTMLUnsafe(` 176 a<div id="host"> 177 <template shadowrootmode=open> 178 <span>hello, world</span> 179 </template> 180 </div>b`); 181 const shadowRoot = host.shadowRoot; 182 const shadowRootSpanElement = shadowRoot.querySelector("span"); 183 const rect = shadowRootSpanElement.getBoundingClientRect(); 184 const characterWidth = rect.width / shadowRootSpanElement.textContent.length; 185 const characterIndex = 2 186 // Get x and y coordinate at `he|llo, world`. 187 const x = rect.left + characterWidth * characterIndex; 188 const y = rect.top + rect.height / 2; 189 const caretPosition = document.caretPositionFromPoint(x, y); 190 assert_true(caretPosition instanceof CaretPosition); 191 assert_true(caretPosition.offsetNode instanceof Node); 192 assert_equals(typeof(caretPosition.offset), "number"); 193 assert_equals(caretPosition.offsetNode, container); 194 assert_equals(caretPosition.offset, 1); 195 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the shadow host\'s parent when the shadow tree is not specified as an argument'); 196 197 test(() => { 198 container.setHTMLUnsafe(` 199 a<div id="outerHost"> 200 <template shadowrootmode=open> 201 <div id="innerHost"> 202 <template shadowrootmode=open> 203 <span>some text</span> 204 </template> 205 </div> 206 <div>world</div> 207 </template> 208 </div>b`); 209 const outerShadowRoot = outerHost.shadowRoot; 210 const innerShadowRoot = outerShadowRoot.getElementById('innerHost').shadowRoot; 211 const innerShadowRootSpanElement = innerShadowRoot.querySelector("span"); 212 const rect = innerShadowRootSpanElement.getBoundingClientRect(); 213 const characterWidth = rect.width / innerShadowRootSpanElement.textContent.length; 214 const characterIndex = 2 215 // Get x and y coordinate at `so|me text`. 216 const x = rect.left + characterWidth * characterIndex; 217 const y = rect.top + rect.height / 2; 218 const caretPosition = document.caretPositionFromPoint(x, y); 219 assert_true(caretPosition instanceof CaretPosition); 220 assert_true(caretPosition.offsetNode instanceof Node); 221 assert_equals(typeof(caretPosition.offset), "number"); 222 assert_equals(caretPosition.offsetNode, container); 223 assert_equals(caretPosition.offset, 1); 224 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the outer shadow host\'s parent when the point is in an inner shadow tree and no shadow tree is specified as an argument'); 225 226 test(() => { 227 container.setHTMLUnsafe(` 228 a<div id="outerHost"> 229 <template shadowrootmode=open> 230 <div id="innerHost"> 231 <template shadowrootmode=open> 232 <span>some text</span> 233 </template> 234 </div> 235 <div>world</div> 236 </template> 237 </div>b`); 238 const outerShadowRoot = outerHost.shadowRoot; 239 const innerShadowRoot = outerShadowRoot.getElementById('innerHost').shadowRoot; 240 const innerShadowRootSpanElement = innerShadowRoot.querySelector("span"); 241 const rect = innerShadowRootSpanElement.getBoundingClientRect(); 242 const characterWidth = rect.width / innerShadowRootSpanElement.textContent.length; 243 const characterIndex = 2 244 // Get x and y coordinate at `so|me text`. 245 const x = rect.left + characterWidth * characterIndex; 246 const y = rect.top + rect.height / 2; 247 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: [innerShadowRoot]}); 248 assert_true(caretPosition instanceof CaretPosition); 249 assert_true(caretPosition.offsetNode instanceof Text); 250 assert_equals(typeof(caretPosition.offset), "number"); 251 assert_equals(caretPosition.offsetNode, innerShadowRootSpanElement.firstChild); 252 assert_equals(caretPosition.offset, characterIndex); 253 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the inner shadow tree when the point is in an inner shadow tree and the inner shadow tree is specified as an argument'); 254 255 test(() => { 256 container.setHTMLUnsafe(` 257 a<div id="outerHost"> 258 <template shadowrootmode=open> 259 <div id="innerHost"> 260 <template shadowrootmode=open> 261 <span>some text</span> 262 </template> 263 </div> 264 <div>world</div> 265 </template> 266 </div>b`); 267 const outerShadowRoot = outerHost.shadowRoot; 268 const innerShadowRoot = outerShadowRoot.getElementById('innerHost').shadowRoot; 269 const innerShadowRootSpanElement = innerShadowRoot.querySelector("span"); 270 const rect = innerShadowRootSpanElement.getBoundingClientRect(); 271 const characterWidth = rect.width / innerShadowRootSpanElement.textContent.length; 272 const characterIndex = 2 273 // Get x and y coordinate at `so|me text`. 274 const x = rect.left + characterWidth * characterIndex; 275 const y = rect.top + rect.height / 2; 276 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: [outerShadowRoot]}); 277 assert_true(caretPosition instanceof CaretPosition); 278 assert_true(caretPosition.offsetNode instanceof Node); 279 assert_equals(typeof(caretPosition.offset), "number"); 280 assert_equals(caretPosition.offsetNode, outerShadowRoot); 281 assert_equals(caretPosition.offset, 1); 282 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the outer shadow tree when the point is in an inner shadow tree and the outer shadow tree is specified as an argument'); 283 284 test(() => { 285 container.setHTMLUnsafe(` 286 a<div id="outerHost"> 287 <template shadowrootmode=open> 288 <div id="innerHost"> 289 <template shadowrootmode=open> 290 <span>some text</span> 291 </template> 292 </div> 293 <div>world</div> 294 </template> 295 </div>b`); 296 297 const outerShadowRoot = outerHost.shadowRoot; 298 const innerShadowRoot = outerShadowRoot.getElementById('innerHost').shadowRoot; 299 const innerShadowRootSpanElement = innerShadowRoot.querySelector("span"); 300 const rect = innerShadowRootSpanElement.getBoundingClientRect(); 301 const characterWidth = rect.width / innerShadowRootSpanElement.textContent.length; 302 const characterIndex = 2 303 // Get x and y coordinate at `so|me text`. 304 const x = rect.left + characterWidth * characterIndex; 305 const y = rect.top + rect.height / 2; 306 const caretPosition = document.caretPositionFromPoint(x, y, {shadowRoots: [innerShadowRoot, outerShadowRoot]}); 307 assert_true(caretPosition instanceof CaretPosition); 308 assert_true(caretPosition.offsetNode instanceof Text); 309 assert_equals(typeof(caretPosition.offset), "number"); 310 assert_equals(caretPosition.offsetNode, innerShadowRootSpanElement.firstChild); 311 assert_equals(caretPosition.offset, characterIndex); 312 }, 'document.caretPositionFromPoint() should return a CaretPosition at the specified location pointing to the inner shadow tree when the point is in an inner shadow tree and the inner shadow tree and the outer shadow tree are specified as an argument'); 313 </script> 314 </body> 315 </html>