|
1 <html> |
|
2 <head> |
|
3 <title>Test for contenteditable focus</title> |
|
4 <script type="text/javascript" |
|
5 src="/tests/SimpleTest/SimpleTest.js"></script> |
|
6 <link rel="stylesheet" type="text/css" |
|
7 href="/tests/SimpleTest/test.css" /> |
|
8 </head> |
|
9 <body> |
|
10 <div id="display"> |
|
11 First text in this document.<br> |
|
12 <input id="inputText" type="text"><br> |
|
13 <input id="inputTextReadonly" type="text" readonly><br> |
|
14 <input id="inputButton" type="button" value="input[type=button]"><br> |
|
15 <button id="button">button</button><br> |
|
16 <div id="editor" contenteditable="true"> |
|
17 editable contents.<br> |
|
18 <input id="inputTextInEditor" type="text"><br> |
|
19 <input id="inputTextReadonlyInEditor" type="text" readonly><br> |
|
20 <input id="inputButtonInEditor" type="button" value="input[type=button]"><br> |
|
21 <button id="buttonInEditor">button</button><br> |
|
22 <div id="noeditableInEditor" contenteditable="false"> |
|
23 <span id="spanInNoneditableInEditor">span element in noneditable in editor</span><br> |
|
24 <input id="inputTextInNoneditableInEditor" type="text"><br> |
|
25 <input id="inputTextReadonlyInNoneditableInEditor" type="text" readonly><br> |
|
26 <input id="inputButtonInNoneditableInEditor" type="button" value="input[type=button]"><br> |
|
27 <button id="buttonInNoneditableInEditor">button</button><br> |
|
28 </div> |
|
29 <span id="spanInEditor">span element in editor</span><br> |
|
30 </div> |
|
31 <div id="otherEditor" contenteditable="true"> |
|
32 other editor. |
|
33 </div> |
|
34 </div> |
|
35 <div id="content" style="display: none"> |
|
36 |
|
37 </div> |
|
38 <pre id="test"> |
|
39 </pre> |
|
40 |
|
41 <script class="testbody" type="application/javascript"> |
|
42 |
|
43 SimpleTest.waitForExplicitFinish(); |
|
44 SimpleTest.waitForFocus(runTests, window); |
|
45 |
|
46 function runTests() |
|
47 { |
|
48 runTestsInternal(); |
|
49 SimpleTest.finish(); |
|
50 } |
|
51 |
|
52 function runTestsInternal() |
|
53 { |
|
54 var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"]. |
|
55 getService(SpecialPowers.Ci.nsIFocusManager); |
|
56 // XXX using selCon for checking the visibility of the caret, however, |
|
57 // selCon is shared in document, cannot get the element of owner of the |
|
58 // caret from javascript? |
|
59 var selCon = SpecialPowers.wrap(window). |
|
60 QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor). |
|
61 getInterface(SpecialPowers.Ci.nsIWebNavigation). |
|
62 QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor). |
|
63 getInterface(SpecialPowers.Ci.nsISelectionDisplay). |
|
64 QueryInterface(SpecialPowers.Ci.nsISelectionController); |
|
65 var selection = window.getSelection(); |
|
66 |
|
67 var inputText = document.getElementById("inputText"); |
|
68 var inputTextReadonly = document.getElementById("inputTextReadonly"); |
|
69 var inputButton = document.getElementById("inputButton"); |
|
70 var button = document.getElementById("button"); |
|
71 var editor = document.getElementById("editor"); |
|
72 var inputTextInEditor = document.getElementById("inputTextInEditor"); |
|
73 var inputTextReadonlyInEditor = document.getElementById("inputTextReadonlyInEditor"); |
|
74 var inputButtonInEditor = document.getElementById("inputButtonInEditor"); |
|
75 var noeditableInEditor = document.getElementById("noeditableInEditor"); |
|
76 var spanInNoneditableInEditor = document.getElementById("spanInNoneditableInEditor"); |
|
77 var inputTextInNoneditableInEditor = document.getElementById("inputTextInNoneditableInEditor"); |
|
78 var inputTextReadonlyInNoneditableInEditor = document.getElementById("inputTextReadonlyInNoneditableInEditor"); |
|
79 var inputButtonInNoneditableInEditor = document.getElementById("inputButtonInNoneditableInEditor"); |
|
80 var buttonInNoneditableInEditor = document.getElementById("buttonInNoneditableInEditor"); |
|
81 var spanInEditor = document.getElementById("spanInEditor"); |
|
82 var otherEditor = document.getElementById("otherEditor"); |
|
83 |
|
84 // XXX if there is a contenteditable element, HTML editor sets dom selection |
|
85 // to first editable node, but this makes inconsistency with normal document |
|
86 // behavior. |
|
87 todo_is(selection.rangeCount, 0, "unexpected selection range is there"); |
|
88 ok(!selCon.caretVisible, "caret is visible in the document"); |
|
89 // Move focus to inputTextInEditor |
|
90 inputTextInEditor.focus(); |
|
91 is(SpecialPowers.unwrap(fm.focusedElement), inputTextInEditor, |
|
92 "inputTextInEditor didn't get focus"); |
|
93 todo_is(selection.rangeCount, 0, "unexpected selection range is there"); |
|
94 ok(selCon.caretVisible, "caret isn't visible in the inputTextInEditor"); |
|
95 // Move focus to the editor |
|
96 editor.focus(); |
|
97 is(SpecialPowers.unwrap(fm.focusedElement), editor, |
|
98 "editor didn't get focus"); |
|
99 is(selection.rangeCount, 1, |
|
100 "there is no selection range when editor has focus"); |
|
101 var range = selection.getRangeAt(0); |
|
102 ok(range.collapsed, "the selection range isn't collapsed"); |
|
103 var startNode = range.startContainer; |
|
104 is(startNode.nodeType, 1, "the caret isn't set to the div node"); |
|
105 is(startNode, editor, "the caret isn't set to the editor"); |
|
106 ok(selCon.caretVisible, "caret isn't visible in the editor"); |
|
107 // Move focus to other editor |
|
108 otherEditor.focus(); |
|
109 is(SpecialPowers.unwrap(fm.focusedElement), otherEditor, |
|
110 "the other editor didn't get focus"); |
|
111 is(selection.rangeCount, 1, |
|
112 "there is no selection range when the other editor has focus"); |
|
113 range = selection.getRangeAt(0); |
|
114 ok(range.collapsed, "the selection range isn't collapsed"); |
|
115 var startNode = range.startContainer; |
|
116 is(startNode.nodeType, 1, "the caret isn't set to the div node"); |
|
117 is(startNode, otherEditor, "the caret isn't set to the other editor"); |
|
118 ok(selCon.caretVisible, "caret isn't visible in the other editor"); |
|
119 // Move focus to inputTextInEditor |
|
120 inputTextInEditor.focus(); |
|
121 is(SpecialPowers.unwrap(fm.focusedElement), inputTextInEditor, |
|
122 "inputTextInEditor didn't get focus #2"); |
|
123 is(selection.rangeCount, 1, "selection range is lost from the document"); |
|
124 range = selection.getRangeAt(0); |
|
125 ok(range.collapsed, "the selection range isn't collapsed"); |
|
126 var startNode = range.startContainer; |
|
127 is(startNode.nodeType, 1, "the caret isn't set to the div node"); |
|
128 // XXX maybe, the caret can stay on the other editor if it's better. |
|
129 is(startNode, editor, |
|
130 "the caret should stay on the other editor"); |
|
131 ok(selCon.caretVisible, |
|
132 "caret isn't visible in the inputTextInEditor"); |
|
133 // Move focus to the other editor again |
|
134 otherEditor.focus(); |
|
135 is(SpecialPowers.unwrap(fm.focusedElement), otherEditor, |
|
136 "the other editor didn't get focus #2"); |
|
137 // Set selection to the span element in the editor (unfocused) |
|
138 range = document.createRange(); |
|
139 range.setStart(spanInEditor.firstChild, 5); |
|
140 selection.removeAllRanges(); |
|
141 selection.addRange(range); |
|
142 is(selection.rangeCount, 1, "selection range is lost from the document"); |
|
143 is(SpecialPowers.unwrap(fm.focusedElement), otherEditor, |
|
144 "the other editor shouldn't lose focus by selection range change"); |
|
145 ok(selCon.caretVisible, "caret isn't visible in inputTextInEditor"); |
|
146 // Move focus to the editor |
|
147 editor.focus(); |
|
148 is(SpecialPowers.unwrap(fm.focusedElement), editor, |
|
149 "the editor didn't get focus #2"); |
|
150 is(selection.rangeCount, 1, "selection range is lost from the document"); |
|
151 range = selection.getRangeAt(0); |
|
152 ok(range.collapsed, "the selection range isn't collapsed"); |
|
153 is(range.startOffset, 5, |
|
154 "the caret is moved when the editor was focused (offset)"); |
|
155 var startNode = range.startContainer; |
|
156 is(startNode.nodeType, 3, "the caret isn't in text node"); |
|
157 is(startNode.parentNode, spanInEditor, |
|
158 "the caret is moved when the editor was focused (node)"); |
|
159 ok(selCon.caretVisible, "caret isn't visible in the editor (spanInEditor)"); |
|
160 |
|
161 // Move focus to each focusable element in the editor. |
|
162 function testFocusMove(aSetFocusElementID, aFocusable, aCaretVisible) |
|
163 { |
|
164 editor.focus(); |
|
165 is(SpecialPowers.unwrap(fm.focusedElement), editor, |
|
166 "testFocusMove: the editor didn't get focus at initializing (" + |
|
167 aSetFocusElementID + ")"); |
|
168 var setFocusElement = document.getElementById(aSetFocusElementID); |
|
169 setFocusElement.focus(); |
|
170 if (aFocusable) { |
|
171 is(SpecialPowers.unwrap(fm.focusedElement), setFocusElement, |
|
172 "testFocusMove: the " + aSetFocusElementID + |
|
173 " didn't get focus"); |
|
174 } else { |
|
175 is(SpecialPowers.unwrap(fm.focusedElement), editor, |
|
176 "testFocusMove: the editor lost focus by focus() of the " + |
|
177 aSetFocusElementID); |
|
178 } |
|
179 if (aCaretVisible) { |
|
180 ok(selCon.caretVisible, |
|
181 "testFocusMove: caret isn't visible when the " + |
|
182 aSetFocusElementID + " has focus"); |
|
183 } else { |
|
184 ok(!selCon.caretVisible, |
|
185 "testFocusMove: caret is visible when the " + |
|
186 aSetFocusElementID + " has focus"); |
|
187 } |
|
188 } |
|
189 testFocusMove("inputTextInEditor", true, true); |
|
190 testFocusMove("inputTextReadonlyInEditor", true, true); |
|
191 // XXX shouldn't the caret become invisible? |
|
192 testFocusMove("inputButtonInEditor", true, true); |
|
193 testFocusMove("noeditableInEditor", false, true); |
|
194 testFocusMove("spanInNoneditableInEditor", false, true); |
|
195 testFocusMove("inputTextInNoneditableInEditor", true, true); |
|
196 testFocusMove("inputTextReadonlyInNoneditableInEditor", true, true); |
|
197 testFocusMove("inputButtonInNoneditableInEditor", true, false); |
|
198 testFocusMove("buttonInNoneditableInEditor", true, false); |
|
199 testFocusMove("spanInEditor", false, true); |
|
200 testFocusMove("inputText", true, true); |
|
201 testFocusMove("inputTextReadonly", true, true); |
|
202 testFocusMove("inputButton", true, false); |
|
203 testFocusMove("button", true, false); |
|
204 } |
|
205 |
|
206 </script> |
|
207 </body> |
|
208 |
|
209 </html> |