test_movement_by_words.html (29040B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test Word Movement (including nsTextFrame::PeekOffsetWord)</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <script src="/tests/SimpleTest/EventUtils.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 8 </head> 9 <body> 10 <p id="display"></p> 11 <div id="content" style="display: block"> 12 <div contentEditable id="editor"></div> 13 </div> 14 <p id="catch">Catch-all 15 <pre id="test"><script class="testbody" type="text/javascript"> 16 17 /** Tests for bugs 384147, 981281, 1066756, 1820290 */ 18 19 const kIsMac = navigator.platform.includes("Mac"); 20 21 SimpleTest.waitForExplicitFinish(); 22 23 SimpleTest.waitForFocus(async () => { 24 const editor = document.getElementById("editor"); 25 const waitForFocusEditor = new Promise(resolve => 26 editor.addEventListener("focus", resolve, {once: true}) 27 ); 28 editor.focus(); 29 // This seems to be necessary because the selection is not set up properly otherwise 30 await waitForFocusEditor; 31 32 await test1(); 33 await test2(); 34 await test3(); 35 await test4(); 36 37 SimpleTest.finish(); 38 }); 39 40 var eatSpace; 41 var stopAtPunctuation; 42 var sel = window.getSelection(); 43 var editor = document.getElementById("editor"); 44 45 function setPrefs(eat_space, stop_at_punctuation) { 46 eatSpace = eat_space; 47 stopAtPunctuation = stop_at_punctuation; 48 return SpecialPowers.pushPrefEnv({ 49 "set": [["layout.word_select.eat_space_to_next_word", eat_space], 50 ["layout.word_select.stop_at_punctuation", stop_at_punctuation], 51 ["intl.icu4x.segmenter.enabled", true]] 52 }); 53 } 54 55 function currentStateDescription() { 56 return `eatSpace=${eatSpace}, stopAtPunctuation=${stopAtPunctuation}, testing="${editor.outerHTML}"`; 57 } 58 59 function getNodeDescription(aNode) { 60 if (aNode === undefined) { 61 return "undefined"; 62 } 63 if (aNode === null) { 64 return "null"; 65 } 66 switch (aNode.nodeType) { 67 case Node.TEXT_NODE: 68 return `"${ 69 aNode.data.replace(/\n/g, "\\n") 70 }" in ${getNodeDescription(aNode.parentNode)}`; 71 case Node.ELEMENT_NODE: 72 return `<${aNode.tagName.toLowerCase()}${ 73 aNode.getAttribute("id") !== null 74 ? ` id="${aNode.getAttribute("id")}"` 75 : "" 76 }${ 77 aNode.getAttribute("dir") !== null 78 ? ` dir="${aNode.getAttribute("dir")}"` 79 : "" 80 }>`; 81 } 82 return aNode.nodeName; 83 } 84 85 function testRight(node, offset, knownFailure) { 86 if (!kIsMac) { 87 synthesizeKey("KEY_ArrowRight", { ctrlKey: true }); 88 } else { 89 // macOS does not have default shortcut key to move caret per word. 90 SpecialPowers.doCommand(window, "cmd_wordNext"); 91 } 92 (knownFailure ? todo_is : is)( 93 `{${getNodeDescription(sel.anchorNode)} - ${sel.anchorOffset}}`, 94 `{${getNodeDescription(node)} - ${offset}}`, 95 `testRight(${currentStateDescription()})` 96 ); 97 if (knownFailure) { 98 getSelection().collapse(node, offset); 99 } 100 } 101 102 function testLeft(node, offset, knownFailure) { 103 if (!kIsMac) { 104 synthesizeKey("KEY_ArrowLeft", { ctrlKey: true }); 105 } else { 106 // macOS does not have default shortcut key to move caret per word. 107 SpecialPowers.doCommand(window, "cmd_wordPrevious"); 108 } 109 (knownFailure ? todo_is : is)( 110 `{${getNodeDescription(sel.anchorNode)} - ${sel.anchorOffset}}`, 111 `{${getNodeDescription(node)} - ${offset}}`, 112 `testLeft(${currentStateDescription()})` 113 ); 114 if (knownFailure) { 115 getSelection().collapse(node, offset); 116 } 117 } 118 119 const afterEditorNode = document.getElementById("catch").firstChild; 120 121 const ChineseChars = "漢字"; 122 const HiraganaChars = "ひらがな"; 123 const KatakanaChars = "カタカナ"; 124 const JapaneseFullStop = "。"; 125 const JapaneseComma = "、"; 126 const ModifierColon = "꞉"; 127 const Symbol = "⛅"; // "sun behind cloud" (weather symbol) 128 const Emoji = "🐀"; // rat emoji 129 const DeseretChars = "𐑀𐑁"; 130 const ChineseCharsPlane2 = "𠀋𠀿"; 131 const ArabicOne = "\u0648\u0627\u062D\u062F"; 132 const ArabicTwo = "\u0627\u062B\u0646\u064A\u0646"; 133 const ArabicThree = "\u062B\u0644\u0627\u062B\u0629"; 134 135 async function test1() { 136 await setPrefs(false, true); 137 138 editor.innerHTML = "Hello Kitty"; 139 sel.collapse(editor.firstChild, 0); 140 testRight(editor.firstChild, 5); 141 testRight(editor.firstChild, 11); 142 testLeft(editor.firstChild, 6); 143 testLeft(editor.firstChild, 0); 144 145 editor.innerHTML = "<b>Hello</b> Kitty"; 146 sel.collapse(editor.firstChild.firstChild, 0); 147 testRight(editor.firstChild.nextSibling, 0); 148 testRight(editor.firstChild.nextSibling, 6); 149 testLeft(editor.firstChild.nextSibling, 1); 150 testLeft(editor.firstChild.firstChild, 0); 151 152 editor.innerHTML = "<b>Hello </b>Kitty"; 153 sel.collapse(editor.firstChild.firstChild, 0); 154 testRight(editor.firstChild.firstChild, 5); 155 testRight(editor.firstChild.nextSibling, 5); 156 testLeft(editor.firstChild.firstChild, 6); 157 testLeft(editor.firstChild.firstChild, 0); 158 159 editor.innerHTML = "<b>Log out</b> roc"; 160 sel.collapse(editor.firstChild.firstChild, 0); 161 testRight(editor.firstChild.firstChild, 3); 162 testRight(editor.firstChild.nextSibling, 0); 163 testRight(editor.firstChild.nextSibling, 5); 164 // In the next test, we expect to be at the end of the 165 // space that is not collapsed away 166 testLeft(editor.firstChild.nextSibling, 1); 167 testLeft(editor.firstChild.firstChild, 4); 168 testLeft(editor.firstChild.firstChild, 0); 169 170 editor.innerHTML = "http://www.mozilla.org"; 171 sel.collapse(editor.firstChild, 0); 172 testRight(editor.firstChild, 7); 173 testRight(editor.firstChild, 11); 174 testRight(editor.firstChild, 19); 175 testLeft(editor.firstChild, 11); 176 testLeft(editor.firstChild, 7); 177 testLeft(editor.firstChild, 0); 178 179 editor.innerHTML = "Set .rc to <b>'</b>quiz'"; 180 sel.collapse(editor.firstChild, 0); 181 testRight(editor.firstChild, 3); 182 testRight(editor.firstChild, 7); 183 testRight(editor.firstChild, 10); 184 testRight(editor.firstChild.nextSibling.nextSibling, 5); 185 testLeft(editor.firstChild.nextSibling.firstChild, 1); 186 testLeft(editor.firstChild, 8); 187 testLeft(editor.firstChild, 5); 188 testLeft(editor.firstChild, 0); 189 190 editor.innerHTML = "layout.word_select.stop_at_punctuation"; 191 sel.collapse(editor.firstChild, 0); 192 testRight(editor.firstChild, 7); 193 testRight(editor.firstChild, 19); 194 testRight(editor.firstChild, 38); 195 testLeft(editor.firstChild, 19); 196 testLeft(editor.firstChild, 7); 197 testLeft(editor.firstChild, 0); 198 199 editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars; 200 sel.collapse(editor.firstChild, 0); 201 testRight(editor.firstChild, 2); 202 testRight(editor.firstChild, 5); 203 testRight(editor.firstChild, 6); 204 testRight(editor.firstChild, 8); 205 testLeft(editor.firstChild, 6); 206 testLeft(editor.firstChild, 5); 207 testLeft(editor.firstChild, 2); 208 testLeft(editor.firstChild, 0); 209 210 editor.innerHTML = ChineseChars + KatakanaChars + ChineseChars; 211 sel.collapse(editor.firstChild, 0); 212 testRight(editor.firstChild, 2); 213 testRight(editor.firstChild, 6); 214 testRight(editor.firstChild, 8); 215 testLeft(editor.firstChild, 6); 216 testLeft(editor.firstChild, 2); 217 testLeft(editor.firstChild, 0); 218 219 editor.innerHTML = KatakanaChars + HiraganaChars + KatakanaChars; 220 sel.collapse(editor.firstChild, 0); 221 testRight(editor.firstChild, 4); 222 testRight(editor.firstChild, 7); 223 testRight(editor.firstChild, 8); 224 testRight(editor.firstChild, 12); 225 testLeft(editor.firstChild, 8); 226 testLeft(editor.firstChild, 7); 227 testLeft(editor.firstChild, 4); 228 testLeft(editor.firstChild, 0); 229 230 editor.innerHTML = HiraganaChars + JapaneseComma + HiraganaChars + JapaneseFullStop + HiraganaChars; 231 sel.collapse(editor.firstChild, 0); 232 testRight(editor.firstChild, 3); 233 testRight(editor.firstChild, 5); 234 testRight(editor.firstChild, 8); 235 testRight(editor.firstChild, 10); 236 testRight(editor.firstChild, 13); 237 testRight(editor.firstChild, 14); 238 testLeft(editor.firstChild, 13); 239 testLeft(editor.firstChild, 10); 240 testLeft(editor.firstChild, 8); 241 testLeft(editor.firstChild, 5); 242 testLeft(editor.firstChild, 3); 243 testLeft(editor.firstChild, 0); 244 245 editor.innerHTML = KatakanaChars + JapaneseComma + KatakanaChars + JapaneseFullStop + KatakanaChars; 246 sel.collapse(editor.firstChild, 0); 247 testRight(editor.firstChild, 5); 248 testRight(editor.firstChild, 10); 249 testRight(editor.firstChild, 14); 250 testLeft(editor.firstChild, 10); 251 testLeft(editor.firstChild, 5); 252 testLeft(editor.firstChild, 0); 253 254 editor.innerHTML = ChineseChars + JapaneseComma + ChineseChars + JapaneseFullStop + ChineseChars; 255 sel.collapse(editor.firstChild, 0); 256 testRight(editor.firstChild, 3); 257 testRight(editor.firstChild, 6); 258 testRight(editor.firstChild, 8); 259 testLeft(editor.firstChild, 6); 260 testLeft(editor.firstChild, 3); 261 testLeft(editor.firstChild, 0); 262 263 // test for bug 1066756 264 editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld"; 265 sel.collapse(editor.firstChild, 0); 266 testRight(editor.firstChild, 6); 267 testRight(editor.firstChild, 13); 268 testLeft(editor.firstChild, 7); 269 testLeft(editor.firstChild, 0); 270 271 // test word selection in Deseret (alphabet in Plane 1) 272 editor.innerHTML = DeseretChars + " " + DeseretChars; 273 sel.collapse(editor.firstChild, 0); 274 testRight(editor.firstChild, 4); 275 testRight(editor.firstChild, 9); 276 testLeft(editor.firstChild, 5); 277 testLeft(editor.firstChild, 0); 278 279 // Latin words separated by a pictographic symbol 280 editor.innerHTML = "hello" + Symbol + "world"; 281 sel.collapse(editor.firstChild, 0); 282 testRight(editor.firstChild, 6); 283 testRight(editor.firstChild, 11); 284 testLeft(editor.firstChild, 6); 285 testLeft(editor.firstChild, 0); 286 287 // Latin words separated by an emoji symbol 288 editor.innerHTML = "hello" + Emoji + "world"; 289 sel.collapse(editor.firstChild, 0); 290 testRight(editor.firstChild, 5); 291 testRight(editor.firstChild, 7); 292 testRight(editor.firstChild, 12); 293 testLeft(editor.firstChild, 7); 294 testLeft(editor.firstChild, 5); 295 testLeft(editor.firstChild, 0); 296 297 // Emoji and Chinese 298 editor.innerHTML = Emoji + ChineseChars; 299 sel.collapse(editor.firstChild, 0); 300 testRight(editor.firstChild, 2); 301 testRight(editor.firstChild, 4); 302 testLeft(editor.firstChild, 2); 303 testLeft(editor.firstChild, 0); 304 305 // test that word selection stops at Latin/Chinese boundary 306 editor.innerHTML = "hello" + ChineseChars + "world"; 307 sel.collapse(editor.firstChild, 0); 308 testRight(editor.firstChild, 5); 309 testRight(editor.firstChild, 7); 310 testRight(editor.firstChild, 12); 311 testLeft(editor.firstChild, 7); 312 testLeft(editor.firstChild, 5); 313 testLeft(editor.firstChild, 0); 314 315 // similar, but with Deseret (alphabet in Plane 1) in place of Latin 316 editor.innerHTML = DeseretChars + ChineseChars + DeseretChars; 317 sel.collapse(editor.firstChild, 0); 318 testRight(editor.firstChild, 4); 319 testRight(editor.firstChild, 6); 320 testRight(editor.firstChild, 10); 321 testLeft(editor.firstChild, 6); 322 testLeft(editor.firstChild, 4); 323 testLeft(editor.firstChild, 0); 324 325 // with Plane 2 Chinese characters 326 editor.innerHTML = "hello" + ChineseCharsPlane2 + "world"; 327 sel.collapse(editor.firstChild, 0); 328 testRight(editor.firstChild, 5); 329 testRight(editor.firstChild, 9); 330 testRight(editor.firstChild, 14); 331 testLeft(editor.firstChild, 9); 332 testLeft(editor.firstChild, 5); 333 testLeft(editor.firstChild, 0); 334 335 // Plane 1 Deseret and Plane 2 Chinese characters 336 editor.innerHTML = DeseretChars + ChineseCharsPlane2 + DeseretChars; 337 sel.collapse(editor.firstChild, 0); 338 testRight(editor.firstChild, 4); 339 testRight(editor.firstChild, 8); 340 testRight(editor.firstChild, 12); 341 testLeft(editor.firstChild, 8); 342 testLeft(editor.firstChild, 4); 343 testLeft(editor.firstChild, 0); 344 345 // Out-of-flow frames around line edges should be treated as independent lines. 346 for (const floatValue of ["left", "right"]) { 347 editor.innerHTML = `<b>One</b> <i>Two</i><span style=float:${floatValue}>Three</span>`; 348 sel.collapse(editor.querySelector("i").firstChild, 0); 349 testRight(editor.querySelector("i").firstChild, "Two".length); 350 testRight(editor.querySelector("span").firstChild, "Three".length); 351 testLeft(editor.querySelector("span").firstChild, 0); 352 testLeft(editor.querySelector("i").previousSibling, " ".length); // FIXME: Should stop at start of "Two" 353 editor.innerHTML = `<span style=float:${floatValue}>One</span><b>Two</b> <i>Three</i>`; 354 sel.collapse(editor.querySelector("b").firstChild, "Two".length); 355 testLeft(editor.querySelector("b").firstChild, 0); 356 testLeft(editor.querySelector("span").firstChild, 0); 357 testRight(editor.querySelector("span").firstChild, "One".length); 358 testRight(editor.querySelector("b").nextSibling, 0); // FIXME: Should stop at end of "Two" 359 } 360 361 // And also visually connected words which are split by an out-of-flow content 362 // shouldn't be treated as a word. 363 editor.innerHTML = 'One<span style=float:right>Two</span>Three'; 364 sel.collapse(editor.firstChild, 0); 365 testRight(editor.firstChild, "One".length); 366 testRight(editor.querySelector("span").firstChild, "Two".length); 367 testRight(editor.lastChild, "Three".length); 368 testLeft(editor.lastChild, 0); 369 testLeft(editor.querySelector("span").firstChild, 0); 370 testLeft(editor.firstChild, 0); 371 372 // Simple RTL cases of above. 373 editor.setAttribute("dir", "rtl"); 374 for (const floatValue of ["left", "right"]) { 375 editor.innerHTML = `<b>${ArabicOne}</b> <i>${ArabicTwo}</i><span style=float:${floatValue}>${ArabicThree}</span>`; 376 sel.collapse(editor.querySelector("i").firstChild, 0); 377 testLeft(editor.querySelector("i").firstChild, ArabicTwo.length); 378 testLeft(editor.querySelector("span").firstChild, ArabicThree.length); 379 testRight(editor.querySelector("span").firstChild, 0); 380 testRight(editor.querySelector("i").previousSibling, " ".length); // FIXME: Should stop at start of ArabicTwo. 381 editor.innerHTML = `<span style=float:${floatValue}>${ArabicOne}</span><b>${ArabicTwo}</b> <i>${ArabicThree}</i>`; 382 sel.collapse(editor.querySelector("b").firstChild, ArabicTwo.length); 383 testRight(editor.querySelector("b").firstChild, 0); 384 testRight(editor.querySelector("span").firstChild, 0); 385 testLeft(editor.querySelector("span").firstChild, ArabicOne.length); 386 testLeft(editor.querySelector("b").nextSibling, 0); // FIXME: Should stop at end of ArabicTwo. 387 } 388 389 // And also the bidi cases which LRT frames are at line edge if ignoring the 390 // out-of-flow things. 391 // XXX Although these tests are behave as expected if I test them manually. 392 // I don't know the reason why the behavior changes in this test file. 393 for (const floatValue of ["left", "right"]) { 394 editor.innerHTML = `<div><b>${ArabicOne}</b> <i dir="ltr">Two</i><span style=float:${floatValue}>${ArabicThree}</span></div>`; 395 sel.collapse(editor.querySelector("i").firstChild, "Two".length); 396 testLeft(editor.querySelector("i").firstChild, 0, true); 397 testLeft(editor.querySelector("span").firstChild, 0, true); 398 testLeft(editor.querySelector("span").firstChild, ArabicThree.length); 399 testRight(editor.querySelector("span").firstChild, 0); 400 testRight(editor.querySelector("i").previousSibling, " ".length); // FIXME: Should stop at end of "Two" 401 editor.innerHTML = `<div><span style=float:${floatValue}>${ArabicOne}</span><b dir="ltr">Two</b> <i>${ArabicThree}</i></div>`; 402 sel.collapse(editor.querySelector("b").firstChild, 0); 403 testRight(editor.querySelector("b").firstChild, "Two".length, true); 404 testRight(editor.querySelector("span").firstChild, ArabicOne.length, true); 405 testRight(editor.querySelector("span").firstChild, 0); 406 testLeft(editor.querySelector("span").firstChild, ArabicOne.length); 407 testLeft(editor.querySelector("b").nextSibling, 0); // FIXME: Should stop at start of "Two". 408 } 409 410 editor.removeAttribute("dir"); 411 } 412 413 async function test2() { 414 // test basic word movement with eat_space_next_to_word true. 415 await setPrefs(true, true); 416 417 editor.innerHTML = "Hello Kitty"; 418 sel.collapse(editor.firstChild, 0); 419 testRight(editor.firstChild, 6); 420 testRight(editor.firstChild, 11); 421 testLeft(editor.firstChild, 6); 422 testLeft(editor.firstChild, 0); 423 424 editor.innerHTML = "<b>Hello</b> Kitty"; 425 sel.collapse(editor.firstChild.firstChild, 0); 426 testRight(editor.firstChild.nextSibling, 1); 427 testRight(editor.firstChild.nextSibling, 6); 428 testLeft(editor.firstChild.nextSibling, 1); 429 testLeft(editor.firstChild.firstChild, 0); 430 431 editor.innerHTML = "<b>Hello </b>Kitty"; 432 sel.collapse(editor.firstChild.firstChild, 0); 433 testRight(editor.firstChild.nextSibling, 0); 434 testRight(editor.firstChild.nextSibling, 5); 435 testLeft(editor.firstChild.firstChild, 6); 436 testLeft(editor.firstChild.firstChild, 0); 437 438 editor.innerHTML = "<b>Log out</b> roc"; 439 sel.collapse(editor.firstChild.firstChild, 0); 440 testRight(editor.firstChild.firstChild, 4); 441 testRight(editor.firstChild.nextSibling, 2); 442 testRight(editor.firstChild.nextSibling, 5); 443 testLeft(editor.firstChild.nextSibling, 1); 444 testLeft(editor.firstChild.firstChild, 4); 445 testLeft(editor.firstChild.firstChild, 0); 446 447 editor.innerHTML = "http://www.mozilla.org"; 448 sel.collapse(editor.firstChild, 0); 449 testRight(editor.firstChild, 7); 450 testRight(editor.firstChild, 11); 451 testRight(editor.firstChild, 19); 452 testLeft(editor.firstChild, 11); 453 testLeft(editor.firstChild, 7); 454 testLeft(editor.firstChild, 0); 455 456 editor.innerHTML = "Set .rc to <b>'</b>quiz'"; 457 sel.collapse(editor.firstChild, 0); 458 testRight(editor.firstChild, 4); 459 testRight(editor.firstChild, 8); 460 testRight(editor.firstChild.nextSibling.firstChild, 0); 461 testRight(editor.firstChild.nextSibling.nextSibling, 5); 462 testLeft(editor.firstChild.nextSibling.firstChild, 1); 463 testLeft(editor.firstChild, 8); 464 testLeft(editor.firstChild, 5); 465 testLeft(editor.firstChild, 0); 466 467 editor.innerHTML = "layout.word_select.stop_at_punctuation"; 468 sel.collapse(editor.firstChild, 0); 469 testRight(editor.firstChild, 7); 470 testRight(editor.firstChild, 19); 471 testRight(editor.firstChild, 38); 472 testLeft(editor.firstChild, 19); 473 testLeft(editor.firstChild, 7); 474 testLeft(editor.firstChild, 0); 475 476 editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars; 477 sel.collapse(editor.firstChild, 0); 478 testRight(editor.firstChild, 2); 479 testRight(editor.firstChild, 5); 480 testRight(editor.firstChild, 6); 481 testRight(editor.firstChild, 8); 482 testLeft(editor.firstChild, 6); 483 testLeft(editor.firstChild, 5); 484 testLeft(editor.firstChild, 2); 485 testLeft(editor.firstChild, 0); 486 487 editor.innerHTML = ChineseChars + KatakanaChars + ChineseChars; 488 sel.collapse(editor.firstChild, 0); 489 testRight(editor.firstChild, 2); 490 testRight(editor.firstChild, 6); 491 testRight(editor.firstChild, 8); 492 testLeft(editor.firstChild, 6); 493 testLeft(editor.firstChild, 2); 494 testLeft(editor.firstChild, 0); 495 496 editor.innerHTML = KatakanaChars + HiraganaChars + KatakanaChars; 497 sel.collapse(editor.firstChild, 0); 498 testRight(editor.firstChild, 4); 499 testRight(editor.firstChild, 7); 500 testRight(editor.firstChild, 8); 501 testRight(editor.firstChild, 12); 502 testLeft(editor.firstChild, 8); 503 testLeft(editor.firstChild, 7); 504 testLeft(editor.firstChild, 4); 505 testLeft(editor.firstChild, 0); 506 507 editor.innerHTML = HiraganaChars + JapaneseComma + HiraganaChars + JapaneseFullStop + HiraganaChars; 508 sel.collapse(editor.firstChild, 0); 509 testRight(editor.firstChild, 3); 510 testRight(editor.firstChild, 5); 511 testRight(editor.firstChild, 8); 512 testRight(editor.firstChild, 10); 513 testRight(editor.firstChild, 13); 514 testRight(editor.firstChild, 14); 515 testLeft(editor.firstChild, 13); 516 testLeft(editor.firstChild, 10); 517 testLeft(editor.firstChild, 8); 518 testLeft(editor.firstChild, 5); 519 testLeft(editor.firstChild, 3); 520 testLeft(editor.firstChild, 0); 521 522 editor.innerHTML = KatakanaChars + JapaneseComma + KatakanaChars + JapaneseFullStop + KatakanaChars; 523 sel.collapse(editor.firstChild, 0); 524 testRight(editor.firstChild, 5); 525 testRight(editor.firstChild, 10); 526 testRight(editor.firstChild, 14); 527 testLeft(editor.firstChild, 10); 528 testLeft(editor.firstChild, 5); 529 testLeft(editor.firstChild, 0); 530 531 editor.innerHTML = ChineseChars + JapaneseComma + ChineseChars + JapaneseFullStop + ChineseChars; 532 sel.collapse(editor.firstChild, 0); 533 testRight(editor.firstChild, 3); 534 testRight(editor.firstChild, 6); 535 testRight(editor.firstChild, 8); 536 testLeft(editor.firstChild, 6); 537 testLeft(editor.firstChild, 3); 538 testLeft(editor.firstChild, 0); 539 540 editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld"; 541 sel.collapse(editor.firstChild, 0); 542 testRight(editor.firstChild, 7); 543 testRight(editor.firstChild, 13); 544 testLeft(editor.firstChild, 7); 545 testLeft(editor.firstChild, 0); 546 } 547 548 async function test3() { 549 // Test basic word movement with stop_at_punctuation false (bug 981281). 550 await setPrefs(false, false); 551 552 editor.innerHTML = "Hello Kitty"; 553 sel.collapse(editor.firstChild, 0); 554 testRight(editor.firstChild, 5); 555 testRight(editor.firstChild, 11); 556 testLeft(editor.firstChild, 6); 557 testLeft(editor.firstChild, 0); 558 559 editor.innerHTML = "<b>Hello</b> Kitty"; 560 sel.collapse(editor.firstChild.firstChild, 0); 561 testRight(editor.firstChild.nextSibling, 0); 562 testRight(editor.firstChild.nextSibling, 6); 563 testLeft(editor.firstChild.nextSibling, 1); 564 testLeft(editor.firstChild.firstChild, 0); 565 566 editor.innerHTML = "<b>Hello </b>Kitty"; 567 sel.collapse(editor.firstChild.firstChild, 0); 568 testRight(editor.firstChild.firstChild, 5); 569 testRight(editor.firstChild.nextSibling, 5); 570 testLeft(editor.firstChild.firstChild, 6); 571 testLeft(editor.firstChild.firstChild, 0); 572 573 editor.innerHTML = "<b>Log out</b> roc"; 574 sel.collapse(editor.firstChild.firstChild, 0); 575 testRight(editor.firstChild.firstChild, 3); 576 testRight(editor.firstChild.nextSibling, 0); 577 testRight(editor.firstChild.nextSibling, 5); 578 testLeft(editor.firstChild.nextSibling, 1); 579 testLeft(editor.firstChild.firstChild, 4); 580 testLeft(editor.firstChild.firstChild, 0); 581 582 editor.innerHTML = "http://www.mozilla.org"; 583 sel.collapse(editor.firstChild, 0); 584 testRight(editor.firstChild, 22); 585 testLeft(editor.firstChild, 0); 586 587 editor.innerHTML = "Set .rc to <b>'</b>quiz'"; 588 sel.collapse(editor.firstChild, 0); 589 testRight(editor.firstChild, 3); 590 testRight(editor.firstChild, 7); 591 testRight(editor.firstChild, 10); 592 testRight(editor.firstChild.nextSibling.nextSibling, 5); 593 testLeft(editor.firstChild, 11); 594 testLeft(editor.firstChild, 8); 595 testLeft(editor.firstChild, 4); 596 testLeft(editor.firstChild, 0); 597 598 editor.innerHTML = "layout.word_select.stop_at_punctuation"; 599 sel.collapse(editor.firstChild, 0); 600 testRight(editor.firstChild, 38); 601 testLeft(editor.firstChild, 0); 602 603 editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars; 604 sel.collapse(editor.firstChild, 0); 605 testRight(editor.firstChild, 2); 606 testRight(editor.firstChild, 5); 607 testRight(editor.firstChild, 6); 608 testRight(editor.firstChild, 8); 609 testLeft(editor.firstChild, 6); 610 testLeft(editor.firstChild, 5); 611 testLeft(editor.firstChild, 2); 612 testLeft(editor.firstChild, 0); 613 614 editor.innerHTML = ChineseChars + KatakanaChars + ChineseChars; 615 sel.collapse(editor.firstChild, 0); 616 testRight(editor.firstChild, 2); 617 testRight(editor.firstChild, 6); 618 testRight(editor.firstChild, 8); 619 testLeft(editor.firstChild, 6); 620 testLeft(editor.firstChild, 2); 621 testLeft(editor.firstChild, 0); 622 623 editor.innerHTML = KatakanaChars + HiraganaChars + KatakanaChars; 624 sel.collapse(editor.firstChild, 0); 625 testRight(editor.firstChild, 4); 626 testRight(editor.firstChild, 7); 627 testRight(editor.firstChild, 8); 628 testRight(editor.firstChild, 12); 629 testLeft(editor.firstChild, 8); 630 testLeft(editor.firstChild, 7); 631 testLeft(editor.firstChild, 4); 632 testLeft(editor.firstChild, 0); 633 634 editor.innerHTML = HiraganaChars + JapaneseComma + HiraganaChars + JapaneseFullStop + HiraganaChars; 635 sel.collapse(editor.firstChild, 0); 636 testRight(editor.firstChild, 3); 637 testRight(editor.firstChild, 8); 638 testRight(editor.firstChild, 13); 639 testRight(editor.firstChild, 14); 640 testLeft(editor.firstChild, 13); 641 testLeft(editor.firstChild, 8); 642 testLeft(editor.firstChild, 3); 643 testLeft(editor.firstChild, 0); 644 645 editor.innerHTML = KatakanaChars + JapaneseComma + KatakanaChars + JapaneseFullStop + KatakanaChars; 646 sel.collapse(editor.firstChild, 0); 647 testRight(editor.firstChild, 14); 648 testLeft(editor.firstChild, 0); 649 650 editor.innerHTML = ChineseChars + JapaneseComma + ChineseChars + JapaneseFullStop + ChineseChars; 651 sel.collapse(editor.firstChild, 0); 652 testRight(editor.firstChild, 8); 653 testLeft(editor.firstChild, 0); 654 655 editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld"; 656 sel.collapse(editor.firstChild, 0); 657 testRight(editor.firstChild, 6); 658 testRight(editor.firstChild, 13); 659 testLeft(editor.firstChild, 7); 660 testLeft(editor.firstChild, 0); 661 } 662 663 async function test4() { 664 // And again with eat_space_next_to_word true. 665 await setPrefs(true, false); 666 667 editor.innerHTML = "Hello Kitty"; 668 sel.collapse(editor.firstChild, 0); 669 testRight(editor.firstChild, 6); 670 testRight(editor.firstChild, 11); 671 testLeft(editor.firstChild, 6); 672 testLeft(editor.firstChild, 0); 673 674 editor.innerHTML = "<b>Hello</b> Kitty"; 675 sel.collapse(editor.firstChild.firstChild, 0); 676 testRight(editor.firstChild.nextSibling, 1); 677 testRight(editor.firstChild.nextSibling, 6); 678 testLeft(editor.firstChild.nextSibling, 1); 679 testLeft(editor.firstChild.firstChild, 0); 680 681 editor.innerHTML = "<b>Hello </b>Kitty"; 682 sel.collapse(editor.firstChild.firstChild, 0); 683 testRight(editor.firstChild.nextSibling, 0); 684 testRight(editor.firstChild.nextSibling, 5); 685 testLeft(editor.firstChild.firstChild, 6); 686 testLeft(editor.firstChild.firstChild, 0); 687 688 editor.innerHTML = "<b>Log out</b> roc"; 689 sel.collapse(editor.firstChild.firstChild, 0); 690 testRight(editor.firstChild.firstChild, 4); 691 testRight(editor.firstChild.nextSibling, 2); 692 testRight(editor.firstChild.nextSibling, 5); 693 testLeft(editor.firstChild.nextSibling, 1); 694 testLeft(editor.firstChild.firstChild, 4); 695 testLeft(editor.firstChild.firstChild, 0); 696 697 editor.innerHTML = "http://www.mozilla.org"; 698 sel.collapse(editor.firstChild, 0); 699 testRight(editor.firstChild, 22); 700 testLeft(editor.firstChild, 0); 701 702 editor.innerHTML = "Set .rc to <b>'</b>quiz'"; 703 sel.collapse(editor.firstChild, 0); 704 testRight(editor.firstChild, 4); 705 testRight(editor.firstChild, 8); 706 testRight(editor.firstChild.nextSibling.firstChild, 0); 707 testRight(editor.firstChild.nextSibling.nextSibling, 5); 708 testLeft(editor.firstChild, 11); 709 testLeft(editor.firstChild, 8); 710 testLeft(editor.firstChild, 4); 711 testLeft(editor.firstChild, 0); 712 713 editor.innerHTML = "layout.word_select.stop_at_punctuation"; 714 sel.collapse(editor.firstChild, 0); 715 testRight(editor.firstChild, 38); 716 testLeft(editor.firstChild, 0); 717 718 editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars; 719 sel.collapse(editor.firstChild, 0); 720 testRight(editor.firstChild, 2); 721 testRight(editor.firstChild, 5); 722 testRight(editor.firstChild, 6); 723 testRight(editor.firstChild, 8); 724 testLeft(editor.firstChild, 6); 725 testLeft(editor.firstChild, 5); 726 testLeft(editor.firstChild, 2); 727 testLeft(editor.firstChild, 0); 728 729 editor.innerHTML = ChineseChars + KatakanaChars + ChineseChars; 730 sel.collapse(editor.firstChild, 0); 731 testRight(editor.firstChild, 2); 732 testRight(editor.firstChild, 6); 733 testRight(editor.firstChild, 8); 734 testLeft(editor.firstChild, 6); 735 testLeft(editor.firstChild, 2); 736 testLeft(editor.firstChild, 0); 737 738 editor.innerHTML = KatakanaChars + HiraganaChars + KatakanaChars; 739 sel.collapse(editor.firstChild, 0); 740 testRight(editor.firstChild, 4); 741 testRight(editor.firstChild, 7); 742 testRight(editor.firstChild, 8); 743 testRight(editor.firstChild, 12); 744 testLeft(editor.firstChild, 8); 745 testLeft(editor.firstChild, 7); 746 testLeft(editor.firstChild, 4); 747 testLeft(editor.firstChild, 0); 748 749 editor.innerHTML = HiraganaChars + JapaneseComma + HiraganaChars + JapaneseFullStop + HiraganaChars; 750 sel.collapse(editor.firstChild, 0); 751 testRight(editor.firstChild, 3); 752 testRight(editor.firstChild, 8); 753 testRight(editor.firstChild, 13); 754 testRight(editor.firstChild, 14); 755 testLeft(editor.firstChild, 13); 756 testLeft(editor.firstChild, 8); 757 testLeft(editor.firstChild, 3); 758 testLeft(editor.firstChild, 0); 759 760 editor.innerHTML = KatakanaChars + JapaneseComma + KatakanaChars + JapaneseFullStop + KatakanaChars; 761 sel.collapse(editor.firstChild, 0); 762 testRight(editor.firstChild, 14); 763 testLeft(editor.firstChild, 0); 764 765 editor.innerHTML = ChineseChars + JapaneseComma + ChineseChars + JapaneseFullStop + ChineseChars; 766 sel.collapse(editor.firstChild, 0); 767 testRight(editor.firstChild, 8); 768 testLeft(editor.firstChild, 0); 769 770 editor.innerHTML = "hello" + ModifierColon + " wo" + ModifierColon + "rld"; 771 sel.collapse(editor.firstChild, 0); 772 testRight(editor.firstChild, 7); 773 testRight(editor.firstChild, 13); 774 testLeft(editor.firstChild, 7); 775 testLeft(editor.firstChild, 0); 776 } 777 778 779 </script></pre> 780 </body> 781 </html>