summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/tests/test_contenteditable_focus.html
blob: 051ac7b2f1355d7b442352d8c5af1491b46151b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<html>
<head>
  <title>Test for contenteditable focus</title>
  <script type="text/javascript"
          src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css"
          href="/tests/SimpleTest/test.css" />
</head>
<body>
<div id="display">
  First text in this document.<br>
  <input id="inputText" type="text"><br>
  <input id="inputTextReadonly" type="text" readonly><br>
  <input id="inputButton" type="button" value="input[type=button]"><br>
  <button id="button">button</button><br>
  <div id="editor" contenteditable="true">
    editable contents.<br>
    <input id="inputTextInEditor" type="text"><br>
    <input id="inputTextReadonlyInEditor" type="text" readonly><br>
    <input id="inputButtonInEditor" type="button" value="input[type=button]"><br>
    <button id="buttonInEditor">button</button><br>
    <div id="noeditableInEditor" contenteditable="false">
      <span id="spanInNoneditableInEditor">span element in noneditable in editor</span><br>
      <input id="inputTextInNoneditableInEditor" type="text"><br>
      <input id="inputTextReadonlyInNoneditableInEditor" type="text" readonly><br>
      <input id="inputButtonInNoneditableInEditor" type="button" value="input[type=button]"><br>
      <button id="buttonInNoneditableInEditor">button</button><br>
    </div>
    <span id="spanInEditor">span element in editor</span><br>
  </div>
  <div id="otherEditor" contenteditable="true">
    other editor.
  </div>
</div>
<div id="content" style="display: none">
  
</div>
<pre id="test">
</pre>

<script class="testbody" type="application/javascript">

SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests, window);

function runTests()
{
  runTestsInternal();
  SimpleTest.finish();
}

