3 document.getElementById("console").appendChild(document.createTextNode(message));
6 function getSerializedSelection()
9 node: getSelection().extentNode,
10 begin: getSelection().baseOffset,
11 end: getSelection().extentOffset
15 function extendSelectionWithinBlock(direction, granularity)
18 var leftIterations = (granularity === "character") ? 5 : 1;
19 var rightIterations = (granularity === "character") ? 15 : 3;
21 for (var index = 0; index <= leftIterations; ++index) {
22 positions.push(getSerializedSelection());
23 getSelection().modify("extend", direction, granularity);
26 for (var index = 0; index <= rightIterations; ++index) {
27 positions.push(getSerializedSelection());
28 getSelection().modify("extend", (direction === "left") ? "right" : "left", granularity);
31 for (var index = 0; index < leftIterations; ++index) {
32 positions.push(getSerializedSelection());
33 getSelection().modify("extend", direction, granularity);
39 function extendSelectionWithinBlockWin(direction, granularity)
41 if (granularity === "character")
42 return extendSelectionWithinBlock(direction, granularity);
46 if (direction === "right") {
47 positions.push(getSerializedSelection());
48 getSelection().modify("extend", "right", granularity);
50 for (var index = 0; index < 3; ++index) {
51 positions.push(getSerializedSelection());
52 getSelection().modify("extend", "left", granularity);
55 positions.push(getSerializedSelection());
56 getSelection().modify("extend", "right", granularity);
58 positions.push(getSerializedSelection());
60 for (var index = 0; index < 2; ++index) {
61 positions.push(getSerializedSelection());
62 getSelection().modify("extend", "left", granularity);
64 for (var index = 0; index < 3; ++index) {
65 positions.push(getSerializedSelection());
66 getSelection().modify("extend", "right", granularity);
72 function extendSelectionToEnd(direction, granularity)
76 var position = getSerializedSelection();
77 positions.push(position);
78 getSelection().modify("extend", direction, granularity);
79 } while (position.node !== getSerializedSelection().node || position.end !== getSerializedSelection().end);
86 for (var i = 0; i < string.length; ++i) {
87 var char = string.charCodeAt(i);
90 else if (char == 10) {
94 result += String.fromCharCode(char);
99 function logPositions(positions)
101 for (var i = 0; i < positions.length; ++i) {
103 if (positions[i].node != positions[i - 1].node)
107 if (!i || positions[i].node != positions[i - 1].node)
108 log((positions[i].node instanceof Text ? '"' + fold(positions[i].node.data) + '"' : "<" + positions[i].node.tagName + ">") + "[");
109 log("(" + positions[i].begin + "," + positions[i].end + ")");
114 function logMismatchingPositions(positions, comparisonPositions)
116 if (positions.length !== comparisonPositions.length) {
117 log("WARNING: positions should be the same, but the length are not the same " + positions.length + " vs. " + comparisonPositions.length + "\n");
121 for (var i = 0; i < positions.length; ++i) {
122 var pos = positions[i];
123 var comparison = comparisonPositions[i];
125 if (pos.node !== comparison.node)
126 log("WARNING: positions should be the same, but node are not the same\n");
127 if (pos.begin !== comparison.begin)
128 log("WARNING: positions should be the same, but begin are not the same " + pos.begin + " vs. " + comparison.begin + "\n");
129 if (pos.end !== comparison.end)
130 log("WARNING: positions should be the same, but end are not the same " + pos.end + " vs. " + comparison.end + "\n");
134 function extendAndLogSelection(functionToExtendSelection, direction, granularity)
136 var positions = functionToExtendSelection(direction, granularity);
137 logPositions(positions);
142 function extendAndLogSelectionWithinBlock(direction, granularity, platform)
144 return extendAndLogSelection({'mac': extendSelectionWithinBlock, 'win': extendSelectionWithinBlockWin}[platform], direction, granularity);
147 function extendAndLogSelectionToEnd(direction, granularity)
149 return extendAndLogSelection(extendSelectionToEnd, direction, granularity);
152 function runSelectionTestsWithGranularity(testNodes, granularity)
154 for (var i = 0; i < testNodes.length; ++i) {
155 var testNode = testNodes[i];
157 log("Test " + (i + 1) + ", LTR:\n");
158 testNode.style.direction = "ltr";
160 log(" Extending right: ");
161 getSelection().collapse(testNode);
162 var ltrRightPos = extendAndLogSelectionToEnd("right", granularity);
164 log(" Extending left: ");
165 var ltrLeftPos = extendAndLogSelectionToEnd("left", granularity);
167 log(" Extending forward: ");
168 getSelection().collapse(testNode);
169 var ltrForwardPos = extendAndLogSelectionToEnd("forward", granularity);
171 log(" Extending backward: ");
172 var ltrBackwardPos = extendAndLogSelectionToEnd("backward", granularity);
174 log("Test " + (i + 1) + ", RTL:\n");
175 testNode.style.direction = "rtl";
177 log(" Extending left: ");
178 getSelection().collapse(testNode);
179 var rtlLeftPos = extendAndLogSelectionToEnd("left", granularity);
181 log(" Extending right: ");
182 var rtlRightPos = extendAndLogSelectionToEnd("right", granularity);
184 log(" Extending forward: ");
185 getSelection().collapse(testNode);
186 var rtlForwardPos = extendAndLogSelectionToEnd("forward", granularity);
188 log(" Extending backward: ");
189 var rtlBackwardPos = extendAndLogSelectionToEnd("backward", granularity);
192 log("\n\n validating ltrRight and ltrLeft\n");
193 if (granularity === "character")
194 logMismatchingPositions(ltrRightPos, ltrLeftPos.slice().reverse());
195 // Order might not be reversed for extending by word because the 1-point shift by space.
197 log(" validating ltrRight and ltrForward\n");
198 logMismatchingPositions(ltrRightPos, ltrForwardPos);
199 log(" validating ltrForward and rtlForward\n");
200 logMismatchingPositions(ltrForwardPos, rtlForwardPos);
201 log(" validating ltrLeft and ltrBackward\n");
202 logMismatchingPositions(ltrLeftPos, ltrBackwardPos);
203 log(" validating ltrBackward and rtlBackward\n");
204 logMismatchingPositions(ltrBackwardPos, rtlBackwardPos);
205 log(" validating ltrRight and rtlLeft\n");
206 logMismatchingPositions(ltrRightPos, rtlLeftPos);
207 log(" validating ltrLeft and rtlRight\n");
208 logMismatchingPositions(ltrLeftPos, rtlRightPos);
213 function getTestNodeContainer()
215 var tests = document.getElementById("tests");
217 tests = document.createElement("div");
219 document.body.insertBefore(tests, document.getElementById("console"));
221 function createButton(name, onclick)
223 var button = document.createElement("button");
224 button.innerText = name;
225 button.onclick = onclick;
226 button.onmousedown = function(event) {
227 // Prevent the mouse event from cancelling the current selection.
228 event.preventDefault();
233 function createButtonToSwitchDirection(direction)
235 return createButton(direction, function() {
236 for (var i = 0; i < tests.childNodes.length; ++i) {
237 var node = tests.childNodes[i];
238 if (node.className === "testNode")
239 node.style.direction = direction;
244 tests.appendChild(document.createTextNode("Use these buttons to help run the tests manually: "));
245 tests.appendChild(createButtonToSwitchDirection("ltr"));
246 tests.appendChild(createButtonToSwitchDirection("rtl"));
251 function createNode(content, style)
253 var node = document.createElement("div");
254 node.innerHTML = content;
255 node.className = "testNode";
256 node.contentEditable = true;
258 node.setAttribute("style", style);
259 getTestNodeContainer().appendChild(node);
263 function createCharAndWordNodes()
266 createNode('\nabc אבג xyz דהו def\n'),
267 createNode('\nאבג xyz דהו def זחט\n'),
268 createNode('\nאבג דהו אבג\n'),
269 createNode('\nabc efd dabeb\n'),
270 createNode('Lorem <span style="direction: rtl">ipsum dolor sit</span> amet'),
271 createNode('Lorem <span dir="rtl">ipsum dolor sit</span> amet'),
272 createNode('Lorem <span style="direction: ltr">ipsum dolor sit</span> amet'),
273 createNode('Lorem <span dir="ltr">ipsum dolor sit</span> amet')
277 function createEnclosingBlockNodes()
280 createNode('Lorem <div dir="rtl">ipsum dolor sit</div> amett')
284 function createHomeEndNodes()
287 createNode('Lorem <span style="direction: ltr">ipsum dolor sit</span> amet'),
288 createNode('Lorem <span style="direction: ltr">ipsum dolor<div > just a test</div> sit</span> amet'),
289 createNode('Lorem <span dir="ltr">ipsum dolor sit</span> amet'),
290 createNode('Lorem <div dir="ltr">ipsum dolor sit</div> amet'),
291 createNode('\n Just\n <span>testing רק</span>\n בודק\n'),
292 createNode('\n Just\n <span>testing what</span>\n ever\n'),
293 createNode('car means אבג.'),
294 createNode('‫car דהו אבג.‬'),
295 createNode('he said "‫car דהו אבג‬."'),
296 createNode('זחט יךכ לםמ \'‪he said ' +
297 '"‫car דהו אבג‬"‬\'?'),
298 createNode('אבג abc דהו<br />edf זחט abrebg'),
299 createNode('abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg ',
300 'line-break:before-white-space; width:5em'),
301 createNode('abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg ',
302 'line-break:after-white-space; width:5em')
306 function createAllNodes()
308 return createCharAndWordNodes().concat(
309 createEnclosingBlockNodes()).concat(
310 createHomeEndNodes());
313 if (window.testRunner) {
314 var originalOnload = window.onload;
315 window.onload = function() {
318 testRunner.dumpAsText();
319 document.body.removeChild(getTestNodeContainer());