/tests/tinymce.Formatter_apply.html

https://github.com/chrisdarroch/tinymce · HTML · 1054 lines · 949 code · 105 blank · 0 comment · 0 complexity · ef8637cebe906fbe39b9fde3483b0155 MD5 · raw file

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <title>Unit tests for apply formatting</title>
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
  7. <script src="http://code.jquery.com/qunit/qunit-git.js"></script>
  8. <script src="qunit/connector.js"></script>
  9. <script type="text/javascript" src="qunit/runner.js"></script>
  10. <script type="text/javascript" src="js/utils.js"></script>
  11. <script type="text/javascript" src="js/tiny_mce_loader.js"></script>
  12. <script>
  13. var editor, rng, format;
  14. QUnit.config.reorder = false;
  15. QUnit.config.autostart = false;
  16. module("Apply formatting", {
  17. autostart: false
  18. });
  19. function getContent() {
  20. return editor.getContent().toLowerCase().replace(/[\r]+/g, '');
  21. };
  22. test('apply inline to a list', function(){
  23. editor.formatter.register('format', {inline : 'b', toggle: false});
  24. editor.getBody().innerHTML = '<p>1234</p><ul><li>first element</li><li>second element</li></ul><p>5678</p>';
  25. rng = editor.dom.createRng();
  26. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  27. rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
  28. editor.selection.setRng(rng);
  29. editor.formatter.apply('format');
  30. equals(getContent(), '<p><b>1234</b></p><ul><li><b>first element</b></li><li><b>second element</b></li></ul><p><b>5678</b></p>', 'selection of a list');
  31. });
  32. test('Toggle OFF - Inline element on selected text', function() {
  33. // Toggle OFF - Inline element on selected text
  34. editor.formatter.register('format', {inline : 'b', toggle: false});
  35. editor.getBody().innerHTML = '<p><b>1234</b></p>';
  36. rng = editor.dom.createRng();
  37. rng.setStart(editor.dom.select('b')[0].firstChild, 0);
  38. rng.setEnd(editor.dom.select('b')[0].firstChild, 4);
  39. editor.selection.setRng(rng);
  40. editor.formatter.toggle('format');
  41. equals(getContent(), '<p><b>1234</b></p>');
  42. });
  43. test('Toggle OFF - Inline element on partially selected text', function() {
  44. // Toggle OFF - Inline element on partially selected text
  45. editor.formatter.register('format', {inline : 'b', toggle: 0});
  46. editor.getBody().innerHTML = '<p>1<b>23</b>4</p>';
  47. rng = editor.dom.createRng();
  48. rng.setStart(editor.dom.select('b')[0].firstChild, 0);
  49. rng.setEnd(editor.dom.select('b')[0].firstChild, 2);
  50. editor.selection.setRng(rng);
  51. editor.formatter.toggle('format');
  52. equals(getContent(), '<p>1<b>23</b>4</p>');
  53. });
  54. test('Toggle OFF - Inline element on partially selected text in start/end elements', function() {
  55. // Toggle OFF - Inline element on partially selected text in start/end elements
  56. editor.formatter.register('format', {inline : 'b', toggle: false});
  57. editor.getBody().innerHTML = '<p>1<b>234</b></p><p><b>123</b>4</p>';//'<p>1234</p><p>1234</p>';
  58. rng = editor.dom.createRng();
  59. rng.setStart(editor.dom.select('b')[0].firstChild, 0);
  60. rng.setEnd(editor.dom.select('b')[1].firstChild, 3);
  61. editor.selection.setRng(rng);
  62. editor.formatter.toggle('format');
  63. equals(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
  64. });
  65. test('Toggle ON - NO inline element on selected text', function() {
  66. // Inline element on selected text
  67. editor.formatter.register('format', {inline : 'b', toggle: true});
  68. editor.getBody().innerHTML = '<p>1234</p>';
  69. rng = editor.dom.createRng();
  70. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  71. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  72. editor.selection.setRng(rng);
  73. editor.formatter.apply('format');
  74. equals(getContent(), '<p><b>1234</b></p>', 'Inline element on selected text');
  75. editor.formatter.toggle('format');
  76. equals(getContent(), '<p>1234</p>', 'Toggle ON - NO inline element on selected text');
  77. });
  78. test('Selection spanning from within format to outside format with toggle off', function() {
  79. editor.formatter.register('format', {inline : 'b', toggle: false});
  80. editor.getBody().innerHTML = '<p><b>12</b>34</p>';
  81. rng = editor.dom.createRng();
  82. rng.setStart(editor.dom.select('b')[0].firstChild, 0);
  83. rng.setEnd(editor.dom.select('p')[0].lastChild, 2);
  84. editor.selection.setRng(rng);
  85. editor.formatter.toggle('format');
  86. equals(getContent(), '<p><b>1234</b></p>', 'Extend formating if start of selection is already formatted');
  87. });
  88. test('Inline element on partially selected text', function() {
  89. editor.formatter.register('format', {inline : 'b'});
  90. editor.getBody().innerHTML = '<p>1234</p>';
  91. rng = editor.dom.createRng();
  92. rng.setStart(editor.dom.select('p')[0].firstChild, 1);
  93. rng.setEnd(editor.dom.select('p')[0].firstChild, 3);
  94. editor.selection.setRng(rng);
  95. editor.formatter.apply('format');
  96. equals(getContent(), '<p>1<b>23</b>4</p>', 'Inline element on partially selected text');
  97. editor.formatter.toggle('format');
  98. equals(getContent(), '<p>1234</p>', 'Toggle ON - NO inline element on partially selected text');
  99. });
  100. test('Inline element on partially selected text in start/end elements', function() {
  101. // Inline element on partially selected text in start/end elements
  102. editor.formatter.register('format', {inline : 'b'});
  103. editor.getBody().innerHTML = '<p>1234</p><p>1234</p>';
  104. rng = editor.dom.createRng();
  105. rng.setStart(editor.dom.select('p')[0].firstChild, 1);
  106. rng.setEnd(editor.dom.select('p')[1].firstChild, 3);
  107. editor.selection.setRng(rng);
  108. editor.formatter.apply('format');
  109. equals(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
  110. });
  111. test('Inline element on selected element', function() {
  112. editor.formatter.register('format', {inline : 'b'});
  113. editor.getBody().innerHTML = '<p>1234</p>';
  114. rng = editor.dom.createRng();
  115. rng.setStart(editor.getBody(), 0);
  116. rng.setEnd(editor.getBody(), 1);
  117. editor.selection.setRng(rng);
  118. editor.formatter.apply('format');
  119. equals(getContent(), '<p><b>1234</b></p>', 'Inline element on selected element');
  120. });
  121. test('Inline element on multiple selected elements', function() {
  122. editor.formatter.register('format', {inline : 'b'});
  123. editor.getBody().innerHTML = '<p>1234</p><p>1234</p>';
  124. rng = editor.dom.createRng();
  125. rng.setStart(editor.getBody(), 0);
  126. rng.setEnd(editor.getBody(), 2);
  127. editor.selection.setRng(rng);
  128. editor.formatter.apply('format');
  129. equals(getContent(), '<p><b>1234</b></p><p><b>1234</b></p>', 'Inline element on multiple selected elements');
  130. });
  131. test('Inline element on multiple selected elements with various childnodes', function() {
  132. editor.formatter.register('format', {inline : 'b'});
  133. editor.getBody().innerHTML = '<p><em>1234</em>5678<span>9</span></p><p><em>1234</em>5678<span>9</span></p>';
  134. rng = editor.dom.createRng();
  135. rng.setStart(editor.getBody(), 0);
  136. rng.setEnd(editor.getBody(), 2);
  137. editor.selection.setRng(rng);
  138. editor.formatter.apply('format');
  139. equals(getContent(), '<p><b><em>1234</em>5678<span>9</span></b></p><p><b><em>1234</em>5678<span>9</span></b></p>', 'Inline element on multiple selected elements with various childnodes');
  140. });
  141. test('Inline element with attributes', function() {
  142. editor.formatter.register('format', {inline : 'b', attributes : {title : 'value1', id : 'value2'}});
  143. editor.getBody().innerHTML = '<p>1234</p>';
  144. rng = editor.dom.createRng();
  145. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  146. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  147. editor.selection.setRng(rng);
  148. editor.formatter.apply('format');
  149. equals(getContent(), '<p><b id="value2" title="value1">1234</b></p>', 'Inline element with attributes');
  150. });
  151. test('Inline element with styles', function() {
  152. editor.formatter.register('format', {inline : 'b', styles : {color : '#ff0000', fontSize : '10px'}});
  153. editor.getBody().innerHTML = '<p>1234</p>';
  154. rng = editor.dom.createRng();
  155. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  156. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  157. editor.selection.setRng(rng);
  158. editor.formatter.apply('format');
  159. equals(getContent(), '<p><b style=\"color: #ff0000; font-size: 10px;\">1234</b></p>', 'Inline element with styles');
  160. });
  161. test('Inline element with attributes and styles', function() {
  162. editor.formatter.register('format', {inline : 'b', attributes : {title : 'value1', id : 'value2'}, styles : {color : '#ff0000', fontSize : '10px'}});
  163. editor.getBody().innerHTML = '<p>1234</p>';
  164. rng = editor.dom.createRng();
  165. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  166. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  167. editor.selection.setRng(rng);
  168. editor.formatter.apply('format');
  169. equals(getContent(), '<p><b id="value2" style="color: #ff0000; font-size: 10px;" title="value1">1234</b></p>', 'Inline element with attributes and styles');
  170. });
  171. test('Inline element with wrapable parents', function() {
  172. editor.formatter.register('format', {inline : 'b'});
  173. editor.getBody().innerHTML = '<p>x<em><span>1234</span></em>y</p>';
  174. rng = editor.dom.createRng();
  175. rng.setStart(editor.dom.select('span')[0].firstChild, 0);
  176. rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
  177. editor.selection.setRng(rng);
  178. editor.formatter.apply('format');
  179. equals(getContent(), '<p>x<b><em><span>1234</span></em></b>y</p>', 'Inline element with wrapable parents');
  180. });
  181. test('Inline element with redundant child', function() {
  182. editor.formatter.register('format', {inline : 'b'});
  183. editor.getBody().innerHTML = '<p><b>1234</b></p>';
  184. rng = editor.dom.createRng();
  185. rng.setStart(editor.dom.select('p')[0], 0);
  186. rng.setEnd(editor.dom.select('p')[0], 1);
  187. editor.selection.setRng(rng);
  188. editor.formatter.apply('format');
  189. equals(getContent(), '<p><b>1234</b></p>', 'Inline element with redundant child');
  190. });
  191. test('Inline element with redundant parent', function() {
  192. editor.formatter.register('format', {inline : 'b'});
  193. editor.getBody().innerHTML = '<p><b>a<em>1234</em>b</b></p>';
  194. rng = editor.dom.createRng();
  195. rng.setStart(editor.dom.select('em')[0].firstChild, 0);
  196. rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
  197. editor.selection.setRng(rng);
  198. editor.formatter.apply('format');
  199. equals(getContent(), '<p><b>a<em>1234</em>b</b></p>', 'Inline element with redundant parent');
  200. });
  201. test('Inline element with redundant child of similar type 1', function() {
  202. editor.formatter.register('format', [
  203. {inline : 'b'},
  204. {inline : 'strong'}
  205. ]);
  206. editor.getBody().innerHTML = '<p>a<strong>1234</strong>b</p>';
  207. rng = editor.dom.createRng();
  208. rng.setStart(editor.dom.select('p')[0], 0);
  209. rng.setEnd(editor.dom.select('p')[0], 3);
  210. editor.selection.setRng(rng);
  211. editor.formatter.apply('format');
  212. equals(getContent(), '<p><b>a1234b</b></p>', 'Inline element with redundant child of similar type 1');
  213. });
  214. test('Inline element with redundant child of similar type 2', function() {
  215. editor.formatter.register('format', [
  216. {inline : 'b'},
  217. {inline : 'span', styles : {fontWeight : 'bold'}}
  218. ]);
  219. editor.getBody().innerHTML = '<p><span style="font-weight:bold">1234</span></p>';
  220. rng = editor.dom.createRng();
  221. rng.setStart(editor.dom.select('p')[0], 0);
  222. rng.setEnd(editor.dom.select('p')[0], 1);
  223. editor.selection.setRng(rng);
  224. editor.formatter.apply('format');
  225. equals(getContent(), '<p><b>1234</b></p>', 'Inline element with redundant child of similar type 2');
  226. });
  227. test('Inline element with redundant children of similar types', function() {
  228. editor.formatter.register('format', [
  229. {inline : 'b'},
  230. {inline : 'strong'},
  231. {inline : 'span', styles : {fontWeight : 'bold'}}
  232. ]);
  233. editor.getBody().innerHTML = '<p><span style="font-weight:bold">a<strong>1234</strong><b>5678</b>b</span></p>';
  234. rng = editor.dom.createRng();
  235. rng.setStart(editor.dom.select('p')[0], 0);
  236. rng.setEnd(editor.dom.select('p')[0], 1);
  237. editor.selection.setRng(rng);
  238. editor.formatter.apply('format');
  239. equals(getContent(), '<p><b>a12345678b</b></p>', 'Inline element with redundant children of similar types');
  240. });
  241. test('Inline element with redundant parent 1', function() {
  242. editor.formatter.register('format', [
  243. {inline : 'b'},
  244. {inline : 'strong'}
  245. ]);
  246. editor.getBody().innerHTML = '<p><strong>a<em>1234</em>b</strong></p>';
  247. rng = editor.dom.createRng();
  248. rng.setStart(editor.dom.select('em')[0].firstChild, 0);
  249. rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
  250. editor.selection.setRng(rng);
  251. editor.formatter.apply('format');
  252. equals(getContent(), '<p><strong>a<em>1234</em>b</strong></p>', 'Inline element with redundant parent 1');
  253. });
  254. test('Inline element with redundant parent 2', function() {
  255. editor.formatter.register('format', [
  256. {inline : 'b'},
  257. {inline : 'span', styles : {fontWeight : 'bold'}}
  258. ]);
  259. editor.getBody().innerHTML = '<p><span style="font-weight:bold">a<em>1234</em>b</span></p>';
  260. rng = editor.dom.createRng();
  261. rng.setStart(editor.dom.select('em')[0].firstChild, 0);
  262. rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
  263. editor.selection.setRng(rng);
  264. editor.formatter.apply('format');
  265. equals(getContent(), '<p><span style="font-weight: bold;">a<em>1234</em>b</span></p>', 'Inline element with redundant parent 2');
  266. });
  267. test('Inline element with redundant parents of similar types', function() {
  268. editor.formatter.register('format', [
  269. {inline : 'b'},
  270. {inline : 'strong'},
  271. {inline : 'span', styles : {fontWeight : 'bold'}}
  272. ]);
  273. editor.getBody().innerHTML = '<p><span style="font-weight:bold"><strong><b>a<em>1234</em>b</b></strong></span></p>';
  274. rng = editor.dom.createRng();
  275. rng.setStart(editor.dom.select('em')[0].firstChild, 0);
  276. rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
  277. editor.selection.setRng(rng);
  278. editor.formatter.apply('format');
  279. equals(getContent(), '<p><span style="font-weight: bold;"><strong><b>a<em>1234</em>b</b></strong></span></p>', 'Inline element with redundant parents of similar types');
  280. });
  281. test('Inline element merged with parent and child', function() {
  282. editor.formatter.register('format', {inline : 'b'});
  283. editor.getBody().innerHTML = '<p>a<b>12<b>34</b>56</b>b</p>';
  284. rng = editor.dom.createRng();
  285. rng.setStart(editor.dom.select('b')[0].firstChild, 1);
  286. rng.setEnd(editor.dom.select('b')[0].lastChild, 1);
  287. editor.selection.setRng(rng);
  288. editor.formatter.apply('format');
  289. equals(getContent(), '<p>a<b>123456</b>b</p>', 'Inline element merged with parent and child');
  290. });
  291. test('Inline element merged with child 1', function() {
  292. editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
  293. editor.getBody().innerHTML = '<p>a<span style="font-weight:bold">1234</span>b</p>';
  294. rng = editor.dom.createRng();
  295. rng.setStart(editor.getBody(), 0);
  296. rng.setEnd(editor.getBody(), 1);
  297. editor.selection.setRng(rng);
  298. editor.formatter.apply('format');
  299. equals(getContent(), '<p><span style="font-weight: bold;">a1234b</span></p>', 'Inline element merged with child 1');
  300. });
  301. test('Inline element merged with child 2', function() {
  302. editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
  303. editor.getBody().innerHTML = '<p>a<span style="font-weight:bold; color:#ff0000">1234</span>b</p>';
  304. rng = editor.dom.createRng();
  305. rng.setStart(editor.getBody(), 0);
  306. rng.setEnd(editor.getBody(), 1);
  307. editor.selection.setRng(rng);
  308. editor.formatter.apply('format');
  309. equals(getContent(), '<p><span style=\"font-weight: bold;\">a<span style=\"color: #ff0000;\">1234</span>b</span></p>', 'Inline element merged with child 2');
  310. });
  311. test('Inline element merged with child 3', function() {
  312. editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
  313. editor.getBody().innerHTML = '<p>a<span id="id" style="font-weight:bold">1234</span>b</p>';
  314. rng = editor.dom.createRng();
  315. rng.setStart(editor.getBody(), 0);
  316. rng.setEnd(editor.getBody(), 1);
  317. editor.selection.setRng(rng);
  318. editor.formatter.apply('format');
  319. equals(getContent(), '<p><span style=\"font-weight: bold;\">a<span id=\"id\">1234</span>b</span></p>', 'Inline element merged with child 3');
  320. });
  321. test('Inline element merged with child 3', function() {
  322. editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}, merge : true});
  323. editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
  324. rng = editor.dom.createRng();
  325. rng.setStart(editor.getBody(), 0);
  326. rng.setEnd(editor.getBody(), 1);
  327. editor.selection.setRng(rng);
  328. editor.formatter.apply('format');
  329. equals(getContent(), '<p><span style="color: #ff0000; font-weight: bold;">1234</span></p>', 'Inline element merged with child 3');
  330. });
  331. test('Inline element merged with child 4', function() {
  332. editor.formatter.register('format', {inline : 'span', styles : {color : '#00ff00'}});
  333. editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
  334. rng = editor.dom.createRng();
  335. rng.setStart(editor.getBody(), 0);
  336. rng.setEnd(editor.getBody(), 1);
  337. editor.selection.setRng(rng);
  338. editor.formatter.apply('format');
  339. equals(getContent(), '<p><span style="color: #00ff00;">1234</span></p>', 'Inline element merged with child 4');
  340. });
  341. test('Inline element with attributes merged with child 1', function() {
  342. editor.formatter.register('format', {inline : 'font', attributes : {face : 'arial'}, merge : true});
  343. editor.getBody().innerHTML = '<p><font size="7">1234</font></p>';
  344. rng = editor.dom.createRng();
  345. rng.setStart(editor.getBody(), 0);
  346. rng.setEnd(editor.getBody(), 1);
  347. editor.selection.setRng(rng);
  348. editor.formatter.apply('format');
  349. equals(getContent(), '<p><font face="arial" size="7">1234</font></p>', 'Inline element with attributes merged with child 1');
  350. });
  351. test('Inline element with attributes merged with child 2', function() {
  352. editor.formatter.register('format', {inline : 'font', attributes : {size : '7'}});
  353. editor.getBody().innerHTML = '<p>a<font size="7">1234</font>b</p>';
  354. rng = editor.dom.createRng();
  355. rng.setStart(editor.getBody(), 0);
  356. rng.setEnd(editor.getBody(), 1);
  357. editor.selection.setRng(rng);
  358. editor.formatter.apply('format');
  359. equals(getContent(), '<p><font size="7">a1234b</font></p>', 'Inline element with attributes merged with child 2');
  360. });
  361. test('Inline element merged with left sibling', function() {
  362. editor.formatter.register('format', {inline : 'b'});
  363. editor.getBody().innerHTML = '<p><b>1234</b>5678</p>';
  364. rng = editor.dom.createRng();
  365. rng.setStart(editor.dom.select('p')[0].lastChild, 0);
  366. rng.setEnd(editor.dom.select('p')[0].lastChild, 4);
  367. editor.selection.setRng(rng);
  368. editor.formatter.apply('format');
  369. equals(getContent(), '<p><b>12345678</b></p>', 'Inline element merged with left sibling');
  370. });
  371. test('Inline element merged with right sibling', function() {
  372. editor.formatter.register('format', {inline : 'b'});
  373. editor.getBody().innerHTML = '<p>1234<b>5678</b></p>';
  374. rng = editor.dom.createRng();
  375. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  376. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  377. editor.selection.setRng(rng);
  378. editor.formatter.apply('format');
  379. equals(getContent(), '<p><b>12345678</b></p>', 'Inline element merged with right sibling');
  380. });
  381. test('Inline element merged with left and right siblings', function() {
  382. editor.formatter.register('format', {inline : 'b'});
  383. editor.getBody().innerHTML = '<p><b>12</b>34<b>56</b></p>';
  384. rng = editor.dom.createRng();
  385. rng.setStart(editor.dom.select('p')[0].childNodes[1], 0);
  386. rng.setEnd(editor.dom.select('p')[0].childNodes[1], 2);
  387. editor.selection.setRng(rng);
  388. editor.formatter.apply('format');
  389. equals(getContent(), '<p><b>123456</b></p>', 'Inline element merged with left and right siblings');
  390. });
  391. test('Don\'t merge siblings with whitespace between 1', function() {
  392. editor.formatter.register('format', {inline : 'b'});
  393. editor.getBody().innerHTML = '<p><b>a</b> b</p>';
  394. rng = editor.dom.createRng();
  395. rng.setStart(editor.dom.select('p')[0].lastChild, 1);
  396. rng.setEnd(editor.dom.select('p')[0].lastChild, 2);
  397. editor.selection.setRng(rng);
  398. editor.formatter.apply('format');
  399. equals(getContent(), '<p><b>a</b> <b>b</b></p>', 'Don\'t merge siblings with whitespace between 1');
  400. });
  401. test('Don\'t merge siblings with whitespace between 1', function() {
  402. editor.formatter.register('format', {inline : 'b'});
  403. editor.getBody().innerHTML = '<p>a <b>b</b></p>';
  404. rng = editor.dom.createRng();
  405. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  406. rng.setEnd(editor.dom.select('p')[0].firstChild, 1);
  407. editor.selection.setRng(rng);
  408. editor.formatter.apply('format');
  409. equals(getContent(), '<p><b>a</b> <b>b</b></p>', 'Don\'t merge siblings with whitespace between 2');
  410. });
  411. test('Inline element not merged in exact mode', function() {
  412. editor.formatter.register('format', {inline : 'span', styles : {color : '#00ff00'}, exact : true});
  413. editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
  414. rng = editor.dom.createRng();
  415. rng.setStart(editor.getBody(), 0);
  416. rng.setEnd(editor.getBody(), 1);
  417. editor.selection.setRng(rng);
  418. editor.formatter.apply('format');
  419. equals(getContent(), '<p><span style="color: #00ff00;"><span style="color: #ff0000;">1234</span></span></p>', 'Inline element not merged in exact mode');
  420. });
  421. test('Inline element merged in exact mode', function() {
  422. editor.formatter.register('format', {inline : 'span', styles : {color : '#ff0000'}, exact : true});
  423. editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
  424. rng = editor.dom.createRng();
  425. rng.setStart(editor.getBody(), 0);
  426. rng.setEnd(editor.getBody(), 1);
  427. editor.selection.setRng(rng);
  428. editor.formatter.apply('format');
  429. equals(getContent(), '<p><span style="color: #ff0000;">1234</span></p>', 'Inline element merged in exact mode');
  430. });
  431. test('Deep left branch', function() {
  432. editor.formatter.register('format', {inline : 'b'});
  433. editor.getBody().innerHTML = '<p><em><i><ins>1234</ins></i></em><em>text1</em><em>text2</em></p><p><em>5678</em></p><p>9012</p>';
  434. rng = editor.dom.createRng();
  435. rng.setStart(editor.dom.select('ins')[0].firstChild, 1);
  436. rng.setEnd(editor.dom.select('p')[2].firstChild, 4);
  437. editor.selection.setRng(rng);
  438. editor.formatter.apply('format');
  439. equals(getContent(), '<p><em><i><ins>1<b>234</b></ins></i></em><b><em>text1</em><em>text2</em></b></p><p><b><em>5678</em></b></p><p><b>9012</b></p>', 'Deep left branch');
  440. });
  441. test('Deep right branch', function() {
  442. editor.formatter.register('format', {inline : 'b'});
  443. editor.getBody().innerHTML = '<p>9012</p><p><em>5678</em></p><p><em><i><ins>1234</ins></i></em><em>text1</em><em>text2</em></p>';
  444. rng = editor.dom.createRng();
  445. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  446. rng.setEnd(editor.dom.select('em')[3].firstChild, 4);
  447. editor.selection.setRng(rng);
  448. editor.formatter.apply('format');
  449. equals(getContent(), '<p><b>9012</b></p><p><b><em>5678</em></b></p><p><b><em><i><ins>1234</ins></i></em><em>text1</em></b><em><b>text</b>2</em></p>', 'Deep right branch');
  450. });
  451. test('Full element text selection on two elements with a table in the middle', function() {
  452. editor.formatter.register('format', {inline : 'b'});
  453. editor.getBody().innerHTML = '<p>1234</p><table><tbody><tr><td>123</td></tr></tbody></table><p>5678</p>';
  454. rng = editor.dom.createRng();
  455. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  456. rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
  457. editor.selection.setRng(rng);
  458. editor.formatter.apply('format');
  459. equals(getContent(), '<p><b>1234</b></p><table><tbody><tr><td><b>123</b></td></tr></tbody></table><p><b>5678</b></p>', 'Full element text selection on two elements with a table in the middle');
  460. });
  461. test('Inline element on selected text with variables', function() {
  462. editor.formatter.register('format', {inline : 'b', styles : {color : '%color'}, attributes : {title : '%title'}}, {color : '#ff0000', title : 'title'});
  463. editor.getBody().innerHTML = '<p>1234</p>';
  464. rng = editor.dom.createRng();
  465. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  466. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  467. editor.selection.setRng(rng);
  468. editor.formatter.apply('format', {color : '#ff0000', title : 'title'});
  469. equals(getContent(), '<p><b style="color: #ff0000;" title="title">1234</b></p>', 'Inline element on selected text');
  470. });
  471. test('Remove redundant children', function() {
  472. editor.formatter.register('format', {inline : 'span', styles : {fontFamily : 'arial'}});
  473. editor.getBody().innerHTML = '<p><span style="font-family: sans-serif;"><span style="font-family: palatino;">1</span>2<span style="font-family: verdana;">3</span>4</span></p>';
  474. rng = editor.dom.createRng();
  475. rng.setStart(editor.dom.select('p')[0], 0);
  476. rng.setEnd(editor.dom.select('p')[0], 1);
  477. editor.selection.setRng(rng);
  478. editor.formatter.apply('format');
  479. equals(getContent(), '<p><span style=\"font-family: ' + fontFace('arial') + ';\">1234</span></p>', 'Remove redundant children');
  480. });
  481. test('Inline element on selected text with function values', function() {
  482. editor.formatter.register('format', {
  483. inline : 'b',
  484. styles : {
  485. color : function(vars) {
  486. return vars.color + '00ff';
  487. }
  488. },
  489. attributes : {
  490. title : function(vars) {
  491. return vars.title + '2';
  492. }
  493. }
  494. });
  495. editor.getBody().innerHTML = '<p>1234</p>';
  496. rng = editor.dom.createRng();
  497. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  498. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  499. editor.selection.setRng(rng);
  500. editor.formatter.apply('format', {
  501. color : '#ff',
  502. title : 'title'
  503. });
  504. equals(getContent(), '<p><b style="color: #ff00ff;" title="title2">1234</b></p>', 'Inline element on selected text with function values');
  505. });
  506. test('Block element on selected text', function() {
  507. editor.formatter.register('format', {block : 'div'});
  508. editor.getBody().innerHTML = '<p>1234</p>';
  509. rng = editor.dom.createRng();
  510. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  511. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  512. editor.selection.setRng(rng);
  513. editor.formatter.apply('format');
  514. equals(getContent(), '<div>1234</div>', 'Block element on selected text');
  515. });
  516. test('Block element on partially selected text', function() {
  517. editor.formatter.register('format', {block : 'div'});
  518. editor.getBody().innerHTML = '<p>1234</p>';
  519. rng = editor.dom.createRng();
  520. rng.setStart(editor.dom.select('p')[0].firstChild, 1);
  521. rng.setEnd(editor.dom.select('p')[0].firstChild, 3);
  522. editor.selection.setRng(rng);
  523. editor.formatter.apply('format');
  524. equals(getContent(), '<div>1234</div>', 'Block element on partially selected text');
  525. });
  526. test('Block element on selected element', function() {
  527. editor.formatter.register('format', {block : 'div'});
  528. editor.getBody().innerHTML = '<p>1234</p>';
  529. rng = editor.dom.createRng();
  530. rng.setStart(editor.getBody(), 0);
  531. rng.setEnd(editor.getBody(), 1);
  532. editor.selection.setRng(rng);
  533. editor.formatter.apply('format');
  534. equals(getContent(), '<div>1234</div>', 'Block element on selected element');
  535. });
  536. test('Block element on selected elements', function() {
  537. editor.formatter.register('format', {block : 'div'});
  538. editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
  539. rng = editor.dom.createRng();
  540. rng.setStart(editor.getBody(), 0);
  541. rng.setEnd(editor.getBody(), 2);
  542. editor.selection.setRng(rng);
  543. editor.formatter.apply('format');
  544. equals(getContent(), '<div>1234</div><div>5678</div>', 'Block element on selected elements');
  545. });
  546. test('Block element on selected elements with attributes', function() {
  547. editor.formatter.register('format', {block : 'div', attributes : {'title' : 'test'}});
  548. editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
  549. rng = editor.dom.createRng();
  550. rng.setStart(editor.getBody(), 0);
  551. rng.setEnd(editor.getBody(), 2);
  552. editor.selection.setRng(rng);
  553. editor.formatter.apply('format');
  554. equals(getContent(), '<div title="test">1234</div><div title="test">5678</div>', 'Block element on selected elements with attributes');
  555. });
  556. test('Block element on nested element', function() {
  557. editor.formatter.register('format', {block : 'p'});
  558. editor.getBody().innerHTML = '<div><h1>1234</h1></div>';
  559. rng = editor.dom.createRng();
  560. rng.setStart(editor.dom.select('h1')[0].firstChild, 0);
  561. rng.setEnd(editor.dom.select('h1')[0].firstChild, 4);
  562. editor.selection.setRng(rng);
  563. editor.formatter.apply('format');
  564. equals(getContent(), '<div><p>1234</p></div>', 'Block element on nested element');
  565. });
  566. test('Block element on selected non wrapped text 1', function() {
  567. editor.formatter.register('format', {block : 'div'});
  568. editor.getBody().innerHTML = '1234';
  569. rng = editor.dom.createRng();
  570. rng.setStart(editor.getBody().firstChild, 0);
  571. rng.setEnd(editor.getBody().firstChild, 4);
  572. editor.selection.setRng(rng);
  573. editor.formatter.apply('format');
  574. equals(getContent(), '<div>1234</div>', 'Block element on selected non wrapped text 1');
  575. });
  576. test('Block element on selected non wrapped text 2', function() {
  577. editor.formatter.register('format', {block : 'div'});
  578. editor.getBody().innerHTML = '1234<br />4567<br />8910';
  579. rng = editor.dom.createRng();
  580. rng.setStart(editor.getBody().firstChild, 0);
  581. rng.setEnd(editor.getBody().lastChild, 4);
  582. editor.selection.setRng(rng);
  583. editor.formatter.apply('format');
  584. equals(getContent(), '<div>1234</div><div>4567</div><div>8910</div>', 'Block element on selected non wrapped text 2');
  585. });
  586. test('Block element on selected non wrapped text 3', function() {
  587. editor.formatter.register('format', {block : 'div'});
  588. editor.getBody().innerHTML = '<br />1234<br /><br />4567<br />8910<br />';
  589. rng = editor.dom.createRng();
  590. rng.setStart(editor.getBody(), 0);
  591. rng.setEnd(editor.getBody(), 7);
  592. editor.selection.setRng(rng);
  593. editor.formatter.apply('format');
  594. equals(getContent(), '<div>1234</div><div>4567</div><div>8910</div>', 'Block element on selected non wrapped text 3');
  595. });
  596. test('Block element wrapper 1', function() {
  597. editor.formatter.register('format', {block : 'blockquote', wrapper : 1});
  598. editor.getBody().innerHTML = '<h1>1234</h1><p>5678</p>';
  599. rng = editor.dom.createRng();
  600. rng.setStart(editor.dom.select('h1')[0].firstChild, 0);
  601. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  602. editor.selection.setRng(rng);
  603. editor.formatter.apply('format');
  604. equals(getContent(), '<blockquote><h1>1234</h1><p>5678</p></blockquote>', 'Block element wrapper 1');
  605. });
  606. test('Block element wrapper 2', function() {
  607. editor.formatter.register('format', {block : 'blockquote', wrapper : 1});
  608. editor.getBody().innerHTML = '<h1>1234</h1>';
  609. rng = editor.dom.createRng();
  610. rng.setStart(editor.dom.select('h1')[0].firstChild, 0);
  611. rng.setEnd(editor.dom.select('h1')[0].firstChild, 4);
  612. editor.selection.setRng(rng);
  613. editor.formatter.apply('format');
  614. equals(getContent(), '<blockquote><h1>1234</h1></blockquote>', 'Block element wrapper 2');
  615. });
  616. test('Block element wrapper 3', function() {
  617. editor.formatter.register('format', {block : 'blockquote', wrapper : 1});
  618. editor.getBody().innerHTML = '<br /><h1>1234</h1><br />';
  619. rng = editor.dom.createRng();
  620. rng.setStart(editor.getBody(), 0);
  621. rng.setEnd(editor.getBody(), 3);
  622. editor.selection.setRng(rng);
  623. editor.formatter.apply('format');
  624. equals(getContent(), '<blockquote><h1>1234</h1></blockquote>', 'Block element wrapper 3');
  625. });
  626. test('Apply format on single element that matches a selector 1', function() {
  627. editor.formatter.register('format', {selector : 'p', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
  628. editor.getBody().innerHTML = '<p>1234</p>';
  629. rng = editor.dom.createRng();
  630. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  631. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  632. editor.selection.setRng(rng);
  633. editor.formatter.apply('format');
  634. equals(getContent(), '<p class="a b c" style="color: #ff0000;" title="test">1234</p>', 'Apply format on single element that matches a selector');
  635. });
  636. test('Apply format on single element parent that matches a selector 2', function() {
  637. editor.formatter.register('format', {selector : 'div', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
  638. editor.getBody().innerHTML = '<div><p>1234</p><p>test</p><p>1234</p></div>';
  639. rng = editor.dom.createRng();
  640. rng.setStart(editor.dom.select('div')[0], 1);
  641. rng.setEnd(editor.dom.select('div')[0], 2);
  642. editor.selection.setRng(rng);
  643. editor.formatter.apply('format');
  644. equals(getContent(), '<div class="a b c" style="color: #ff0000;" title="test"><p>1234</p><p>test</p><p>1234</p></div>', 'Apply format on single element parent that matches a selector');
  645. });
  646. test('Apply format on multiple elements that matches a selector 2', function() {
  647. editor.formatter.register('format', {selector : 'p', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
  648. editor.getBody().innerHTML = '<p>1234</p><div>test</div><p>1234</p>';
  649. rng = editor.dom.createRng();
  650. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  651. rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
  652. editor.selection.setRng(rng);
  653. editor.formatter.apply('format');
  654. equals(getContent(), '<p class="a b c" style="color: #ff0000;" title="test">1234</p><div>test</div><p class="a b c" style="color: #ff0000;" title="test">1234</p>', 'Apply format on multiple elements that matches a selector');
  655. });
  656. test('Apply format on top of existing selector element', function() {
  657. editor.formatter.register('format', {selector : 'p', attributes : {title : 'test2'}, styles : {'color' : '#00ff00'}, classes : 'a b c'});
  658. editor.getBody().innerHTML = '<p class=\"c d\" title=\"test\">1234</p>';
  659. rng = editor.dom.createRng();
  660. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  661. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  662. editor.selection.setRng(rng);
  663. editor.formatter.apply('format');
  664. equals(getContent(), '<p class="c d a b" style="color: #00ff00;" title="test2">1234</p>', 'Apply format on top of existing selector element');
  665. });
  666. test('Format on single li that matches a selector', function() {
  667. editor.formatter.register('format', {inline : 'span', selector : 'li', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
  668. editor.getBody().innerHTML = '<div>text</div>';
  669. rng = editor.dom.createRng();
  670. rng.setStart(editor.dom.select('div')[0], 0);
  671. rng.setEnd(editor.dom.select('div')[0], 1);
  672. editor.selection.setRng(rng);
  673. editor.formatter.apply('format');
  674. equals(getContent(), '<div><span class="a b c" style="color: #ff0000;" title="test">text</span></div>', 'Apply format on single element that matches a selector');
  675. });
  676. test('Format on single div that matches a selector', function() {
  677. editor.formatter.register('format', {inline : 'span', selector : 'div', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
  678. editor.getBody().innerHTML = '<div>text</div>';
  679. rng = editor.dom.createRng();
  680. rng.setStart(editor.dom.select('div')[0], 0);
  681. rng.setEnd(editor.dom.select('div')[0], 1);
  682. editor.selection.setRng(rng);
  683. editor.formatter.apply('format');
  684. equals(getContent(), '<div class="a b c" style="color: #ff0000;" title="test">text</div>', 'Apply format on single element that matches a selector');
  685. });
  686. test('Bold and italics is applied to text that is not highlighted', function() {
  687. rng = editor.dom.createRng();
  688. editor.setContent('<p><span style="font-family: Arial;"><strong>test1 test2</strong> test3 test4 test5 test6</span></p>');
  689. rng.setStart(editor.dom.select('strong')[0].firstChild, 6);
  690. rng.setEnd(editor.dom.select('strong')[0].firstChild, 11);
  691. editor.focus();
  692. editor.selection.setRng(rng);
  693. editor.execCommand('Italic');
  694. equals(editor.getContent(), '<p><span style="font-family: Arial;"><strong>test1 <em>test2</em></strong> test3 test4 test5 test6</span></p>', 'Selected text should be bold.');
  695. });
  696. test('No wrapping of links', function() {
  697. editor.setContent('<p>123<a href="#">abc</a>456</p>');
  698. rng = editor.dom.createRng();
  699. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  700. rng.setEnd(editor.dom.select('p')[0].lastChild, 3);
  701. editor.selection.setRng(rng);
  702. editor.formatter.register('format', {inline : 'span', styles : {color : '#FF0000'}, wrap_links : false});
  703. editor.formatter.apply('format');
  704. equals(editor.getContent(), '<p><span style="color: #ff0000;">123<a href="#"><span style="color: #ff0000;">abc</span></a>456</span></p>', 'Link should have it\'s own span.');
  705. });
  706. test('Color on link element', function() {
  707. editor.setContent('<p><span style="font-size: 10px;">123<a href="#">abc</a>456</span></p>');
  708. rng = editor.dom.createRng();
  709. rng.setStart(editor.dom.select('span')[0].firstChild, 0);
  710. rng.setEnd(editor.dom.select('span')[0].lastChild, 3);
  711. editor.selection.setRng(rng);
  712. editor.formatter.register('format', {inline : 'span', styles : {color : '#FF0000'}, wrap_links : false});
  713. editor.formatter.apply('format');
  714. equals(editor.getContent(), '<p><span style="color: #ff0000; font-size: 10px;">123<a href="#"><span style="color: #ff0000;">abc</span></a>456</span></p>', 'Link should have it\'s own span.');
  715. });
  716. test("Applying formats in lists", function(){
  717. editor.setContent('<ul><li>text<ul><li>nested</li></ul></li></ul>');
  718. rng = editor.dom.createRng();
  719. rng.setStart(editor.dom.select('li')[0].firstChild, 0);
  720. rng.setEnd(editor.dom.select('li')[0].firstChild, 1);
  721. editor.selection.setRng(rng);
  722. editor.formatter.apply("h1");
  723. equals(editor.getContent(), '<ul><li><h1>text</h1><ul><li>nested</li></ul></li></ul>', "heading should not automatically apply to sublists");
  724. });
  725. test('Block format on li element', function() {
  726. editor.setContent('<ul><li>text<ul><li>nested</li></ul></li></ul>');
  727. rng = editor.dom.createRng();
  728. rng.setStart(editor.dom.select('li')[0].firstChild, 0);
  729. rng.setEnd(editor.dom.select('li')[1].firstChild, 1);
  730. editor.selection.setRng(rng);
  731. editor.formatter.apply("h1");
  732. equals(editor.getContent(), '<ul><li><h1>text</h1><ul><li><h1>nested</h1></li></ul></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
  733. });
  734. test('Block on li element 2', function() {
  735. editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
  736. rng = editor.dom.createRng();
  737. rng.setStart(editor.dom.select('li')[0].lastChild, 1);
  738. rng.setEnd(editor.dom.select('li')[0].lastChild, 2);
  739. editor.selection.setRng(rng);
  740. editor.formatter.apply("h1");
  741. equals(editor.getContent(), '<ul><li>before<ul><li>nested</li></ul><h1>after</h1></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
  742. });
  743. test('Block on li element 3', function() {
  744. editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
  745. rng = editor.dom.createRng();
  746. rng.setStart(editor.dom.select('li')[1].firstChild, 0);
  747. rng.setEnd(editor.dom.select('li')[0].lastChild, 1);
  748. editor.selection.setRng(rng);
  749. editor.formatter.apply("h1");
  750. equals(editor.getContent(), '<ul><li>before<ul><li><h1>nested</h1></li></ul><h1>after</h1></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
  751. });
  752. test('Block on li element 4', function() {
  753. editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
  754. rng = editor.dom.createRng();
  755. rng.setStart(editor.dom.select('li')[0].firstChild, 0);
  756. rng.setEnd(editor.dom.select('li')[0].lastChild, 1);
  757. editor.selection.setRng(rng);
  758. editor.formatter.apply("h1");
  759. equals(editor.getContent(), '<ul><li><h1>before</h1><ul><li><h1>nested</h1></li></ul><h1>after</h1></li></ul>', "heading should apply correctly when selection is after a sublist");
  760. });
  761. test('Underline colors 1', function() {
  762. editor.formatter.register('format', {inline: 'span', styles : {'color' : '#ff0000'}});
  763. editor.setContent('<p><span style="font-family: \'arial black\'; text-decoration: underline;">test</span></p>');
  764. editor.execCommand('SelectAll');
  765. editor.formatter.apply('format');
  766. equals(editor.getContent(), '<p><span style="color: #ff0000; font-family: \'arial black\'; text-decoration: underline;">test</span></p>', 'Coloring an underlined text should result in a colored underline');
  767. });
  768. test('Underline colors 2', function() {
  769. editor.formatter.register('format', {inline: "span", exact: true, styles: {'textDecoration' : 'underline'}});
  770. editor.setContent('<p><span style="font-family: \'arial black\'; color: rgb(255, 0, 0);">test</span></p>');
  771. editor.execCommand('SelectAll');
  772. editor.formatter.apply('format');
  773. equals(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="color: #ff0000; font-family: \'arial black\'; text-decoration: underline;">test</span></span></p>', 'Underlining colored text should result in a colored underline');
  774. });
  775. test('Underline colors 3', function() {
  776. editor.formatter.register('format', {inline: "span", exact: true, styles: {'textDecoration' : 'underline'}});
  777. editor.setContent('<p><span style="font-family: \'arial black\'; text-decoration: underline;"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p>');
  778. editor.execCommand('SelectAll');
  779. editor.formatter.apply('format');
  780. equals(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="font-family: \'arial black\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p>', 'Underlining colored and underlined text should result in a colored underline');
  781. });
  782. test('Underline colors 4', function() {
  783. editor.formatter.register('format', {inline: 'span', styles : {'color' : '#ff0000'}});
  784. editor.setContent('<p style="font-size: 22pt;"><span style=\"text-decoration: underline;\"><span style=\"color: yellow; text-decoration: underline;\">yellowredyellow</span></span></p>');
  785. rng = editor.dom.createRng();
  786. rng.setStart(editor.dom.select('span')[1].firstChild, 6);
  787. rng.setEnd(editor.dom.select('span')[1].firstChild, 9);
  788. editor.selection.setRng(rng);
  789. editor.formatter.apply('format');
  790. equals(getContent(), '<p style="font-size: 22pt;"><span style="text-decoration: underline;"><span style="color: yellow; text-decoration: underline;">yellow<span style="color: #ff0000; text-decoration: underline;">red</span>yellow</span></span></p>', 'Coloring an colored underdlined text should result in newly colored underline');
  791. });
  792. test('Underline colors 5', function() {
  793. editor.formatter.register('format', {inline: "span", exact: true, styles: {'textDecoration' : 'underline'}});
  794. editor.setContent('<p><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p><p><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p><p><span style="font-family: \'arial black\', \'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p>');
  795. rng = editor.dom.createRng();
  796. rng.setStart(editor.dom.select('strong')[0].firstChild, 0);
  797. rng.setEnd(editor.dom.select('span')[4].lastChild, 5);
  798. editor.selection.setRng(rng);
  799. editor.formatter.apply('format');
  800. equals(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p><p><span style="text-decoration: underline;"><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p><p><span style="text-decoration: underline;"><span style="font-family: \'arial black\', \'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p>', 'Colored elements should be underlined when selection is across multiple paragraphs');
  801. });
  802. test('Underline colors 6', function() {
  803. editor.formatter.register('format', {inline: 'span', exact: true, styles : {'color' : '#ff0000'}});
  804. editor.setContent('<p><span style="text-decoration: underline;">This is some text.</span></p>');
  805. rng = editor.dom.createRng();
  806. rng.setStart(editor.dom.select('span')[0].firstChild, 8);
  807. rng.setEnd(editor.dom.select('span')[0].firstChild, 12);
  808. editor.selection.setRng(rng);
  809. editor.formatter.apply('format');
  810. editor.formatter.remove('format');
  811. equals(editor.getContent(), '<p><span style="text-decoration: underline;">This is some text.</span></p>', 'Children nodes that are underlined should be removed if their parent nodes are underlined');
  812. });
  813. test('Underline colors 7', function() {
  814. editor.formatter.register('format', {inline: 'span', exact: true, styles : {'color' : '#ff0000'}});
  815. editor.setContent('<p><span style="text-decoration: underline;">This is <span style="color: #ff0000; text-decoration: underline; background-color: #ff0000">some</span> text.</span></p>');
  816. rng = editor.dom.createRng();
  817. rng.setStart(editor.dom.select('span')[1].firstChild, 0);
  818. rng.setEnd(editor.dom.select('span')[1].firstChild, 4);
  819. editor.selection.setRng(rng);
  820. editor.formatter.remove('format');
  821. equals(editor.getContent(), '<p><span style=\"text-decoration: underline;\">This is <span style=\"background-color: #ff0000;\">some</span> text.</span></p>', 'Children nodes that are underlined should be removed if their parent nodes are underlined');
  822. });
  823. test('Caret format inside single block word', function() {
  824. editor.setContent('<p>abc</p>');
  825. editor.formatter.register('format', {inline: 'b'});
  826. setSelection('p', 2, 'p', 2);
  827. editor.formatter.apply('format');
  828. equals(editor.getContent(), '<p><b>abc</b></p>');
  829. });
  830. test('Caret format inside first block word', function() {
  831. editor.setContent('<p>abc 123</p>');
  832. editor.formatter.register('format', {inline: 'b'});
  833. setSelection('p', 2, 'p', 2);
  834. editor.formatter.apply('format');
  835. equals(editor.getContent(), '<p><b>abc</b> 123</p>');
  836. });
  837. test('Caret format inside last block word', function() {
  838. editor.setContent('<p>abc 123</p>');
  839. editor.formatter.register('format', {inline: 'b'});
  840. setSelection('p', 5, 'p', 5);
  841. editor.formatter.apply('format');
  842. equals(editor.getContent(), '<p>abc <b>123</b></p>');
  843. });
  844. test('Caret format inside middle block word', function() {
  845. editor.setContent('<p>abc 123 456</p>');
  846. editor.formatter.register('format', {inline: 'b'});
  847. setSelection('p', 5, 'p', 5);
  848. editor.formatter.apply('format');
  849. equals(editor.getContent(), '<p>abc <b>123</b> 456</p>');
  850. });
  851. test('Caret format on word separated by non breaking space', function() {
  852. editor.setContent('<p>one&nbsp;two</p>');
  853. editor.formatter.register('format', {inline: 'b'});
  854. setSelection('p', 1, 'p', 1);
  855. editor.formatter.apply('format');
  856. equals(editor.getContent(), '<p><b>one</b>\u00a0two</p>');
  857. });
  858. test('Caret format inside single inline wrapped word', function() {
  859. editor.setContent('<p>abc <em>123</em> 456</p>');
  860. editor.formatter.register('format', {inline: 'b'});
  861. setSelection('em', 1, 'em', 1);
  862. editor.formatter.apply('format');
  863. equals(editor.getContent(), '<p>abc <b><em>123</em></b> 456</p>');
  864. });
  865. test('Caret format inside last inline wrapped word', function() {
  866. editor.setContent('<p>abc <em>abc 123</em> 456</p>');
  867. editor.formatter.register('format', {inline: 'b'});
  868. setSelection('em', 5, 'em', 5);
  869. editor.formatter.apply('format');
  870. equals(editor.getContent(), '<p>abc <em>abc <b>123</b></em> 456</p>');
  871. });
  872. test('Caret format before text', function() {
  873. editor.setContent('<p>a</p>');
  874. editor.formatter.register('format', {inline: 'b'});
  875. setSelection('p', 0, 'p', 0);
  876. editor.formatter.apply('format');
  877. type('b');
  878. equals(editor.getContent(), '<p><b>b</b>a</p>');
  879. });
  880. test('Caret format after text', function() {
  881. editor.setContent('<p>a</p>');
  882. editor.formatter.register('format', {inline: 'b'});
  883. setSelection('p', 1, 'p', 1);
  884. editor.formatter.apply('format');
  885. type('b');
  886. equals(editor.getContent(), '<p>a<b>b</b></p>');
  887. });
  888. test('Caret format and no key press', function() {
  889. editor.setContent('<p>a</p>');
  890. editor.formatter.register('format', {inline: 'b'});
  891. setSelection('p', 0, 'p', 0);
  892. editor.formatter.apply('format');
  893. equals(editor.getContent(), '<p>a</p>');
  894. });
  895. test('Caret format and arrow left', function() {
  896. editor.setContent('<p>a</p>');
  897. editor.formatter.register('format', {inline: 'b'});
  898. setSelection('p', 0, 'p', 0);
  899. editor.formatter.apply('format');
  900. type({keyCode: 37});
  901. equals(editor.getContent(), '<p>a</p>');
  902. });
  903. test('Caret format and arrow right', function() {
  904. editor.setContent('<p>a</p>');
  905. editor.formatter.register('format', {inline: 'b'});
  906. setSelection('p', 0, 'p', 0);
  907. editor.formatter.apply('format');
  908. type({keyCode: 39});
  909. equals(editor.getContent(), '<p>a</p>');
  910. });
  911. test('Caret format and backspace', function() {
  912. var rng;
  913. if (tinymce.isOpera) {
  914. ok(true, "Skip Opera since faking backspace doesn't work.");
  915. return;
  916. }
  917. editor.formatter.register('format', {inline: 'b'});
  918. editor.setContent('<p>abc</p>');
  919. rng = editor.dom.createRng();
  920. rng.setStart(editor.dom.select('p')[0].firstChild, 3);
  921. rng.setEnd(editor.dom.select('p')[0].firstChild, 3);
  922. editor.selection.setRng(rng);
  923. editor.formatter.apply('format');
  924. type('\b');
  925. equals(editor.getContent(), '<p>ab</p>');
  926. });
  927. test('Caret format on word in li with word in parent li before it', function() {
  928. editor.setContent('<ul><li>one<ul><li>two</li></ul></li></ul>');
  929. editor.formatter.register('format', {inline: 'b'});
  930. setSelection('ul li li', 1, 'ul li li', 1);
  931. editor.formatter.apply('format');
  932. equals(editor.getContent(), '<ul><li>one<ul><li><b>two</b></li></ul></li></ul>');
  933. });
  934. /*
  935. test('apply (list block)', function() {
  936. var rng;
  937. // Ordered list on selected paragraph text
  938. editor.getBody().innerHTML = '<p>1234</p>';
  939. rng = editor.dom.createRng();
  940. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  941. rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
  942. editor.selection.setRng(rng);
  943. editor.formatter.apply({list_block : 'ol', replace : 'ul', list_item : 'li'});
  944. equals(getContent(), '<ol><li>1234</li></ol>', 'Ordered list on paragraph text');
  945. // Ordered list on the text of two selected paragraphs
  946. editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
  947. rng = editor.dom.createRng();
  948. rng.setStart(editor.dom.select('p')[0].firstChild, 0);
  949. r