function runTestsInternal()
{
  var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"].
             getService(SpecialPowers.Ci.nsIFocusManager);
  // XXX using selCon for checking the visibility of the caret, however,
  // selCon is shared in document, cannot get the element of owner of the
  // caret from javascript?
  var selCon = SpecialPowers.wrap(window).
        QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
        getInterface(SpecialPowers.Ci.nsIWebNavigation).
        QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
        getInterface(SpecialPowers.Ci.nsISelectionDisplay).
        QueryInterface(SpecialPowers.Ci.nsISelectionController);
  var selection = window.getSelection();

  var inputText = document.getElementById("inputText");
  var inputTextReadonly = document.getElementById("inputTextReadonly");
  var inputButton = document.getElementById("inputButton");
  var button = document.getElementById("button");
  var editor = document.getElementById("editor");
  var inputTextInEditor = document.getElementById("inputTextInEditor");
  var inputTextReadonlyInEditor = document.getElementById("inputTextReadonlyInEditor");
  var inputButtonInEditor = document.getElementById("inputButtonInEditor");
  var noeditableInEditor = document.getElementById("noeditableInEditor");
  var spanInNoneditableInEditor = document.getElementById("spanInNoneditableInEditor");
  var inputTextInNoneditableInEditor = document.getElementById("inputTextInNoneditableInEditor");
  var inputTextReadonlyInNoneditableInEditor = document.getElementById("inputTextReadonlyInNoneditableInEditor");
  var inputButtonInNoneditableInEditor = document.getElementById("inputButtonInNoneditableInEditor");
  var buttonInNoneditableInEditor = document.getElementById("buttonInNoneditableInEditor");
  var spanInEditor = document.getElementById("spanInEditor");
  var otherEditor = document.getElementById("otherEditor");

  // XXX if there is a contenteditable element, HTML editor sets dom selection
  // to first editable node, but this makes inconsistency with normal document
  // behavior.
  todo_is(selection.rangeCount, 0, "unexpected selection range is there");
  ok(!selCon.caretVisible, "caret is visible in the document");
  // Move focus to inputTextInEditor
  inputTextInEditor.focus();
  is(SpecialPowers.unwrap(fm.focusedElement), inputTextInEditor,
     "inputTextInEditor didn't get focus");
  todo_is(selection.rangeCount, 0, "unexpected selection range is there");
  ok(selCon.caretVisible, "caret isn't visible in the inputTextInEditor");
  // Move focus to the editor
  editor.focus();
  is(SpecialPowers.unwrap(fm.focusedElement), editor,
     "editor didn't get focus");
  is(selection.rangeCount, 1,
     "there is no selection range when editor has focus");
  var range = selection.getRangeAt(0);
  ok(range.collapsed, "the selection range isn't collapsed");
  var startNode = range.startContainer;
  is(startNode.nodeType, 1, "the caret isn't set to the div node");
  is(startNode, editor, "the caret isn't set to the editor");
  ok(selCon.caretVisible, "caret isn't visible in the editor");
  // Move focus to other editor
  otherEditor.focus();
  is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
     "the other editor didn't get focus");
  is(selection.rangeCount, 1,
     "there is no selection range when the other editor has focus");
  range = selection.getRangeAt(0);
  ok(range.collapsed, "the selection range isn't collapsed");
  var startNode = range.startContainer;
  is(startNode.nodeType, 1, "the caret isn't set to the div node");
  is(startNode, otherEditor, "the caret isn't set to the other editor");
  ok(selCon.caretVisible, "caret isn't visible in the other editor");
  // Move focus to inputTextInEditor
  inputTextInEditor.focus();
  is(SpecialPowers.unwrap(fm.focusedElement), inputTextInEditor,
     "inputTextInEditor didn't get focus #2");
  is(selection.rangeCount, 1, "selection range is lost from the document");
  range = selection.getRangeAt(0);
  ok(range.collapsed, "the selection range isn't collapsed");
  var startNode = range.startContainer;
  is(startNode.nodeType, 1, "the caret isn't set to the div node");
  // XXX maybe, the caret can stay on the other editor if it's better.
  is(startNode, editor,
     "the caret should stay on the other editor");
  ok(selCon.caretVisible,
     "caret isn't visible in the inputTextInEditor");
  // Move focus to the other editor again
  otherEditor.focus();
  is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
     "the other editor didn't get focus #2");
  // Set selection to the span element in the editor (unfocused)
  range = document.createRange();
  range.setStart(spanInEditor.firstChild, 5);
  selection.removeAllRanges();
  selection.addRange(range);
  is(selection.rangeCount, 1, "selection range is lost from the document");
  is(SpecialPowers.unwrap(fm.focusedElement), otherEditor,
     "the other editor shouldn't lose focus by selection range change");
  ok(selCon.caretVisible, "caret isn't visible in inputTextInEditor");
  // Move focus to the editor
  editor.focus();
  is(SpecialPowers.unwrap(fm.focusedElement), editor,
     "the editor didn't get focus #2");
  is(selection.rangeCount, 1, "selection range is lost from the document");
  range = selection.getRangeAt(0);
  ok(range.collapsed, "the selection range isn't collapsed");
  is(range.startOffset, 5,
     "the caret is moved when the editor was focused (offset)");
  var startNode = range.startContainer;
  is(startNode.nodeType, 3, "the caret isn't in text node");
  is(startNode.parentNode, spanInEditor,
     "the caret is moved when the editor was focused (node)");
  ok(selCon.caretVisible, "caret isn't visible in the editor (spanInEditor)");

  // Move focus to each focusable element in the editor.
  function testFocusMove(aSetFocusElementID, aFocusable, aCaretVisible)
  {
    editor.focus();
    is(SpecialPowers.unwrap(fm.focusedElement), editor,
       "testFocusMove: the editor didn't get focus at initializing (" +
       aSetFocusElementID + ")");
    var setFocusElement = document.getElementById(aSetFocusElementID);
    setFocusElement.focus();
    if (aFocusable) {
      is(SpecialPowers.unwrap(fm.focusedElement), setFocusElement,
         "testFocusMove: the " + aSetFocusElementID +
         " didn't get focus");
    } else {
      is(SpecialPowers.unwrap(fm.focusedElement), editor,
         "testFocusMove: the editor lost focus by focus() of the " +
         aSetFocusElementID);
    }
    if (aCaretVisible) {
      ok(selCon.caretVisible,
         "testFocusMove: caret isn't visible when the " +
         aSetFocusElementID + " has focus");
    } else {
      ok(!selCon.caretVisible,
         "testFocusMove: caret is visible when the " +
         aSetFocusElementID + " has focus");
    }
  }
  testFocusMove("inputTextInEditor", true, true);
  testFocusMove("inputTextReadonlyInEditor", true, true);
  // XXX shouldn't the caret become invisible?
  testFocusMove("inputButtonInEditor", true, true);
  testFocusMove("noeditableInEditor", false, true);
  testFocusMove("spanInNoneditableInEditor", false, true);
  testFocusMove("inputTextInNoneditableInEditor", true, true);
  testFocusMove("inputTextReadonlyInNoneditableInEditor", true, true);
  testFocusMove("inputButtonInNoneditableInEditor", true, false);
  testFocusMove("buttonInNoneditableInEditor", true, false);
  testFocusMove("spanInEditor", false, true);
  testFocusMove("inputText", true, true);
  testFocusMove("inputTextReadonly", true, true);
  testFocusMove("inputButton", true, false);
  testFocusMove("button", true, false);
}

</script>
</body>

</html>