selection_test.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.dom.selectionTest');
  15. goog.setTestOnly('goog.dom.selectionTest');
  16. goog.require('goog.dom');
  17. goog.require('goog.dom.InputType');
  18. goog.require('goog.dom.TagName');
  19. goog.require('goog.dom.selection');
  20. goog.require('goog.testing.jsunit');
  21. goog.require('goog.userAgent');
  22. var input;
  23. var hiddenInput;
  24. var textarea;
  25. var hiddenTextarea;
  26. function setUp() {
  27. input = goog.dom.createDom(
  28. goog.dom.TagName.INPUT, {type: goog.dom.InputType.TEXT});
  29. textarea = goog.dom.createDom(goog.dom.TagName.TEXTAREA);
  30. hiddenInput = goog.dom.createDom(
  31. goog.dom.TagName.INPUT,
  32. {type: goog.dom.InputType.TEXT, style: 'display: none'});
  33. hiddenTextarea =
  34. goog.dom.createDom(goog.dom.TagName.TEXTAREA, {style: 'display: none'});
  35. document.body.appendChild(input);
  36. document.body.appendChild(textarea);
  37. document.body.appendChild(hiddenInput);
  38. document.body.appendChild(hiddenTextarea);
  39. }
  40. function tearDown() {
  41. goog.dom.removeChildren(document.body);
  42. }
  43. /**
  44. * Tests getStart routine in both input and textarea.
  45. */
  46. function testGetStartInput() {
  47. getStartHelper(input, hiddenInput);
  48. }
  49. function testGetStartTextarea() {
  50. getStartHelper(textarea, hiddenTextarea);
  51. }
  52. /**
  53. * Tests that getStart routine does not error for elements that are neither
  54. * text inputs nor text areas.
  55. */
  56. function testGetStartOther() {
  57. var button = goog.dom.createDom(goog.dom.TagName.BUTTON);
  58. var hiddenButton =
  59. goog.dom.createDom(goog.dom.TagName.BUTTON, {style: 'display: none'});
  60. document.body.appendChild(button);
  61. document.body.appendChild(hiddenButton);
  62. getStartHelper(button, hiddenButton);
  63. }
  64. function getStartHelper(field, hiddenField) {
  65. assertEquals(0, goog.dom.selection.getStart(field));
  66. assertEquals(0, goog.dom.selection.getStart(hiddenField));
  67. field.focus();
  68. assertEquals(0, goog.dom.selection.getStart(field));
  69. }
  70. /**
  71. * Tests the setText routine for both input and textarea
  72. * with a single line of text.
  73. */
  74. function testSetTextInput() {
  75. setTextHelper(input);
  76. }
  77. function testSetTextTextarea() {
  78. setTextHelper(textarea);
  79. }
  80. function setTextHelper(field) {
  81. // Test one line string only
  82. select(field);
  83. assertEquals('', goog.dom.selection.getText(field));
  84. goog.dom.selection.setText(field, 'Get Behind Me Satan');
  85. assertEquals('Get Behind Me Satan', goog.dom.selection.getText(field));
  86. }
  87. /**
  88. * Tests the setText routine for textarea with multiple lines of text.
  89. */
  90. function testSetTextMultipleLines() {
  91. select(textarea);
  92. assertEquals('', goog.dom.selection.getText(textarea));
  93. var isLegacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');
  94. var message = isLegacyIE ? 'Get Behind Me\r\nSatan' : 'Get Behind Me\nSatan';
  95. goog.dom.selection.setText(textarea, message);
  96. assertEquals(message, goog.dom.selection.getText(textarea));
  97. // Select the text up to the point just after the \r\n combination
  98. // or \n in GECKO.
  99. var endOfNewline = isLegacyIE ? 15 : 14;
  100. var selectedMessage = message.substring(0, endOfNewline);
  101. goog.dom.selection.setStart(textarea, 0);
  102. goog.dom.selection.setEnd(textarea, endOfNewline);
  103. assertEquals(selectedMessage, goog.dom.selection.getText(textarea));
  104. selectedMessage = isLegacyIE ? '\r\n' : '\n';
  105. goog.dom.selection.setStart(textarea, 13);
  106. goog.dom.selection.setEnd(textarea, endOfNewline);
  107. assertEquals(selectedMessage, goog.dom.selection.getText(textarea));
  108. }
  109. /**
  110. * Tests the setCursor routine for both input and textarea.
  111. */
  112. function testSetCursorInput() {
  113. setCursorHelper(input);
  114. }
  115. function testSetCursorTextarea() {
  116. setCursorHelper(textarea);
  117. }
  118. function setCursorHelper(field) {
  119. select(field);
  120. // try to set the cursor beyond the length of the content
  121. goog.dom.selection.setStart(field, 5);
  122. goog.dom.selection.setEnd(field, 15);
  123. assertEquals(0, goog.dom.selection.getStart(field));
  124. assertEquals(0, goog.dom.selection.getEnd(field));
  125. select(field);
  126. var message = 'Get Behind Me Satan';
  127. goog.dom.selection.setText(field, message);
  128. goog.dom.selection.setStart(field, 5);
  129. goog.dom.selection.setEnd(field, message.length);
  130. assertEquals(5, goog.dom.selection.getStart(field));
  131. assertEquals(message.length, goog.dom.selection.getEnd(field));
  132. // Set the end before the start, and see if getEnd returns the start
  133. // position itself.
  134. goog.dom.selection.setStart(field, 5);
  135. goog.dom.selection.setEnd(field, 3);
  136. assertEquals(3, goog.dom.selection.getEnd(field));
  137. }
  138. /**
  139. * Tests the getText and setText routines acting on selected text in
  140. * both input and textarea.
  141. */
  142. function testGetAndSetSelectedTextInput() {
  143. getAndSetSelectedTextHelper(input);
  144. }
  145. function testGetAndSetSelectedTextTextarea() {
  146. getAndSetSelectedTextHelper(textarea);
  147. }
  148. function getAndSetSelectedTextHelper(field) {
  149. select(field);
  150. goog.dom.selection.setText(field, 'Get Behind Me Satan');
  151. // select 'Behind'
  152. goog.dom.selection.setStart(field, 4);
  153. goog.dom.selection.setEnd(field, 10);
  154. assertEquals('Behind', goog.dom.selection.getText(field));
  155. goog.dom.selection.setText(field, 'In Front Of');
  156. goog.dom.selection.setStart(field, 0);
  157. goog.dom.selection.setEnd(field, 100);
  158. assertEquals('Get In Front Of Me Satan', goog.dom.selection.getText(field));
  159. }
  160. /**
  161. * Test setStart on hidden input and hidden textarea.
  162. */
  163. function testSetCursorOnHiddenInput() {
  164. setCursorOnHiddenInputHelper(hiddenInput);
  165. }
  166. function testSetCursorOnHiddenTextarea() {
  167. setCursorOnHiddenInputHelper(hiddenTextarea);
  168. }
  169. function setCursorOnHiddenInputHelper(hiddenField) {
  170. goog.dom.selection.setStart(hiddenField, 0);
  171. assertEquals(0, goog.dom.selection.getStart(hiddenField));
  172. }
  173. /**
  174. * Test setStart, setEnd, getStart and getEnd in textarea with text
  175. * containing line breaks.
  176. */
  177. function testSetAndGetCursorWithLineBreaks() {
  178. select(textarea);
  179. var isLegacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');
  180. var newline = isLegacyIE ? '\r\n' : '\n';
  181. var message = 'Hello' + newline + 'World';
  182. goog.dom.selection.setText(textarea, message);
  183. // Test setEnd and getEnd, by setting the cursor somewhere after the
  184. // \r\n combination.
  185. goog.dom.selection.setEnd(textarea, 9);
  186. assertEquals(9, goog.dom.selection.getEnd(textarea));
  187. // Test basic setStart and getStart
  188. goog.dom.selection.setStart(textarea, 10);
  189. assertEquals(10, goog.dom.selection.getStart(textarea));
  190. // Test setEnd and getEnd, by setting the cursor exactly after the
  191. // \r\n combination in IE or after \n in GECKO.
  192. var endOfNewline = isLegacyIE ? 7 : 6;
  193. checkSetAndGetTextarea(endOfNewline, endOfNewline);
  194. // Select a \r\n combination in IE or \n in GECKO and see if
  195. // getStart and getEnd work correctly.
  196. clearField(textarea);
  197. message = 'Hello' + newline + newline + 'World';
  198. goog.dom.selection.setText(textarea, message);
  199. var startOfNewline = isLegacyIE ? 7 : 6;
  200. endOfNewline = isLegacyIE ? 9 : 7;
  201. checkSetAndGetTextarea(startOfNewline, endOfNewline);
  202. // Select 2 \r\n combinations in IE or 2 \ns in GECKO and see if getStart
  203. // and getEnd work correctly.
  204. checkSetAndGetTextarea(5, endOfNewline);
  205. // Position cursor b/w 2 \r\n combinations in IE or 2 \ns in GECKO and see
  206. // if getStart and getEnd work correctly.
  207. clearField(textarea);
  208. message = 'Hello' + newline + newline + newline + newline + 'World';
  209. goog.dom.selection.setText(textarea, message);
  210. var middleOfNewlines = isLegacyIE ? 9 : 7;
  211. checkSetAndGetTextarea(middleOfNewlines, middleOfNewlines);
  212. // Position cursor at end of a textarea which ends with \r\n in IE or \n in
  213. // GECKO.
  214. if (!goog.userAgent.IE || !goog.userAgent.isVersionOrHigher('11')) {
  215. // TODO(johnlenz): investigate why this fails in IE 11.
  216. clearField(textarea);
  217. message = 'Hello' + newline + newline;
  218. goog.dom.selection.setText(textarea, message);
  219. var endOfTextarea = message.length;
  220. checkSetAndGetTextarea(endOfTextarea, endOfTextarea);
  221. }
  222. // Position cursor at the end of the 2 starting \r\ns in IE or \ns in GECKO
  223. // within a textarea.
  224. clearField(textarea);
  225. message = newline + newline + 'World';
  226. goog.dom.selection.setText(textarea, message);
  227. var endOfTwoNewlines = isLegacyIE ? 4 : 2;
  228. checkSetAndGetTextarea(endOfTwoNewlines, endOfTwoNewlines);
  229. // Position cursor at the end of the first \r\n in IE or \n in
  230. // GECKO within a textarea.
  231. endOfOneNewline = isLegacyIE ? 2 : 1;
  232. checkSetAndGetTextarea(endOfOneNewline, endOfOneNewline);
  233. }
  234. /**
  235. * Test to make sure there's no error when getting the range of an unselected
  236. * textarea. See bug 1274027.
  237. */
  238. function testGetStartOnUnfocusedTextarea() {
  239. input.value = 'White Blood Cells';
  240. input.focus();
  241. goog.dom.selection.setCursorPosition(input, 5);
  242. assertEquals(
  243. 'getStart on input should return where we put the cursor', 5,
  244. goog.dom.selection.getStart(input));
  245. assertEquals(
  246. 'getStart on unfocused textarea should succeed without error', 0,
  247. goog.dom.selection.getStart(textarea));
  248. }
  249. /**
  250. * Test to make sure there's no error setting cursor position within a
  251. * textarea after a newline. This is problematic on IE because of the
  252. * '\r\n' vs '\n' issue.
  253. */
  254. function testSetCursorPositionTextareaWithNewlines() {
  255. textarea.value = 'Hello\nWorld';
  256. textarea.focus();
  257. // Set the selection point between 'W' and 'o'. Position is computed this
  258. // way instead of being hard-coded because it's different in IE due to \r\n
  259. // vs \n.
  260. goog.dom.selection.setCursorPosition(textarea, textarea.value.length - 4);
  261. var isLegacyIE = goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('9');
  262. var linebreak = isLegacyIE ? '\r\n' : '\n';
  263. var expectedLeftString = 'Hello' + linebreak + 'W';
  264. assertEquals(
  265. 'getStart on input should return after the newline',
  266. expectedLeftString.length, goog.dom.selection.getStart(textarea));
  267. assertEquals(
  268. 'getEnd on input should return after the newline',
  269. expectedLeftString.length, goog.dom.selection.getEnd(textarea));
  270. goog.dom.selection.setEnd(textarea, textarea.value.length);
  271. assertEquals('orld', goog.dom.selection.getText(textarea));
  272. }
  273. /**
  274. * Helper function to clear the textfield contents.
  275. */
  276. function clearField(field) {
  277. field.value = '';
  278. }
  279. /**
  280. * Helper function to set the start and end and assert the getter values.
  281. */
  282. function checkSetAndGetTextarea(start, end) {
  283. goog.dom.selection.setStart(textarea, start);
  284. goog.dom.selection.setEnd(textarea, end);
  285. assertEquals(start, goog.dom.selection.getStart(textarea));
  286. assertEquals(end, goog.dom.selection.getEnd(textarea));
  287. }
  288. /**
  289. * Helper function to focus and select a field. In IE8, selected
  290. * fields need focus.
  291. */
  292. function select(field) {
  293. field.focus();
  294. field.select();
  295. }