2011-03-30 Xiaomei Ji <xji@chromium.org>
[WebKit-https.git] / LayoutTests / editing / selection / move-by-word-visually.html
1 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5 <style>
6 div.test {
7     -webkit-user-modify: read-write;
8     padding: 4px;
9     border: 1px dashed lightblue;
10     margin: 4px 4px 4px 24px;
11     outline: none;
12     font-family: Lucida Grande;
13     counter-increment: test-number;
14 }
15 div.test:before { content: counter(test-number); position: absolute; left: 8px; font-size: x-small; text-align: right; width: 20px; }
16 div.test span { background-color: #def; }
17 div.test img { width: 1em; height: 1em; background-color: lightgreen; }
18 div.test img + img { background-color: lightblue; }
19 div.test div { border: 1px dashed pink; padding: 3px; height: 2em; }
20 test_move_by_word {display: none;}
21 </style>
22 <script>
23 var messages = [];
24
25 function log(message)
26 {
27     messages.push(message);
28 }
29
30 function flushLog()
31 {
32     document.getElementById("console").appendChild(document.createTextNode(messages.join("")));
33 }
34
35 function caretCoordinates()
36 {
37     if (!window.textInputController)
38         return { x: 0, y :0 };
39     var caretRect = textInputController.firstRectForCharacterRange(textInputController.selectedRange()[0], 0);
40     return { x: caretRect[0], y: caretRect[1] };
41 }
42
43
44 function fold(string)
45 {
46     var result = "";
47     for (var i = 0; i < string.length; ++i) {
48         var char = string.charCodeAt(i);
49         if (char >= 0x05d0)
50             char -= 0x058f;
51         else if (char == 10) {
52             result += "\\n";
53             continue;
54         }
55         result += String.fromCharCode(char);
56     }
57     return result;
58 }
59
60 function logPositions(positions)
61 {
62     for (var i = 0; i < positions.length; ++i) {
63         if (i) {
64             if (positions[i].node != positions[i - 1].node)
65                 log("]");
66             log(", ");
67         }
68         if (!i || positions[i].node != positions[i - 1].node)
69             log((positions[i].node instanceof Text ? '"' + fold(positions[i].node.data) + '"' : "<" + positions[i].node.tagName + ">") + "[");
70         log(positions[i].offset);
71     }
72     log("]");
73 }
74
75 var wordBreaks;
76
77 function validateData(positions)
78 {
79     for (var i = 0; i < wordBreaks.length - 1; ++i) {
80         if (positions[i].offset != wordBreaks[i + 1]) {
81             break;
82         }
83     }
84     if (i != wordBreaks.length - 1 && positions[i] != wordBreaks[i]) {
85         log("    FAIL expected: [");
86         for (var i = 1; i < wordBreaks.length; ++i) {
87             log(wordBreaks[i] + ", ");
88         }
89         log(wordBreaks[wordBreaks.length - 1] + "]");
90     }
91 }
92
93 function collectWordBreaks(test, searchDirection)
94 {
95     if (searchDirection == "right") {
96         if (test.getAttribute("dir") == 'ltr') 
97             wordBreaks = test.title.split("|")[0].split(" ");
98         else 
99             wordBreaks = test.title.split("|")[1].split(" ");
100     } else {
101         if (test.getAttribute("dir") == 'ltr') 
102             wordBreaks = test.title.split("|")[1].split(" ");
103         else 
104             wordBreaks = test.title.split("|")[0].split(" ");
105     }
106 }
107
108 function moveByWord(sel, test, searchDirection, dir)
109 {
110     log("Move " + searchDirection + " by one word\n");
111     var prevOffset = sel.anchorOffset;
112     var node = sel.anchorNode;
113     collectWordBreaks(test, searchDirection);
114     sel.setPosition(node, wordBreaks[0]);
115     var positions = [];
116     for (var index = 1; index < wordBreaks.length; ++index) {
117         sel.modify("move", searchDirection, "-webkit-visual-word");
118         positions.push({ node: sel.anchorNode, offset: sel.anchorOffset, point: caretCoordinates() });
119         sel.setPosition(node, wordBreaks[index]);
120     }
121     sel.modify("move", searchDirection, "-webkit-visual-word");
122     positions.push({ node: sel.anchorNode, offset: sel.anchorOffset, point: caretCoordinates() });
123     logPositions(positions);
124     validateData(positions);
125     log("\n");
126 }
127
128 function moveByWordForEveryPosition(sel, test, dir)
129 {
130     // Check ctrl-right-arrow works for every position.
131     sel.setPosition(test, 0);
132     var direction = "right";
133     if (dir == "rtl")
134         direction = "left";    
135     moveByWord(sel, test, direction, dir);    
136     // Check ctrl-left-arrow works for every position.
137     if (dir == "ltr")
138         direction = "left";
139     else
140         direction = "right";    
141     moveByWord(sel, test, direction, dir);    
142 }
143
144 function runMoveLeftRight(tests, unit)
145 {
146     var sel = getSelection();
147     for (var i = 0; i < tests.length; ++i) {
148         var positionsMovingRight;
149         var positionsMovingLeft;
150
151         if (tests[i].getAttribute("dir") == 'ltr')
152         {
153             log("Test " + (i + 1) + ", LTR:\n");
154             moveByWordForEveryPosition(sel, tests[i], "ltr");
155         } else {
156             log("Test " + (i + 1) + ", RTL:\n");
157             moveByWordForEveryPosition(sel, tests[i], "rtl");
158         }
159
160     }
161     document.getElementById("testMoveByWord").style.display = "none";
162 }
163
164 function runTest() {
165     log("\n======== Move By Word ====\n");
166     var tests = document.getElementsByClassName("test_move_by_word");
167     runMoveLeftRight(tests, "word");
168 }
169
170 onload = function() {
171     try {
172         runTest();
173     } finally {
174         flushLog();
175     }
176 };
177
178 if (window.layoutTestController)
179     layoutTestController.dumpAsText();
180 </script>
181 </head>
182 <body>
183 <div id="testMoveByWord">
184 <!-- The numbers put in title are starting word boundaries.
185 The numbers printed out in the output are ending word boundaries. -->
186 <div dir=ltr class="test_move_by_word" title="0 4 8 12 16 19|19 16 12 8 4 0" contenteditable>abc def hij opq rst</div>
187 <div dir=rtl class="test_move_by_word" title="0 15 11 7 3 19|19 3 7 11 15 0" contenteditable>abc def hij opq rst</div>
188 <div dir=ltr class="test_move_by_word" title="0 15 11 7 3 19|19 3 7 11 15 0" contenteditable>ששש נננ בבב גגג קקק</div>
189 <div dir=rtl class="test_move_by_word" title="0 4 8 12 16 19|19 16 12 8 4 0" contenteditable>ששש נננ בבב גגג קקק</div>
190 <div dir=ltr class="test_move_by_word" title="0 4 8 11 16 20 23|23 20 16 11 8 4 0" contenteditable>abc def שנב סטז uvw xyz</div>
191 <div dir=rtl class="test_move_by_word" title="0 3 8 12 16 19 23|23 19 16 12 8 3 0" contenteditable>abc def שנב סטז uvw xyz</div>
192 <div dir=ltr class="test_move_by_word" title="0 4 8 11|11 8 4 0" contenteditable>שנב abc סטז</div>
193 <div dir=rtl class="test_move_by_word" title="0 4 8 11|11 8 4 0" contenteditable>שנב abc סטז</div>
194 </div>
195
196 <pre id="console"></pre>
197 </body>
198 </html>